Fast Multidimensional Matrix Multiplication on CPU from Scratch (2022)
siboehm.com
siboehm.com
Source code: https://github.com/arekpaterek/Faster_SGEMM_CUDA
size tflops_cublas tflops_my diff gpu
4096² 50.8-50.9 61.8 +21% 4090
6144² 55.3 59.8 +8% 4090
8192² 56.3-56.5 67.1 +19% 4090
12288² 53.7 66.7 +24% 4090
16384² 53.6 66.7 +24% 4090
4096² 28.7-28.8 32.5 +13% 4070ts
4096² 3.8-4.3 6.7 +56-76% T4 size tflops_cublas tflops_my diff gpu
12288² 51.4 56.3 +9% h100
8192² 50.5 56.1 +11% h100
4096² 43.8 53.9 +23% h100
12288² 18.9 27.0 +43% a100
8192² 19.0 26.3 +38% a100
4096² 17.5 19.8 +13% a100
12288² 28.8 34.5 +20% 3090ti
Edit: The values for A100 are fishy. They should not exceed 19.5 TFLOPS, which is the maximum from the spec. I have to take a closer look into that.E.g. consider the line:
sum[y2*8 + x2] += ...
In the final loop iteration when y2=15 and x2=7, the index is 127.You can look at the generated sass on godbolt: https://cuda.godbolt.org/z/19excTxM3
Note that there are 1024 FFMA instructions in the loop but you would expect 16*8*BK = 2048. This would suggest half the operations are skipped, which lines up with the half of writes that are out of bounds being omitted.
After the compute loop when you're calculating the final result and storing it, you can see that the FFMAs referencing out of bounds indices write QNAN instead of any real results.
Is it possible that the NANs are what are messing with your tests? Those are notoriously hard to deal with correctly, but you should assert that the result doesn't have any NANs whatsoever.
It definitely sucks to be led astray and have time wasted by a bug inherited from the original repo though, sorry to hear that :/
The article, or something similar, was posted recently with discussion.
- They're a bit less numerically stable, which used to matter more for common BLAS use cases. Less so these days.
- The memory access patterns and algorithm parallelism make it much harder to reach as high a fraction of peak performance as standard GEMM. Matrix size restrictions for recursive mult algorithms is also an issue.
250GFLOP/core is no joke - He also cross-compared to an M1 Pro, that when not using the secret matrix coprocessor achieves effectively the same vector throughput, a decade later...
Beating cuBlas is unlikely. You probably made a mistake. Last I tested it, it was even better than MKL in efficiency.
While flash memory became so fast in recent years, I haven't heard of any break-through technology prototypes to bring some significant progress into RAM. Let alone the RAM latency, which remained constant (+/- few ns) through all the years.
Unlike the main memory bandwidth or that of the shared L3 cache memory, the memory bandwidth of the non-shared L1 and L2 caches has been increased exactly in the same ratio as the FMA throughput. Almost all CPUs have always been able to do exactly the same number of FMA operations per clock cycle and loads from the L1 cache per clock cycle (simultaneously with typically only a half of that number, of stores to the L1 cache per clock cycle).
Had this not been true, the computational execution units of the cores would have become useless.
Fortunately, the solution of systems of linear equations and the multiplication of matrices are very frequent operations and these reuse most of their operands, so they can reach the maximum computational throughput.
Until Haswell, for many years Intel had the target of doubling the FP throughput per desktop socket every 2 years, in order to avoid the risk of AMD catching up again with them.
After launching Haswell, Intel has relaxed and they did not increase again the throughput for about a half of decade, until they had to start again to do that, under the menace of AMD Zen, when for lack of other better means they have increased every year the number of cores per socket from Kaby Lake (4 cores in 2016) to Comet Lake (10 cores in 2019).