71 lines
3.2 KiB
C++
71 lines
3.2 KiB
C++
// Validation : mon cp_inference (intégré dans tts_orchestrate) doit reproduire
|
|
// cp_runner standalone bit-exact. Sur test_cp_input.bin (33 frames hidden+CB0
|
|
// du Talker PyTorch) → comparer codes CB1..15 vs test_codes_greedy.bin
|
|
// (golden cp.generate do_sample=False). Cible : 33/33 frames parfaits.
|
|
#include "cp_inference.h"
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <cstdint>
|
|
#include <vector>
|
|
#include <string>
|
|
|
|
int main(int argc, char** argv) {
|
|
if (argc < 6) {
|
|
printf("usage: %s <cp_gguf> <cp_heads.bin> <cp_codec_embs.bin> <test_cp_input.bin> <golden.bin>\n", argv[0]);
|
|
return 1;
|
|
}
|
|
CPState s; s.n_threads = 4;
|
|
if (!cp_load(s, argv[1], argv[2], argv[3])) { printf("cp_load FAILED\n"); return 1; }
|
|
|
|
// input : int32 T, T * (hidden[1024] + cb0_emb[1024]) f32
|
|
FILE* fi = fopen(argv[4], "rb"); if (!fi) { printf("input fail\n"); return 1; }
|
|
int32_t T = 0; if (fread(&T, 4, 1, fi) != 1) return 1;
|
|
std::vector<float> inbuf((size_t)T * 2 * 1024);
|
|
if (fread(inbuf.data(), sizeof(float), inbuf.size(), fi) != inbuf.size()) return 1;
|
|
fclose(fi);
|
|
|
|
// golden : pour test_codes_greedy.bin pas de header (T * 16 int32 direct, 33 * 16 * 4 = 2112 bytes ≈ 2116)
|
|
FILE* fg = fopen(argv[5], "rb"); if (!fg) return 1;
|
|
fseek(fg, 0, SEEK_END); long gsz = ftell(fg); fseek(fg, 0, SEEK_SET);
|
|
// 2 layouts possibles : (a) header int32+T*16 int32 (size = 4 + T*64),
|
|
// (b) raw T*16 int32 (size = T*64). On déduit.
|
|
bool has_hdr = (gsz == 4 + (long)T * 64);
|
|
if (has_hdr) { int32_t ng = 0; fread(&ng, 4, 1, fg); printf("golden has header, ng=%d\n", ng); }
|
|
std::vector<int32_t> gold((size_t)T * 16);
|
|
size_t expect = T * 16;
|
|
if (fread(gold.data(), sizeof(int32_t), expect, fg) != expect) {
|
|
// Maybe golden has fewer or different format
|
|
printf("golden short read; size %ld, expected %zu*4=%zu bytes (T=%d)\n", gsz, expect, expect*4, T);
|
|
fclose(fg); return 1;
|
|
}
|
|
fclose(fg);
|
|
|
|
printf("running CP on %d frames...\n", T);
|
|
long n_match_cb15 = 0, total_codes_cb15 = 0;
|
|
int n_perfect_cb15 = 0;
|
|
for (int f = 0; f < T; f++) {
|
|
const float* hidden = &inbuf[(size_t)f * 2 * 1024];
|
|
const float* cb0_emb = &inbuf[(size_t)f * 2 * 1024 + 1024];
|
|
int32_t codes15[15];
|
|
cp_predict(s, hidden, cb0_emb, codes15);
|
|
|
|
// golden format = [CB0 ... CB15] (16 entries per frame)
|
|
const int32_t* gf16 = &gold[(size_t)f * 16];
|
|
int match = 0;
|
|
for (int c = 0; c < 15; c++) if (codes15[c] == gf16[1 + c]) match++;
|
|
n_match_cb15 += match; total_codes_cb15 += 15;
|
|
if (match == 15) n_perfect_cb15++;
|
|
if (f < 3 || match < 15) {
|
|
printf("frame %2d: CB1..15 match %2d/15 -> CP=[%d,%d,%d,%d] PY=[%d,%d,%d,%d]\n",
|
|
f, match, codes15[0], codes15[1], codes15[2], codes15[3],
|
|
gf16[1], gf16[2], gf16[3], gf16[4]);
|
|
}
|
|
}
|
|
printf("\n=== cp_predict (engine) vs cp.generate greedy (golden) ===\n");
|
|
printf("codes match : %ld/%ld (%.1f%%)\n", n_match_cb15, total_codes_cb15, 100.0 * n_match_cb15 / total_codes_cb15);
|
|
printf("frames parfaits : %d/%d\n", n_perfect_cb15, T);
|
|
cp_free(s);
|
|
return (n_match_cb15 == total_codes_cb15) ? 0 : 5;
|
|
}
|