/* Microbenchmark: old (single-accumulator) vs new (independent-accumulator) AVX-VNNI * int8/int4 dot kernels (quant.h). NOT a unit test -- test_idot.c proves correctness. * This measures the headline claim: breaking the serial vpdpbusd->acc chain lifts * per-core kernel throughput, the same win the NEON path already took ("26->63 GB/s, 2.4x"). * * It re-implements the OLD single-acc AVX-VNNI kernels inline and calls the REAL (new) * ones via the include-colibri.c pattern -- one process, identical frozen inputs, warm * caches. Reports median ns/call + GB/s-of-weights + new/old ratio. Measures the kernel's * compute ceiling (warm caches), NOT end-to-end tok/s. * * Run: make tests/bench_idot ARCH=native && ./tests/bench_idot (not in TEST_BINS -- not a gate) */ #define main coli_glm_main_unused #include "../colibri.c" #undef main #include #include static uint32_t rs=0x2545F491u; static uint32_t xr(void){ rs^=rs<<13; rs^=rs>>17; rs^=rs<<5; return rs; } /* ---- OLD kernels: verbatim copies of the pre-change __AVXVNNI__ branches (single acc) ---- */ #if defined(__AVXVNNI__) && defined(__AVX2__) static int32_t dot_i8i8_old(const int8_t *w, const int8_t *x, int I){ int32_t sum=0; int i=0; __m128i acc=_mm_setzero_si128(); for(;i+16<=I;i+=16){ __m128i wv=_mm_loadu_si128((const __m128i*)(w+i)); __m128i xv=_mm_loadu_si128((const __m128i*)(x+i)); __m128i xs=_mm_sign_epi8(xv,wv); acc=_mm_dpbusd_epi32(acc,_mm_abs_epi8(wv),xs); } sum=hsum128_i32(acc); for(;i>1))); __m128i lo=_mm_and_si128(by,m4), hi=_mm_and_si128(_mm_srli_epi16(by,4),m4); __m128i n0=_mm_unpacklo_epi8(lo,hi), n1=_mm_unpackhi_epi8(lo,hi); __m128i w0=_mm_sub_epi8(n0,b8), w1=_mm_sub_epi8(n1,b8); __m128i x0=_mm_loadu_si128((const __m128i*)(x+i)); __m128i x1=_mm_loadu_si128((const __m128i*)(x+i+16)); acc=_mm_dpbusd_epi32(acc,_mm_abs_epi8(w0),_mm_sign_epi8(x0,w0)); acc=_mm_dpbusd_epi32(acc,_mm_abs_epi8(w1),_mm_sign_epi8(x1,w1)); } sum=hsum128_i32(acc); for(;i>1]; int v=(i&1)?((int)(b>>4)-8):((int)(b&0xF)-8); sum+=v*x[i]; } return sum; } #else #error "bench_idot requires an AVX-VNNI build: make tests/bench_idot ARCH=native on an AVX-VNNI CPU" #endif #define I_DIM 6144 #define N_REPEAT 20000 static int cmp_d(const void*a,const void*b){ double x=*(const double*)a,y=*(const double*)b; return xy?1:0; } int main(void){ static int8_t w8[I_DIM], x8[I_DIM]; static uint8_t w4[I_DIM/2]; for(int i=0;i