#include #include #include #include #include #include #include #include #include #include #include #include #include constexpr int kVecSize = 1 << 16; // Copy-pasted from ggml.c #define QK4_0 32 typedef struct { float d; // delta uint8_t qs[QK4_0 / 2]; // nibbles / quants } block_q4_0; static_assert(sizeof(block_q4_0) == sizeof(float) + QK4_0 / 2, "wrong q4_0 block size/padding"); #define QK4_1 32 typedef struct { float d; // delta float m; // min uint8_t qs[QK4_1 / 2]; // nibbles / quants } block_q4_1; static_assert(sizeof(block_q4_1) == sizeof(float) * 2 + QK4_1 / 2, "wrong q4_1 block size/padding"); // Copy-pasted from ggml.c #define QK8_0 32 typedef struct { float d; // delta float s; // d * sum(qs[i]) int8_t qs[QK8_0]; // quants } block_q8_0; static_assert(sizeof(block_q8_0) == 2*sizeof(float) + QK8_0, "wrong q8_0 block size/padding"); static_assert(QK4_1 == QK8_0, "QK4_1 and QK8_0 must be the same"); static_assert(QK4_0 == QK8_0, "QK4_0 and QK8_0 must be the same"); template static void fillQ4blocks(std::vector& blocks, std::mt19937& rndm) { for (auto& b : blocks) { b.d = 1; for (int i=0; i> 28; uint8_t v2 = rndm() >> 28; b.qs[i] = v1 | (v2 << 4); } } } static void fillQ80blocks(std::vector& blocks, std::mt19937& rndm) { for (auto& b : blocks) { b.d = 1; int sum = 0; for (int i=0; i> 24) - 128; sum += b.qs[i]; } b.s = b.d * sum; } } static float simpleDot(const block_q4_0& x, const block_q8_0& y) { int s1 = 0; //, s2 = 0; for (int i=0; i> 4; int v3 = x.qs[i+1] & 0xf; int v4 = x.qs[i+1] >> 4; int j = 2*i; s1 += v1*y.qs[j] + v2*y.qs[j+1] + v3*y.qs[j+2] + v4*y.qs[j+3]; //s2 += y.qs[j] + y.qs[j+1] + y.qs[j+2] + y.qs[j+3]; } return y.d * x.d * s1 - 8 * x.d * y.s; //return y.d * x.d * (s1 - 8 * s2); } static float simpleDot(const block_q4_1& x, const block_q8_0& y) { int s1 = 0; //, s2 = 0; for (int i=0; i> 4; int v3 = x.qs[i+1] & 0xf; int v4 = x.qs[i+1] >> 4; int j = 2*i; s1 += v1*y.qs[j] + v2*y.qs[j+1] + v3*y.qs[j+2] + v4*y.qs[j+3]; //s2 += y.qs[j] + y.qs[j+1] + y.qs[j+2] + y.qs[j+3]; } return y.d * x.d * s1 + y.s * x.m; //return y.d * (x.d * s1 + x.m * s2); } struct Stat { double sum = 0, sumt = 0, sumt2 = 0, maxt = 0; int nloop = 0; void addResult(double s, double t) { sum += s; sumt += t; sumt2 += t*t; maxt = std::max(maxt, t); ++nloop; } void reportResult(const char* title) const { if (nloop < 1) { printf("%s(%s): no result\n",__func__,title); return; } printf("============ %s\n",title); printf(" = %g\n",sum/nloop); auto t = sumt/nloop, dt = sumt2/nloop - t*t; if (dt > 0) dt = sqrt(dt); printf("