私は大学で、医療用の画像再構成アルゴリズムに関連する研究を行っています。
次のコードのパフォーマンスを改善する必要があります。
for (lor=lor0[mypid]; lor <= lor1[mypid]; lor++)
{
LOR_X = P.symmLOR[lor].x;
LOR_Y = P.symmLOR[lor].y;
LOR_XY = P.symmLOR[lor].xy;
lor_z = P.symmLOR[lor].z;
LOR_Z_X = P.symmLOR[lor_z].x;
LOR_Z_Y = P.symmLOR[lor_z].y;
LOR_Z_XY = P.symmLOR[lor_z].xy;
s0 = P.a2r[lor];
s1 = P.a2r[lor+1];
for (s=s0; s < s1; s++)
{
pixel = P.a2b[s];
v = P.a2p[s];
b[lor] += v * x[pixel];
p = P.symm_Xpixel[pixel];
b[LOR_X] += v * x[p];
p = P.symm_Ypixel[pixel];
b[LOR_Y] += v * x[p];
p = P.symm_XYpixel[pixel];
b[LOR_XY] += v * x[p];
// do Z symmetry.
pixel_z = P.symm_Zpixel[pixel];
b[lor_z] += v * x[pixel_z];
p = P.symm_Xpixel[pixel_z];
b[LOR_Z_X] += v * x[p];
p = P.symm_Ypixel[pixel_z];
b[LOR_Z_Y] += v * x[p];
p = P.symm_XYpixel[pixel_z];
b[LOR_Z_XY] += v * x[p];
}
}
知りたい人のために、コードは MLEM 転送関数を実装し、すべての変数は FLOATです。
いくつかのテストの後、大きな遅延がコードのこの部分にあることに気付きました。(ご存知のように、90 - 10 ルール)。
その後、Papi (http://cl.cs.utk.edu/papi/) を使用して L1D キャッシュ ミスを測定しました。私が思ったように、Papi は、特に b ベクトル (サイズが大きい) へのランダム アクセスの場合に、ミスの量が多いためにパフォーマンスが低下することを確認しています。
インターネットで情報を読む これまでのところ、パフォーマンスを改善するための 2 つのオプションを知っているだけです。データの局所性を改善するか、データ汚染を減らすことです。
最初の改善を行うために、すべてのプログラマーがメモリについて知っておくべきこと(www.akkadia.org/drepper/cpumemory.pdf) A. 1 行列の乗算。
SpMV (sparse matrix-vector Multiplication) をブロックすると、パフォーマンスが向上すると思います。
一方、プログラムが b ベクトルにアクセスしようとするたびに、いわゆるキャッシュ汚染が発生しました。
キャッシュを使用せずに SIMD 命令で b ベクトルから値をロードする方法はありますか?
また、 void _mm_stream_ps(float * p , __m128 a ) のような関数を使用して、キャッシュを汚染することなく、ベクトル b に 1 つの float 値を格納することは可能ですか?
_mm_stream_ps は常に 4 つの float を格納するため使用できませんが、b ベクトルへのアクセスは明らかにランダムです。
私のジレンマを明確にしたいと思います。
詳細: v は、CRS 形式のスパース マトリックス ストアの列値です。CRS 形式を別の形式に変更しようとすると、別の最適化を実行できることはわかっていますが、前に述べたように、数か月にわたっていくつかのテストを行った結果、パフォーマンスの低下はベクター b のランダム アクセスに関連していることがわかっています。from 400.000.000 L1D Misses ベクトル b に格納しない場合、100~ Misses に進むことができます。
ありがとう。