blas-microbenchmark1.5.0-dev

Outputs

What the benchmarks print and save, and the page bmb_report makes of it.

A benchmark prints where the result came from, then one row per point as it is measured: here dgemm over three sizes, at one and two threads. These runs were made when this page was built, by the machine that built it.

$ bmb_dgemm -m 256:1024 -t 1,2
# blas-microbenchmark 1.5.0-dev
# backend: openblas (OpenBLAS 0.3.26 NO_LAPACKE DYNAMIC_ARCH NO_AFFINITY Cooperlake MAX_THREADS=64)
# verified: every point, against a reference, before it was timed
# layout: row-major
# cpu: AMD EPYC 9V74 80-Core Processor (4 logical CPUs, 1 NUMA node)
# caches: L1d 32K, L1i 32K, L2 1M, L3 32M
# os: Linux 6.17.0-1022-azure x86_64
# date: 2026-10-12T09:48:01Z
# routine: dgemm
Thread count    Matrix dim1 (M=K)   Matrix dim2 (N)     time [s]        GFLOP/s       
1               256                 256                 0.000658143     50.983        
1               512                 512                 0.005228642     51.339        
1               1024                1024                0.040134619     53.507        
2               256                 256                 0.000352101     95.298        
2               512                 512                 0.002579224     104.076       
2               1024                1024                0.020220410     106.204       

With -o, the same results go to a file as well; -s adds the mean, the standard deviation, the slowest sample and the batch size. The comment lines say where the result came from; skip them when reading the file.

$ bmb_ddot -v 1024:8192 -s -o ddot.csv
$ cat ddot.csv
# blas-microbenchmark 1.5.0-dev
# backend: openblas (OpenBLAS 0.3.26 NO_LAPACKE DYNAMIC_ARCH NO_AFFINITY Cooperlake MAX_THREADS=64)
# verified: every point, against a reference, before it was timed
# cpu: AMD EPYC 9V74 80-Core Processor (4 logical CPUs, 1 NUMA node)
# caches: L1d 32K, L1i 32K, L2 1M, L3 32M
# os: Linux 6.17.0-1022-azure x86_64
# date: 2026-10-12T09:48:02Z
# routine: ddot
thread_count,vector_size,time_s,gflops,gbytes_per_s,mean_s,stddev_s,max_s,calls_per_sample,median_s
1,1024,0.000000109,18.752850,150.022801,0.000000112,0.000000007,0.000000131,914,0.000000110
1,2048,0.000000267,15.346063,122.768504,0.000000271,0.000000011,0.000000303,373,0.000000268
1,4096,0.000000625,13.099028,104.792220,0.000000636,0.000000028,0.000000721,159,0.000000627
1,8192,0.000001232,13.295194,106.361552,0.000001282,0.000000106,0.000001586,80,0.000001237

The JSON holds the same as fields, and is what bmb_report(1) reads. Here with a label, to tell two runs on the same machine apart.

$ bmb_dgemv -m 512 -M 256:512 -l 'turbo off' -o dgemv.json
$ cat dgemv.json
{
  "version": "1.5.0-dev",
  "backend": "openblas",
  "blas": "OpenBLAS 0.3.26 NO_LAPACKE DYNAMIC_ARCH NO_AFFINITY Cooperlake MAX_THREADS=64",
  "label": "turbo off",
  "verified": true,
  "layout": "row",
  "date": "2026-10-12T09:48:02Z",
  "machine": {
    "cpu": "AMD EPYC 9V74 80-Core Processor",
    "logical_cpus": 4,
    "numa_nodes": 1,
    "caches": [
      {"level": 1, "type": "data", "size_bytes": 32768},
      {"level": 1, "type": "instruction", "size_bytes": 32768},
      {"level": 2, "type": "unified", "size_bytes": 1048576},
      {"level": 3, "type": "unified", "size_bytes": 33554432}
    ],
    "os": "Linux 6.17.0-1022-azure x86_64"
  },
  "routine": "dgemv",
  "dim1_label": "Matrix dim1 (M)",
  "dim2_label": "Matrix dim2 (N)",
  "results": [
    {
      "thread_count": 1,
      "dim1": 512,
      "dim2": 256,
      "time_s": 0.000013223,
      "gflops": 19.825350,
      "gbytes_per_s": 80.075829
    },
    {
      "thread_count": 1,
      "dim1": 512,
      "dim2": 512,
      "time_s": 0.000026109,
      "gflops": 20.081123,
      "gbytes_per_s": 80.795143
    }
  ]
}

bmb_report results/*.json > report.html makes one page of all of them. These are from results measured on a laptop (Intel Core Ultra 7 155U, WSL2), with OpenBLAS 0.3.26 and BLIS 0.9.0: they show what the page draws, not which library is faster.

The best figure for each routine, and where every series came from.

The report's summary: the best GFLOP/s for ddot, dgemv and dgemm, and a table of the library, CPU, caches, OS, date and files of each series
The summary and the provenance of each series.

Hovering a chart gives the exact values.

ddot GFLOP/s against vector size, OpenBLAS and BLIS, with the L1d, L2 and L3 sizes marked
Performance against size, the caches marked.
dgemm, BLIS relative to OpenBLAS at 8 threads, on a log scale around x1
Each library against the reference.
dgemm GFLOP/s at 1, 2, 4 and 8 threads, with ideal scaling dashed
Thread scaling, against ideal.
dgemv heatmaps of GFLOP/s over M and N, OpenBLAS and BLIS
Every shape of a two-dimension sweep.

The same ddot command run four times with each library, each run into its own file: a band shows how far the runs spread, and the comparison tells a difference within that noise (a hollow point) from one beyond it (see Repeated runs and noise).

ddot GFLOP/s against vector size, OpenBLAS and BLIS, four runs each, with a band from the fastest run to the slowest
The spread of four runs.
ddot, BLIS relative to OpenBLAS, four runs each: hollow points where the difference is within the noise, filled ones where it is beyond
Hollow: within the noise.

Every row, sortable by any column.

The report's raw data table: routine, series, threads, sizes, time, GFLOP/s, GB/s and file of each point
The raw data table, opened.