FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

RISC-VプロセッサHiFive1で機械学習コードを動作させる(6. 高速化の検討)

RISC-VプロセッサHiFive1でMNISTを実行させている。現状の問題点としては、いろいろなところが遅いことだ。 予想よりも性能が出ない。いろいろ試行した結果、やはり問題としては学習データがCPUに対して遠いところにある事だろう。 つまり、固定値の学習データをフラッシュメモリの上に置いており、そこにデータを毎回取りに行っている。 行列式の計算なので、縦方向の計算になり、あらかじめ局所的な部分をあらかじめL1キャッシュにロードしておくのも難しい。 何とかして少しでも高速化できないだろうか。

固定値の中でも、小さなものはL1に置きなおすことができるかもしれない。 現状、固定値としてフラッシュメモリに置いているのは、

  • 入力データ (28x28バイトx100個分)
  • MNIST学習済みデータ1. (28x28x50x4バイト : 50はHidden Layerのサイズ)
  • MNIST学習済みデータ2. (50x4バイト : 50はHidden Layerのサイズ)
  • MNIST学習済みデータ3. (50x10x4バイト : 10は出力層のサイズ)
  • MNIST学習済みデータ4. (10x4バイト : 10は出力層のサイズ)

ということで、とりあえず一番大きいのは最初の学習済みデータな訳だが、これを全部L1キャッシュに入れるのはちょっと無理だ。 それ以外のものなら入るかもしれない。プログラムを実行する前に、これらの学習済みデータをL1キャッシュにコピーしてみよう。

もともとのフラッシュメモリに格納されたデータは、以下のようにして参照している。

extern char _binary_wb0_bin_start[];
extern char _binary_wb0_bin_end[];
extern char _binary_wb1_bin_start[];
extern char _binary_wb1_bin_end[];
extern char _binary_wh0_bin_start[];
extern char _binary_wh0_bin_end[];
extern char _binary_wh1_bin_start[];
extern char _binary_wh1_bin_end[];

const fix16_t *wh0 = (fix16_t *)_binary_wh0_bin_start;  // [INPUTNO * HIDDENNO];
const fix16_t *wb0 = (fix16_t *)_binary_wb0_bin_start;  // [HIDDENNO];
const fix16_t *wh1 = (fix16_t *)_binary_wh1_bin_start;  // [HIDDENNO * OUTPUTNO];
const fix16_t *wb1 = (fix16_t *)_binary_wb1_bin_start;  // [OUTPUTNO];          

最初のwh0は非常に大きいので、さすがにこれはL1に格納できない。それ以外のものをコピーする。

const fix16_t *wh0 = (fix16_t *)_binary_wh0_bin_start;  // [INPUTNO * HIDDENNO];
const fix16_t *c_wb0 = (fix16_t *)_binary_wb0_bin_start;  // [HIDDENNO];
const fix16_t *c_wh1 = (fix16_t *)_binary_wh1_bin_start;  // [HIDDENNO * OUTPUTNO];
const fix16_t *c_wb1 = (fix16_t *)_binary_wb1_bin_start;  // [OUTPUTNO];          

int main ()
{
  int i;

  // for (i = 0; i < INPUTNO * HIDDENNO; i++)  wh0[i] = c_wh0[i];
  for (i = 0; i < HIDDENNO; i++)            wb0[i] = c_wb0[i];
  for (i = 0; i < HIDDENNO * OUTPUTNO; i++) wh1[i] = c_wh1[i];
  for (i = 0; i < OUTPUTNO; i++)            wb1[i] = c_wb1[i];

フラッシュメモリのデータへのポインタをc_wb0, c_wh1,c_wb1として、L1のデータ格納場所wb0, wh1, wb1`へコピーする。これでどれくらい速くなるか。

  • 高速化処置前 : 4960983060 サイクル
  • 高速化処理後 : 4893267026 サイクル

割合にして1.5%程度だ。あんまり劇的な効果にはなっていないなあ。やはり一番大きなデータを格納できていないことが原因か。 まあ、これ以上HiFive1で巨大が画像を処理させるのはちょっと無理かな。