前回の続き、前回まででやっと環境が整ったので、MNISTの行列計算の部分をオフロードしてRoCCアクセラレータのシミュレーションを行う。
SpikeでRoCCアクセラレータを模擬するのは以下の操作だ。 行列積の1要素を計算するのに、1番目の行列の要素を行方向にシークしていき、2番目の行列の要素を列方向にシークしていく。 それぞれの値を掛け算し、16bitの固定小数点で加算していく。これで行列積の要素1つ分の計算になる。 この部分をRoCCアクセラレータで一回で実行できるものとし、RoCCアクセラレータのモデルをC++で記述する。
関連記事
- RISC-V ISS Spike を使ってMNISTのハードウェアアクセラレーションをシミュレーションしたい
- RISC-V ISS Spike を使ってMNISTのハードウェアアクセラレーションを実装する
- Chiselを使ってMNISTハードウェアアクセラレータを実装(実装中)
- Chiselを使ってMNISTハードウェアアクセラレータを実装(FPGAで確認)
RoCCアクセラレータをC++でモデル化する
RoCCアクセラレータをC++でモデルし、以下ようなmatrix16_rocc.cc
を作成した。途中で64ビットの計算とか入ってしまっている。
ライブラリと同じ動きをさせるとこのようになってしまった。libfix16をもうちょっと調べて、ハードウェア化しやすい状態までもっていく必要があるなあ。
case 0: { m_length = xs1; break; } case 1: { m_v_step = xs1; break; } case 2: { reg_t xs1_p = xs1; reg_t xs2_p = xs2; for (reg_t i = 0; i < m_length; i++) { int32_t a_val = p->get_mmu()->load_int32(xs1_p); xs1_p += sizeof(int32_t); int32_t b_val = p->get_mmu()->load_int32(xs2_p); xs2_p += (m_v_step * sizeof(int32_t)); int64_t product = static_cast<int64_t>(a_val) * b_val; int32_t adjust = (product & 0x8000) >> 15; total = total + (product >> 16) + adjust; } break; }
というわけで、RoCCにオフロードする前とオフロードした後で、実行命令数にどれくらい差がでているのか調査した。 SpikeはFunctionalな命令セットシミュレータなので、サイクル数までは計算できない。とりあえずRoCCアクセラレータが正しく上記のDot Productを計算できているかどうかを確認しよう。
- ハードウェア化する前
./spike --extension=matrix16_rocc --extlib libmatrix16_rocc.so /home/msyksphinz/work/training/risc-v/mnist/train_twolayernet_fix16_full &> train_twolayernet_fix16_full.log
- ハードウェア化した場合
./spike --extension=matrix16_rocc --extlib libmatrix16_rocc.so /home/msyksphinz/work/training/risc-v/mnist/train_twolayernet_fix16_hw &> train_twolayernet_fix16_hw.log
$ for f in `ls -1 train_twolayernet_fix16*.log`; do echo ${f}; cat ${f}; done train_twolayernet_fix16_full.log === TestNetwork === === start === Final Result : Correct = 185 / 200 Time = 218279215 - 10031 = 218269184 train_twolayernet_fix16_hw.log === TestNetwork === === start === Final Result : Correct = 185 / 200 Time = 1345620 - 10031 = 1335589
推論動作は正しく動いていることが確認できた。命令数的にも、しっかり削減できている(ログはTimeってなっているけど...)。
次は、ちゃんとハードウェアを実装してFPGAで動作させよう。