優れた出発点は、Robert A. van de GeijnとEnrique S.Quintana-Ortíによるすばらしい本、プログラミング行列計算の科学です。彼らは無料ダウンロード版を提供します。
BLASは3つのレベルに分かれています。
レベル1は、ベクトルのみを操作する線形代数関数のセットを定義します。これらの関数は、ベクトル化の恩恵を受けます(SSEの使用など)。
レベル2の関数は、行列とベクトルの演算です(例:行列とベクトルの積)。これらの関数は、Level1関数の観点から実装できます。ただし、共有メモリを備えたマルチプロセッサアーキテクチャを利用する専用の実装を提供できる場合は、この関数のパフォーマンスを向上させることができます。
レベル3の関数は、行列-行列積のような演算です。ここでも、Level2関数の観点からそれらを実装できます。ただし、Level3関数はO(N ^ 2)データに対してO(N ^ 3)操作を実行します。したがって、プラットフォームにキャッシュ階層がある場合、キャッシュ最適化/キャッシュフレンドリーな専用の実装を提供すると、パフォーマンスを向上させることができます。これは本でうまく説明されています。Level3関数の主な機能強化は、キャッシュの最適化です。このブーストは、並列処理やその他のハードウェア最適化による2番目のブーストを大幅に上回っています。
ちなみに、高性能BLAS実装のほとんど(またはすべて)はFortranで実装されていません。ATLASはCで実装されています。GotoBLAS/ OpenBLASはCで実装されており、パフォーマンスが重要な部分はアセンブラーで実装されています。Fortranでは、BLASのリファレンス実装のみが実装されています。ただし、これらすべてのBLAS実装は、LAPACKにリンクできるようにFortranインターフェースを提供します(LAPACKはBLASからすべてのパフォーマンスを獲得します)。
最適化されたコンパイラは、この点で小さな役割を果たします(GotoBLAS / OpenBLASの場合、コンパイラはまったく問題ではありません)。
私見のBLAS実装では、Coppersmith–WinogradアルゴリズムやStrassenアルゴリズムなどのアルゴリズムを使用しています。理由は正確にはわかりませんが、これは私の推測です:
- おそらく、これらのアルゴリズムのキャッシュ最適化実装を提供することは不可能です(つまり、勝つよりも失う可能性が高くなります)。
- これらのアルゴリズムは数値的に安定していません。BLASはLAPACKの計算カーネルであるため、これは実行できません。
編集/更新:
このトピックの新しく画期的なペーパーは、BLISペーパーです。彼らは非常によく書かれています。私の講義「高性能コンピューティングのためのソフトウェアの基礎」では、論文に続いてマトリックスマトリックス製品を実装しました。実際、私はマトリックスマトリックス製品のいくつかのバリアントを実装しました。最も単純なバリアントは完全にプレーンCで記述されており、コードは450行未満です。他のすべてのバリアントは単にループを最適化します
for (l=0; l<MR*NR; ++l) {
AB[l] = 0;
}
for (l=0; l<kc; ++l) {
for (j=0; j<NR; ++j) {
for (i=0; i<MR; ++i) {
AB[i+j*MR] += A[i]*B[j];
}
}
A += MR;
B += NR;
}
マトリックスマトリックス製品の全体的なパフォーマンスは、これらのループにのみ依存します。時間の約99.9%はここで費やされます。他のバリアントでは、パフォーマンスを改善するために組み込み関数とアセンブラコードを使用しました。あなたはここですべてのバリアントを通過するチュートリアルを見ることができます:
ulmBLAS:GEMM(Matrix-Matrix Product)のチュートリアル
BLISの論文と合わせて、インテルMKLのようなライブラリーがどのようにしてこのようなパフォーマンスを実現できるかを理解するのはかなり簡単になります。また、行または列の主要なストレージを使用するかどうかが問題にならないのはなぜですか。
最終的なベンチマークはここにあります(私たちは私たちのプロジェクトをulmBLASと呼びました):
ulmBLAS、BLIS、MKL、openBLAS、Eigenのベンチマーク
別の編集/更新:
また、線形方程式系を解くような数値線形代数問題にBLASがどのように使用されるかについてのチュートリアルも書きました。
高性能LU分解
(このLU因数分解は、たとえば、Matlabによって線形方程式系を解くために使用されます。)
チュートリアルを拡張して、PLASMAのようなLU因数分解の非常にスケーラブルな並列実装を実現する方法を説明およびデモする時間を見つけたいと思います。
では、次のようにします:キャッシュ最適化並列LU因数分解のコーディング
PS:私はuBLASのパフォーマンスを改善するための実験も行いました。実際、uBLASのパフォーマンスを向上させるのは非常に簡単です(ええ、言葉で遊びます:))。
uBLASでの実験。
ここでBLAZEを使用した同様のプロジェクト:
ブレイズの実験。