666db68matmul-bench: browser GEMM benchmark (JS, WebGPU, custom C WASM, libFLAME/BLIS WASM)Jeremy Magland 1/*
2 * Native dgemm benchmark, for a reference point outside the browser.
3 * Same flop-count and timing convention as the browser benchmarks.
4 *
5 * ./build.sh
6 * OPENBLAS_NUM_THREADS=1 ./bench_native 128 256 512 1024 2048
7 * OPENBLAS_NUM_THREADS=$(nproc) ./bench_native 128 256 512 1024 2048
8 */
14extern void dgemm_( const char* transa, const char* transb, const int* m,
15 const int* n, const int* k, const double* alpha,
16 const double* a, const int* lda, const double* b,
17 const int* ldb, const double* beta, double* c,
18 const int* ldc );
20static double now_sec( void )
21{
22 struct timespec ts;
23 clock_gettime( CLOCK_MONOTONIC, &ts );
24 return ts.tv_sec + 1e-9 * ts.tv_nsec;
25}
27/* Same deterministic PRNG as the browser methods, for an identical checksum. */
28static unsigned long long rng_state = 12345;
29static double frand( void )
30{
31 rng_state = rng_state * 6364136223846793005ULL + 1442695040888963407ULL;
32 return ( ( rng_state >> 33 ) & 0xffffff ) / (double) 0x1000000 - 0.5;
33}
35static void fill_random( double* a, int n2 )
36{
37 rng_state = 12345;
38 for ( int i = 0; i < n2; i++ ) a[i] = frand();
39}
41static void bench_dgemm( int n )
42{
43 double *a = malloc( (size_t)n * n * sizeof(double) );
44 double *b = malloc( (size_t)n * n * sizeof(double) );
45 double *c = malloc( (size_t)n * n * sizeof(double) );
46 double alpha = 1.0, beta = 0.0, t, gflops;
47 char tr = 'N';
49 fill_random( a, n * n );
50 fill_random( b, n * n );
51 memset( c, 0, (size_t)n * n * sizeof(double) );
53 t = now_sec();
54 dgemm_( &tr, &tr, &n, &n, &n, &alpha, a, &n, b, &n, &beta, c, &n );
55 t = now_sec() - t;
57 gflops = 2.0 * n * (double) n * n / t / 1e9;
58 printf( "dgemm n=%5d %10.4f s %8.2f GFLOP/s (check c[0]=%.6f)\n",
59 n, t, gflops, c[0] );
61 free( a ); free( b ); free( c );
62}
64int main( int argc, char** argv )
65{
66 int sizes_default[] = { 128, 256, 512, 1024, 2048 };
67 int *sizes = sizes_default, nsizes = 5;
69 if ( argc > 1 ) {
70 nsizes = argc - 1;
71 sizes = malloc( nsizes * sizeof(int) );
72 for ( int i = 0; i < nsizes; i++ ) sizes[i] = atoi( argv[i + 1] );
73 }
75 for ( int i = 0; i < nsizes; i++ ) bench_dgemm( sizes[i] );
77 return 0;
78}