マトリックス-マトリックス製品の高速化は、アセンブリ コードの使用による部分的なものにすぎません。単純な実装では、主なボトルネックはメモリ アクセスです。ほとんどの場合、CPU は実際の計算を待機します。
最初に、L2 および L1 キャッシュ内のデータをできるだけ頻繁に再利用できるように、行列 - 行列乗算のアルゴリズムを変更する必要があります。これは、C (または C++、Fortran、または ...) で行うことができます。これにより、行列のサイズがキャッシュよりも大きくなっても機能しなくなることのない実装になります。また、実装が常に計算を実行できることも意味します (CPU レジスタで必要なデータはほとんど常に L1 キャッシュにあり、L1 キャッシュで必要なデータはほとんど常に L2 キャッシュにあります...)。
次のステップは、すべての計算が行われるホット スポットを最適化することです。これには数行の C コードしか含まれていません (私のGEMM チュートリアルでは 10 行しかありません)。アセンブリ コードは、SSE (または AVX) を使用して、命令のパイプライン処理、ループ展開 (分岐予測を改善するため)、プリフェッチ (キャッシュ ミスを減らすため) に関して最適化を行います。
同様の手法は、他の BLAS レベル 3 関数にも使用できます。実際、それらのほとんどは、GEMM 関数の内部のもの (いわゆるマイクロ カーネル) を使用します。
ulmBLAS ベンチマークでは、ほぼすべての BLAS レベル 3 関数がほぼ同じパフォーマンスを達成できることが わかります。
より完全な読み物として、Robert A. van de Geijn と Enrique S. Quintana-Ortí によるすばらしい論文The Science of Programming Matrix Computationsをお勧めします。また、ほとんどのアイデアがulmBLASのために採用され、単純化されているBLISも見たいと思うかもしれません。