行列ベクトル乗算のスケーリングが行われないのはなぜですか?


15

長い投稿で申し訳ありませんが、最初の段階で関連があると思ったものをすべて含めたかったのです。

私が欲しいもの

Krylov Subspace Methods for Dense Matricesの並列バージョンを実装しています。主にGMRES、QMRおよびCG。(プロファイリング後)私のDGEMVルーチンは哀れなことに気付きました。それで、私はそれを分離することによってそれに集中することに決めました。12コアのマシンで実行してみましたが、以下の結果は4コアのIntel i3ラップトップ用です。傾向に大きな違いはありません。

私のKMP_AFFINITY=VERBOSE出力はここにあります

私は小さなコードを書きました:

size_N = 15000
A = randomly_generated_dense_matrix(size_N,size_N); %Condition Number is not bad
b = randomly_generated_dense_vector(size_N);
for it=1:n_times %n_times I kept at 50 
 x = Matrix_Vector_Multi(A,b);
end

これは、50回の反復でCGの動作をシミュレートすると思います。

私が試したもの:

翻訳

私はもともとFortranでコードを書いていました。C、MATLAB、Python(Numpy)に翻訳しました。言うまでもなく、MATLABとPythonは恐ろしいものでした。驚くべきことに、上記の値ではCはFORTRANよりも1〜2秒優れていました。一貫して。

プロファイリング

実行するコードのプロファイルを作成し、46.075数秒間実行しました。これは、MKL_DYNAMICがに設定されFALSE、すべてのコアが使用されていたときです。MKL_DYNAMICをtrueとして使用した場合、特定の時点で使用されていたコアの数は(およそ)半分だけです。詳細は次のとおりです。

Address Line    Assembly                CPU Time

0x5cb51c        mulpd %xmm9, %xmm14     36.591s

最も時間がかかるプロセスは次のようです:

Call Stack                          LAX16_N4_Loop_M16gas_1
CPU Time by Utilization             157.926s
CPU Time:Total by Utilization       94.1%
Overhead Time                       0us
Overhead Time:Total                 0.0%    
Module                              libmkl_mc3.so   

以下にいくつかの写真を示します。ここに画像の説明を入力してください ここに画像の説明を入力してください

結論:

私はプロファイリングの本当の初心者ですが、スピードアップがまだ良くないことを理解しています。シーケンシャル(1コア)コードは53秒で終了します。それは1.1未満のスピードアップです!

本当の質問:スピードアップを改善するにはどうすればよいですか?

私が役立つかもしれないと思うものですが、私は確信できません:

  • Pthreadsの実装
  • MPI(ScaLapack)の実装
  • 手動調整(方法がわかりません。これを提案する場合は、リソースを推奨してください)

誰かが(特にメモリに関して)より多くの詳細を必要とする場合、私が何をどのように実行すべきかを教えてください。以前にメモリのプロファイルを作成したことがありません。

回答:


20

マトリックスのサイズは15,000 x 15,000であるため、マトリックスには225Mの要素があります。これにより、約2GBのメモリが確保されます。これは、プロセッサのキャッシュサイズよりもはるかに大きいため、すべての行列乗算でメインメモリから完全にロードする必要があり、約100GBのデータ転送に加えて、ソースベクトルとデスティネーションベクトルに必要なものが必要になります。

i3の最大メモリ帯域幅は、Intelの仕様に基づいて約21 GB / sですが、Webを見ると、実際にはその半分しか実際に使用できないことがわかります。したがって、少なくとも、ベンチマークは10秒続くと予想されますが、実際の45秒の測定値はそれほど大きくはありません。

同時に、約100億の浮動小数点乗算および加算も実行しています。たとえば、組み合わせの10クロックサイクルと3 GHzクロックレートを考慮すると、30秒で出てきます。もちろん、キャッシュが巧妙であれば、投機的なメモリロードと同時に実行できます。

全体として、私はあなたがあまりにも遠くないことを言うでしょう。何を期待していましたか?


少なくとも2〜3倍高速化する方法はありませんか?
-Inquest

@Nunoxic-SiSoftware Sandraなどのツールを使用して、システムのメモリパフォーマンスをベンチマークすることができます。Wolfgangs分析は、私に注目します。アプリケーションがメモリ帯域幅に制限されている場合、並列化はほとんど効果がありません。また、お持ちの省電力オプションをご覧ください。メモリのパフォーマンスが低下している可能性があります。また、メモリを高品質のメモリに交換することを検討してください。たとえば、CASレイテンシを低くすると、ウォール時間に大きな違いが生じる可能性があります。
マークブース

4

行列ベクトル乗算はどのようにしていますか?手で二重ループ?または、BLASを呼び出しますか?MKLを使用している場合は、スレッドバージョンのBLASルーチンを使用することを強くお勧めします。

好奇心から、独自の調整バージョンのATLASをコンパイルし、それが問題にどのように影響するかを確認することもできます。

更新

以下のコメントの説明に従って、Intel Core i3-330Mには2つの「実際の」コアしかありません。欠落している2つのコアは、ハイパースレッディングでエミュレートされます。ハイパースレッドコアでは、メモリバスと浮動小数点ユニットの両方が共有されるため、2つのうちのいずれかが制限要因である場合、速度は向上しません。実際、4つのコアを使用すると速度が低下する可能性があります。

「2つの」コアのみでどのような結果が得られますか?


ATLA、GoTo、Netlib BLASを試しました。すべてパフォーマンスがMKLよりも弱いです。これは予想されているのですか、何か間違っていますか?ハンドブックに記載されているようにATLASをコンパイルしました。さらに、(正確な)コードをここに貼り付けました。その呼び出しMKLのBLAS。
-Inquest

OK、そしてスケーリングのために、ベースラインの場合、コードは単一のCPUでのみ実行されていると確信していますか?たとえば、ベンチマークを実行すると、CPU使用率のヒストグラムに単一のコアのみが表示されますか?
ペドロ

はい。CPUヒストグラムは1コアを示します。
-Inquest

再び好奇心から、2つまたは3つのコアで何が得られますか?お使いのマシンには実際に4つの物理コアがありますか、それともハイパースレッディングを備えた2つのコアしかありませんか?
ペドロ

それをどうやって見つけるのですか?メインにKMP_AFFINITYを含めました。
-Inquest

0

メモリアクセス時間、キャッシュラインの使用率、TLBミスに関して、この問題には行優先順序が最適であるという印象があります。FORTRANバージョンでは、代わりに列優先の順序が使用されているため、Cバージョンより一貫して遅い理由を説明できます。

b

行列ベクトルの乗算の代わりに、単一ループで行列のすべての要素を合計する場合、速度をテストすることもできます。(追加の非結合性により、コンパイラがこの最適化を実行できなくなる可能性があるため、係数4でループを展開することができます。)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.