キャッシュの使用について話している場合は、ループタイリングと呼ばれるものを実行することをお勧めします。ループの内側がキャッシュ内に格納されるように、ループをタイルに分割します(最近はかなり大きくなっています)。したがって、ループは次のようになります(ポインタを使用して行列を関数に渡す場合)
for(j=0;j<size;j+=t)
for(k=0;k<size;k+=t)
for(i=0;i<size;i+=t)
for(ii=i;ii<MIN(i+t,size);ii++)
for(jj=j;jj<MIN(j+t,size);jj++)
{
var=*(c+ii * size+jj); //Var is a scalar variable
for(kk=k;kk<MIN(k+t,size);kk++)
{
var = var + *(a+ii *size +kk) * *(bt +jj * size+ kk);
}
*(c+ii *size +jj) = var;
}
tの値は、得られるスピードアップによって異なります。t=64,128,256などになります。ここで使用できるテクニックは他にもたくさんあります。ループタイリングは、キャッシュを効率的に利用するための1回限りの手法です。さらに、乗算関数に送信する前に、B行列を転置することができます。そうすれば、行列Bの要素に線形にアクセスできるようになります。
A -------- and B | | | |
-------- | | | |
-------- | | | |
-------- | | | |
ここでは、Aの最初の行にBの最初の列を掛けることを常に検討します。またC
、CPUは、メモリ内のマトリックスBのすべての列を1つずつ読み取るために、余分な労力を必要とします。これらの作業を容易にするために、行列を転置して行列の行B'
(本質的には列にすぎないB
)を取得し、ループタイリングを使用して乗算用の要素の最大量をキャッシュできます。これが役立つことを願っています。