FPGA開発日記

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

フルスクラッチから作るニューラルネットワーク (8. 性能解析)

誤差逆伝搬法を実装してMNISTの学習と認識プログラムをC言語フルスクラッチで作る、動作するコードは完成したのだが、最終的にはこれらのコードをマイコンで実行させたいし、もっと軽くしなければならない。

また現状の問題点として、C言語で書いたプログラムとPythonで書いてある例題のプログラムの実行速度がほぼ同一ということも挙げられる。バイナリ実行とPythonスクリプト実行の速度が同一だなんて!

まず、入力ファイルを少しずつ読み込んでいくのをや止め、一気に配列に読み込んでニューラルネットワークに流し込んでいくように変更する。最初は大きめの配列を確保しているとSegmentation Faultが起きて何だろうと思っていたのだが、mallocを使うと解消した。C言語忘れすぎ。

  double hi[HIDDENNO + 1];
  double *in_data = malloc (sizeof(double) * MAXINPUTNO * INPUTNO);
  double ans_data[MAXINPUTNO];
  double o[OUTPUTNO];
  int n_of_e;

これで一応一気にファイルを読み込んで実行できるようになったが、これでも全然速くならない。

Google-Profilerを使って解析してみることにした。解析方法はコチラを参考にした。

nu-pan.hatenablog.com

プロファイリングを取りたい場所に、以下の関数を挿入してプロファイリングを取得する。

  ProfilerStart("mnist.prof");

...
  ProfilerStop();

取得したプロファイリングをGUIで表示する。

google-pprof --callgrind train_twolayernet mnist.prof > train_twolayernet.cg
kcachegrind train_twolayernet.cg &

念のため、-O3をすると関数の呼び出し関係が崩れるので省略して解析した。

f:id:msyksphinz:20170704021534p:plain

異様に単純なループだが、やはりAffineのニューロンがかなりの計算量を消費していることが分かる。この部分は完全に行列演算の部分であるため、ここをどのように実装するかが鍵になるんだろう。

さて、ここら辺を考慮しつつ、今度はマイコンで実装するために、制度を落として固定小数点での実装方法を検討していく。