Organize project tools and local workflows: c/tools, c/scripts, c/tests, root Makefile (flat C core untouched) (#22)
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
#include "../backend_cuda.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
|
||||
static int close_enough(const float *got, const float *want, int n) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (std::fabs(got[i] - want[i]) > 1e-4f) {
|
||||
std::fprintf(stderr, "mismatch %d: got %.6f want %.6f\n", i, got[i], want[i]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int devices[COLI_CUDA_MAX_DEVICES], ndev = argc > 1 ? argc - 1 : 1;
|
||||
if (ndev > COLI_CUDA_MAX_DEVICES) return 2;
|
||||
for (int i = 0; i < ndev; i++) devices[i] = argc > 1 ? std::atoi(argv[i + 1]) : 0;
|
||||
if (!coli_cuda_init(devices, ndev)) return 77;
|
||||
if (coli_cuda_device_count() != ndev) return 1;
|
||||
int d0 = devices[0], d1 = devices[ndev > 1 ? 1 : 0];
|
||||
size_t count = 99, bytes = 99;
|
||||
coli_cuda_stats(-1, &count, &bytes);
|
||||
if (count || bytes) return 1;
|
||||
const float x[8] = {1, -2, 3, -4, 2, 1, -1, 0.5f};
|
||||
float got[4];
|
||||
|
||||
const int8_t q8[8] = {1, 2, 3, 4, -1, 2, -3, 4};
|
||||
const float s8[2] = {0.5f, 2.0f};
|
||||
const float want8[4] = {-5.0f, -60.0f, 1.5f, 10.0f};
|
||||
ColiCudaTensor *t8 = nullptr;
|
||||
if (!coli_cuda_tensor_upload(&t8, q8, s8, 1, 4, 2, d0)) return 1;
|
||||
if (coli_cuda_tensor_upload(&t8, q8, s8, 1, 5, 2, d0)) return 1;
|
||||
if (ndev > 1 && coli_cuda_tensor_upload(&t8, q8, s8, 1, 4, 2, d1)) return 1;
|
||||
if (!coli_cuda_matmul(&t8, got, x, q8, s8, 1, 2, 4, 2, d0) || !close_enough(got, want8, 4)) return 1;
|
||||
|
||||
/* Rows [-8,-1,0,7] and [1,2,3,4], packed low nibble first. */
|
||||
const uint8_t q4[4] = {0x70, 0xf8, 0xa9, 0xcb};
|
||||
const float s4[2] = {1.0f, 0.25f};
|
||||
const float want4[2] = {-34.0f, -2.5f};
|
||||
ColiCudaTensor *t4 = nullptr;
|
||||
if (!coli_cuda_matmul(&t4, got, x, q4, s4, 2, 1, 4, 2, d1) || !close_enough(got, want4, 2)) return 1;
|
||||
|
||||
const uint8_t q2[2] = {0xe4, 0x1b};
|
||||
const float s2[2] = {0.5f, 2.0f};
|
||||
const float want2[2] = {-2.0f, 12.0f};
|
||||
ColiCudaTensor *t2 = nullptr;
|
||||
if (!coli_cuda_matmul(&t2, got, x, q2, s2, 3, 1, 4, 2, d1) || !close_enough(got, want2, 2)) return 1;
|
||||
|
||||
const float wf[8] = {1, 0, -1, 2, 0.5f, 0.5f, 0.5f, 0.5f};
|
||||
const float wantf[2] = {-10.0f, -1.0f};
|
||||
ColiCudaTensor *tf = nullptr;
|
||||
if (!coli_cuda_matmul(&tf, got, x, wf, nullptr, 0, 1, 4, 2, d0) || !close_enough(got, wantf, 2)) return 1;
|
||||
|
||||
coli_cuda_stats(-1, &count, &bytes);
|
||||
if (count != 4 || bytes != 70) {
|
||||
std::fprintf(stderr, "unexpected CUDA stats: %zu tensors, %zu bytes\n", count, bytes);
|
||||
return 1;
|
||||
}
|
||||
if (coli_cuda_tensor_device(t8) != d0 || coli_cuda_tensor_device(tf) != d0 ||
|
||||
coli_cuda_tensor_device(t4) != d1 || coli_cuda_tensor_device(t2) != d1) return 1;
|
||||
coli_cuda_stats(d0, &count, &bytes);
|
||||
if (ndev > 1) {
|
||||
if (count != 2 || bytes != 48) return 1;
|
||||
coli_cuda_stats(d1, &count, &bytes);
|
||||
if (count != 2 || bytes != 22) return 1;
|
||||
} else if (count != 4 || bytes != 70) return 1;
|
||||
|
||||
coli_cuda_tensor_free(t8);
|
||||
coli_cuda_tensor_free(t4);
|
||||
coli_cuda_tensor_free(t2);
|
||||
coli_cuda_tensor_free(tf);
|
||||
coli_cuda_stats(-1, &count, &bytes);
|
||||
if (count || bytes) return 1;
|
||||
coli_cuda_shutdown();
|
||||
std::printf("cuda backend: q8/q4/q2/f32 correctness ok on %d device(s)\n", ndev);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import unittest
|
||||
|
||||
from benchmark_cuda_fixture import parse_output
|
||||
from tools.benchmark_cuda_fixture import parse_output
|
||||
|
||||
|
||||
SAMPLE = """
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/* Validazione del tokenizer C contro l'oracolo HF.
|
||||
* build da c/: gcc -O2 tests/test_tok.c -o tok_test
|
||||
* uso: ./tok_test <tokenizer.json> (legge righe "TEXT\tID,ID,.." da stdin) */
|
||||
#define _GNU_SOURCE
|
||||
#include "../tok.h"
|
||||
|
||||
int main(int argc, char **argv){
|
||||
if(argc<2){ fprintf(stderr,"uso: %s tokenizer.json < casi\n",argv[0]); return 1; }
|
||||
Tok T;
|
||||
tok_load(&T, argv[1]);
|
||||
fprintf(stderr,"caricato: vocab_ids=%d specials=%d\n", T.n_ids, T.nsp);
|
||||
char *line=NULL; size_t cap=0; ssize_t nr;
|
||||
int pass=0, tot=0, dpass=0;
|
||||
while((nr=getline(&line,&cap,stdin))>=0){
|
||||
if(nr>0 && line[nr-1]=='\n'){ line[--nr]=0; }
|
||||
if(nr==0) continue;
|
||||
char *tab=strchr(line,'\t'); if(!tab) continue;
|
||||
*tab=0; const char *text=line; const char *idstr=tab+1;
|
||||
/* il testo puo' contenere \n e \t codificati come \\n \\t */
|
||||
char tbuf[4096]; int tn=0;
|
||||
for(const char *q=text; *q && tn<4095; q++){
|
||||
if(q[0]=='\\' && q[1]=='n'){ tbuf[tn++]='\n'; q++; }
|
||||
else if(q[0]=='\\' && q[1]=='t'){ tbuf[tn++]='\t'; q++; }
|
||||
else if(q[0]=='\\' && q[1]=='r'){ tbuf[tn++]='\r'; q++; }
|
||||
else if(q[0]=='\\' && q[1]=='\\'){ tbuf[tn++]='\\'; q++; }
|
||||
else tbuf[tn++]=*q;
|
||||
}
|
||||
tbuf[tn]=0;
|
||||
int exp[4096], ne=0;
|
||||
for(const char *q=idstr; *q; ){ while(*q==','||*q==' ')q++; if(!*q)break; exp[ne++]=atoi(q); while(*q&&*q!=',')q++; }
|
||||
int got[4096]; int ng=tok_encode(&T,tbuf,tn,got,4096);
|
||||
int ok = (ng==ne); for(int i=0;i<ng&&ok;i++) ok = (got[i]==exp[i]);
|
||||
tot++; if(ok) pass++;
|
||||
/* round-trip decode */
|
||||
char dec[8192]; int dn=tok_decode(&T,got,ng,dec,8191);
|
||||
int drt = (dn==tn) && !memcmp(dec,tbuf,tn);
|
||||
if(drt) dpass++;
|
||||
if(!ok || !drt){
|
||||
fprintf(stderr,"MISMATCH text=%s\n exp(%d):",text,ne); for(int i=0;i<ne;i++)fprintf(stderr," %d",exp[i]);
|
||||
fprintf(stderr,"\n got(%d):",ng); for(int i=0;i<ng;i++)fprintf(stderr," %d",got[i]);
|
||||
fprintf(stderr,"\n decode_ok=%d\n", drt);
|
||||
}
|
||||
}
|
||||
printf("ENCODE: %d/%d DECODE(round-trip): %d/%d\n", pass,tot, dpass,tot);
|
||||
return pass==tot ? 0 : 2;
|
||||
}
|
||||
Reference in New Issue
Block a user