Performance experiments with matrix multiplication in Rust
vorner.github.io
vorner.github.io
Compare: The original steam enginge trains went I believe 10km/h, so if it received the same level of speedup, it reaches somehere between mach 5 and 10. You can classify this algorithm as hypersonic ;-)
If modern train engine produced 700 times as much power that’s only 26 times faster for the same cargo (don’t they pull more now?) And we do have trains that can go 260 km/hr... just not with cargo.
progress, man.
Coppersmith–Winograd approaches take the crown for asymptotic scaling in matrix-matrix multiplication [1].
It kind of blows my mind that a tight bound on the complexity of matrix-matrix multiplication still isn't known!
Edit: Some quick googling shows that François Le Gall took the crown in 2014.
[1] https://en.wikipedia.org/wiki/Computational_complexity_of_ma...
E.g. strassens-algorithms assumes something like:
(A+B)C - BC = AC
With the convential floating point representation this becomes a problem if B >> A because of rounding errors.
Most algorithms faster than Strassen assume:
(( fA + B)C - BC)/f = AC
and
(fA + B)C = BC +fAC
f is then choosen in such a way, that fAC is neglegible. But if that is the case fA is much smaller than B and we automatically get numerical problems.
There is a procedure to remove the fAC terms (which would imply that f could be choosen close to 1) which armortizes over enough recursions. But for Coppersmith-Winograd (and derivatives like Le-Galls algorithm). We need to divide the matrix in each recursion step into enough submatrices that the indices can be treated heuristically(lets say a division of each index in each iteration in 100 subindices). This would imply the sides of each matrix must be at least of size 100^n_recusion. We won't need to multiply matrices of that size.
For avx512 (and maybe other x86_64, which is now dynamically dispatched) large BLAS, use BLIS. BLIS also provides a non-BLAS interface. For small matrix multiplication, use libxsmm, of course.
Remember that the world isn't all amd64/x86_64, in which case BLIS is infinitely faster than MKL, and it's probably faster even on Bulldozer/Zen. (I haven't compared on Bulldozer recently, and don't have Zen.)
Thanks for the heads-up RE: BLIS, I'd forgotten about them; it's probably the best option, especially considering its open source status.
[0] https://github.com/xianyi/OpenBLAS/issues/991#issuecomment-3...
I stand by what I said (although that paper was a cool read!)
Unless you know this is what your consumers want, I wouldn’t use it in library code.
See https://gist.github.com/rygorous/32bc3ea8301dba09358fd2c64e0... for a writeup about it.
There are relevant snippets of information on SIMD trades-off around FFTW, BLIS, and, especially, libxsmm. This stuff definitely isn't simple.
For dense matrix multiplication it’s probably worth it, but the article is phrased much more broadly in its conclusions, and does not mention the fact that this issue exists (possibly because the author isn’t aware of it — which I don’t fault them for).
To be clear, a 2ms stall when calling certain functions has the potential to be devastating for anything that wants to run at speeds approximating realtime.
If you do this while also storing the matrix in z-order in memory the offsets in the unrolled part become constants independent of the matrix size.
This technique is applicable to anything using nested loops where the indicies take you to a lot of memory repeatedly.
I'm still waiting for a couple with bit interleave and deinterleave instructions, but those wouldn't be usable without intrinsics.