flint_cpu_opt / benchmarks /nvfp4 /test_nvfp4.c
HelloSun's picture
Add NVFP4 CPU kernels results, integrate model card, add handoff
45f1d0b verified
Raw History Blame Contribute Delete
2.34 kB
// Compare ggml_vec_dot_nvfp4_q8_0 (arch path) against ggml_vec_dot_nvfp4_q8_0_generic on random data.
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stddef.h>
typedef struct { uint8_t d[4]; uint8_t qs[32]; } block_nvfp4; // 64 elems: 4 UE4M3 scales + 32 nibble bytes
typedef struct { _Float16 d; int8_t qs[32]; } block_q8_0; // 32 elems
void ggml_vec_dot_nvfp4_q8_0(int n, float * s, size_t bs, const void * vx, size_t bx, const void * vy, size_t by, int nrc);
void ggml_vec_dot_nvfp4_q8_0_generic(int n, float * s, size_t bs, const void * vx, size_t bx, const void * vy, size_t by, int nrc);
static uint32_t rng_state = 12345;
static uint32_t rnd(void) { rng_state = rng_state * 1664525u + 1013904223u; return rng_state >> 8; }
void ggml_cpu_init(void);
int main(void) {
ggml_cpu_init();
int fails = 0;
for (int trial = 0; trial < 20; ++trial) {
const int n = 64 * (1 + (trial * 37) % 200);
const int nb = n / 64;
block_nvfp4 * w = aligned_alloc(64, sizeof(block_nvfp4) * nb);
block_q8_0 * a = aligned_alloc(64, sizeof(block_q8_0) * (n / 32));
for (int i = 0; i < nb; ++i) {
for (int s = 0; s < 4; ++s) w[i].d[s] = (uint8_t)(rnd() % 127); // avoid NaN code 0x7F
for (int j = 0; j < 32; ++j) w[i].qs[j] = (uint8_t)rnd();
}
for (int i = 0; i < n / 32; ++i) {
float amax = 0.f; float xs[32];
for (int j = 0; j < 32; ++j) { xs[j] = ((int)(rnd() % 20001) - 10000) / 1000.0f; if (fabsf(xs[j]) > amax) amax = fabsf(xs[j]); }
float d = amax / 127.0f; float id = d ? 1.0f / d : 0.0f;
a[i].d = (_Float16) d;
for (int j = 0; j < 32; ++j) a[i].qs[j] = (int8_t) lrintf(xs[j] * id);
}
float r_gen = 0.f, r_arch = 0.f;
ggml_vec_dot_nvfp4_q8_0_generic(n, &r_gen, 0, w, 0, a, 0, 1);
ggml_vec_dot_nvfp4_q8_0(n, &r_arch, 0, w, 0, a, 0, 1);
double rel = fabs((double) r_arch - r_gen) / (fabs((double) r_gen) + 1e-9);
printf("n=%6d generic=% .6f arch=% .6f rel=%.3e %s\n", n, r_gen, r_arch, rel, rel < 1e-5 ? "OK" : "FAIL");
if (rel >= 1e-5) fails++;
free(w); free(a);
}
printf("%s (%d failures)\n", fails ? "FAILED" : "PASSED", fails);
return fails != 0;
}