// 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 #include #include #include #include #include int main(int argc, char** argv) { if (argc < 6) { printf("usage: %s \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 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 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; }