// 用 ggml 自己的 dequantize 抽出一列權重,給 Python 端做「逐位元組」對照。 // // 用途:verify_moe_dsv4.py 裡的 IQ3_S / MXFP4 dequant 是照著 ggml 原始碼手寫的 // NumPy 版本。這支工具提供**獨立**的第二份實作(直接呼叫 ggml 的 C 函式), // 兩者必須逐位元組相同 —— 否則後面所有「SDQ kernel 對得上 NumPy」的結論 // 都只是在一份錯誤的 reference 上自我一致。 // // build(對 SDQ 那份 llama.cpp build 目錄): // c++ -O2 -o ggml_deq ggml_deq.cpp \ // -I/ggml/include -I/ggml/src \ // -L/build/bin -lggml-base -Wl,-rpath,/build/bin // // 用法:ggml_deq → stdout 印 n 個 float // type: 21 = IQ3_S, 39 = MXFP4, 8 = Q8_0, 12 = Q4_K, 13 = Q5_K, 7 = Q5_1 #include "ggml.h" #include "ggml-quants.h" // ggml/src/ggml-quants.h(block_iq3_s / block_mxfp4 定義) #include #include #include int main(int argc, char ** argv) { if (argc < 5) { fprintf(stderr, "usage: %s \n", argv[0]); return 1; } const int tt = atoi(argv[1]); const char * path = argv[2]; const long long off = atoll(argv[3]); const int n = atoi(argv[4]); FILE * f = fopen(path, "rb"); if (!f) { perror("open"); return 1; } const size_t ts = ggml_row_size((ggml_type) tt, n); void * buf = malloc(ts); if (fseek(f, (long) off, SEEK_SET) != 0) { perror("seek"); return 1; } if (fread(buf, 1, ts, f) != ts) { fprintf(stderr, "short read\n"); return 1; } fclose(f); float * y = (float *) malloc(sizeof(float) * (size_t) n); switch (tt) { case 21: dequantize_row_iq3_s((const block_iq3_s *) buf, y, n); break; case 39: dequantize_row_mxfp4((const block_mxfp4 *) buf, y, n); break; case 12: dequantize_row_q4_K ((const block_q4_K *) buf, y, n); break; case 13: dequantize_row_q5_K ((const block_q5_K *) buf, y, n); break; case 7: dequantize_row_q5_1((const block_q5_1 *) buf, y, n); break; case 8: dequantize_row_q8_0((const block_q8_0 *) buf, y, n); break; default: fprintf(stderr, "type %d not handled\n", tt); return 1; } fwrite(y, sizeof(float), (size_t) n, stdout); free(y); free(buf); return 0; }