blas-microbenchmark1.11.0-dev

Output

From the manual of the benchmarks, man blas-microbenchmark

Results go to standard output, one row per point, as they are measured; warnings and errors go to standard error. Every result starts with where it came from:

# blas-microbenchmark 1.11.0-dev
# backend: openblas (OpenBLAS 0.3.26 DYNAMIC_ARCH Haswell MAX_THREADS=64)
# kernels: Haswell
# verified: every point, against a reference, before it was timed
# layout: row-major
# cpu: Intel(R) Core(TM) Ultra 7 155U (14 logical CPUs, 1 NUMA node)
# caches: L1d 48K, L1i 64K, L2 2M, L3 12M
# frequency: governor performance, turbo off
# os: Linux 6.6.87 x86_64
# date: 2026-10-02T09:05:04Z
# affinity: CPUs 0-13
# command: bmb_dgemm -m 512:2048 -o dgemm.json
# run: 0.2 s and 1 call of warm-up, 10 samples, batch size chosen per point, hot cache
# operands: aligned to 64 bytes, leading dimensions + 0
# arguments: trans NN, batch_count 1, batch_mode loop
# compiler: gcc 13.3.0, CFLAGS -g -O2 -fopenmp
# environment: OMP_PROC_BIND=close
# routine: dgemm

The library's version string, where it exposes one, tells apart two builds of the same library. The kernels are those the library's dispatch chose at run time, as it names them: OpenBLAS's core, BLIS's and AOCL-BLAS's configuration, MKL's code branch (which MKL_ENABLE_INSTRUCTIONS limits; AUTO where MKL names none, as on AMD CPUs). On a CPU with SME, AMX or AVX10 the path changes the numbers, and two files from the same library can only be told apart by it. Netlib, NVPL, ArmPL and FlexiBLAS do not say, and the line is left out. A build against the library's 64-bit integer interface (ILP64, configure --enable-ilp64 with OpenBLAS or MKL) adds the line # integers: 64-bit (ILP64); in it, a vector may hold more than 2^31 elements. sbgemm, whose inputs are of another type than its output, adds # types: bf16 inputs, fp32 accumulation and output. The caches show where a sweep leaves each level. The frequency line gives the CPU frequency governor (several, joined by /, when CPUs differ) and whether turbo is on, as Linux exposes them in /sys; virtual machines and containers often expose neither. When either lets the frequency change during the run, a governor other than performance or turbo on, a warning on standard error says so and gives the commands that fix it; the run goes on. A field that cannot be read on a machine is left out, never guessed. The hostname is deliberately not recorded.

The next lines say how the run was made, so that it can be made again: the CPUs the process could run on, as Linux lists its affinity; the command line, the program by its name and each word as a shell would take it back (as typed: a path given to -o goes with the results, a relative one keeps a home directory out); the warm-up time and calls, the samples and the time and spread that may ask for more, and the batch size (-w, -x, -i, -T, -e, -E, -b, which is 1 whatever -b says for the routines whose operand is restored before every call), and the cache (-k); the operands' alignment and, for the routines with a matrix, the padding of their leading dimensions (-a, -p); the routine's arguments, those it takes (--trans, --uplo, --side, --diag, and GEMM's --batch-count, --batch-mode), defaults included; the compiler and the CFLAGS the benchmarks were built with (not the BLAS library's own); and the variables set among those that change what a BLAS library does: OMP_NUM_THREADS, OMP_PROC_BIND, OMP_PLACES, OMP_DYNAMIC, OMP_WAIT_POLICY, GOMP_CPU_AFFINITY, GOMP_SPINCOUNT, KMP_AFFINITY, KMP_BLOCKTIME, KMP_HW_SUBSET, OPENBLAS_NUM_THREADS, GOTO_NUM_THREADS, OPENBLAS_CORETYPE, BLIS_NUM_THREADS, BLIS_JC_NT, BLIS_PC_NT, BLIS_IC_NT, BLIS_JR_NT, BLIS_IR_NT, BLIS_ARCH_TYPE, AOCL_ENABLE_INSTRUCTIONS, MKL_NUM_THREADS, MKL_DOMAIN_NUM_THREADS, MKL_DYNAMIC, MKL_THREADING_LAYER, MKL_ENABLE_INSTRUCTIONS, MKL_CBWR and FLEXIBLAS. With -l, a # label: line follows the backend and kernels lines, and with --peak-gflops or --peak-gbs, a # peak: line after it, the values as given; unless -C was given, a # verified: line comes next, then, for the routines with a matrix, the # layout: (-L).

With -o, the results are also saved to a file:

the same comment lines, then a header and one row per point. Readers must skip lines starting with #, e.g. pd.read_csv(file, comment="#") in pandas.
one object holding the same information as fields: version, backend, blas, kernels, blas_int_bits (32, or 64 in an ILP64 build), types (sbgemm's: an object of inputs and accumulator, "bf16" and "fp32"), label, peak_gflops_per_core and peak_gbs (as given), verified, layout (row or col, for the routines with a matrix), date; machine with cpu, logical_cpus, numa_nodes, caches, governor, turbo (true or false) and os; run with command (the words of the command line), warmup, warmup_time, iterations, min_time, max_spread, max_time, cache (hot or cold), star (under --star: an object whose cpus lists the CPUs the instances are pinned to, in order: N instances take the first N), align, ld_pad (for the routines with a matrix), arguments (for the routines that have them: an object of trans, uplo, side, diag, batch_count and batch_mode, those the routine takes), batch (when every point used the same: -b or 1, as above), compiler, cflags, cpus_allowed and environment (the variables set, by name); routine and, naming its dimensions, dim1_label, dim2_label and, for GEMM under -K, dim3_label. Then a results array, one object per point: thread_count, dim1, dim2, dim3 (GEMM under -K), time_s, gflops, gbytes_per_s, with -s mean_s, stddev_s and max_s, then calls_per_sample, median_s, q1_s, q3_s and samples, and with -k cold, copies, the copies of the operands the point rotated over, which the table and the CSV give last too. A field that does not apply is left out. This is what bmb_report(1) reads.