前回、RISC-VのRocket Chipに整数のDot Productを計算するアクセラレータを接続した。 これにより、整数行列積の計算において、約2.7倍の高速化を達成した。
ただし、これはまだ高速化できる余地がある。 一度データをアクセラレータ内に格納すると、次に同じアドレスからフェッチをしてくる場合はそのフェッチ処理を省略し、なるべく使いまわしたい。 特に、データキャッシュを縦方向に舐める、乗数行列のフェッチにおいては、なるべくフェッチの回数を短くしたい。
ということで、一度キャッシュした場所を再度フェッチしに行く場合は、既にキャッシュしてあるデータを再利用し、再フェッチをしないという方式を導入してみる。 コヒーレントを取るという観点からはこの方式は若干問題があるが、とりあえず気にせず進めていこう。
この時にソフトウェアの注意点として、行列積を求める順番が重要になる。つまり、なるべく乗数行列(第2オペランド側)が、なるべく連続で同じデータを利用するように工夫してやる必要がある。
for (int i = 0; i < 16; i++) { for (int j = 0; j < 16; j++) { matrixmul (output_data[j*16+i], &(input1_data[j*16]), &(input2_data[i])); // ~~~~~~~~~~~~~~~~~ ← ここがなるべく連続で同じアドレスを使用するように。 } }
これで、メモリアクセスの回数を約半分に削減できたはずだ。性能はどうなったかと言うと、
というわけで、オリジナルのソフトウェアによる実装と比較して、4.15倍の高速化となった。まあまあかな。
逆に、これだけ頑張ったのに何で4倍程度しか速くならないんだろう。これをむしろ調査しなければ。