/* Phase 2b: RMSNorm in C, validated against Python ref. * RMSNorm(x)[i] = x[i] * rsqrt(mean(x^2)+eps) * weight[i] (per row, over dim=6144) * Build: gcc -O2 -o phase2b_rmsnorm phase2b_rmsnorm.c -lm */ #include #include #include #define DIM 6144 #define ROWS 5 #define EPS 1e-5f static float* load_f32(const char* path, long n) { FILE* f = fopen(path, "rb"); if (!f) { perror(path); exit(1); } float* buf = malloc(n * sizeof(float)); if (fread(buf, sizeof(float), n, f) != (size_t)n) { fprintf(stderr, "short read %s\n", path); exit(1); } fclose(f); return buf; } int main(void) { const char* D = "ref"; char p[512]; snprintf(p, sizeof p, "%s/norm_in.f32", D); float* x = load_f32(p, ROWS * DIM); snprintf(p, sizeof p, "%s/norm_weight.f32", D); float* w = load_f32(p, DIM); snprintf(p, sizeof p, "%s/norm_out.f32", D); float* ref = load_f32(p, ROWS * DIM); float* out = malloc(ROWS * DIM * sizeof(float)); for (int r = 0; r < ROWS; r++) { const float* xr = x + r * DIM; double ss = 0.0; for (int i = 0; i < DIM; i++) ss += (double)xr[i] * xr[i]; float inv = 1.0f / sqrtf((float)(ss / DIM) + EPS); for (int i = 0; i < DIM; i++) out[r * DIM + i] = xr[i] * inv * w[i]; } /* validate against Python ref */ double max_abs = 0.0; long worst = 0; for (long i = 0; i < (long)ROWS * DIM; i++) { double d = fabs((double)out[i] - ref[i]); if (d > max_abs) { max_abs = d; worst = i; } } printf("C RMSNorm out[0..8]: "); for (int i = 0; i < 8; i++) printf("%.4f ", out[i]); printf("\nmax abs diff vs Python ref: %.3e (at idx %ld)\n", max_abs, worst); printf("VERDICT: %s\n", max_abs < 1e-4 ? "PASS — RMSNorm matches Python" : "FAIL"); return max_abs < 1e-4 ? 0 : 1; }