※ 画像はイメージです。
ディープラーニングと言えばTensorFlowだのKerasだのChainerだの、高級なインタフェースを持ったツールを使うケースが多いが、例えばマイコンや組み込みプロセッサなどでディープラーニングを動かしたいときは、そこまで高級な機能はいらず、C++などで簡単に記述されたCNNの実装のほうが実行しやすかったりする。
というわけで、RISC-V上で(というかFPGA上などで動いている非力なプロセッサ)でCNNを動かすことができれば面白そうだ。
「ゼロから作るディープラーニング」を見ながら位置からC++で実装してもよいけど大変そうなので、とりあえず簡単なフレームワークは無いかと探して、mojo-cnnというC++のCNN実装を見つけた。
github.com
mojo-cnn を使ってCIFAR-10を動かしたい
さっそくgit cloneして動作させてみる。環境はUbuntu 18.04 LTS上にダウンロードして試行した。
MNISTはもう飽きてしまったのでCIFAR-10を使ってみたい。ちょうとmojo-cnnにもCIFAR-10を動かすための環境がある。
単純にcloneしてビルドすると以下のようにエラーが出る。
$ git clone https://github.com/gnawice/mojo-cnn.git
$ cd mojo-cnn/example
$ make
g++ -I../mojo/ -std=c++11 -fopenmp -O3 -DMOJO_OPM -DMOJO_AVX -msse4 -mavx test.cpp -o test
In file included from test.cpp:44:0:
../mojo/mojo.h:31:0: warning: "MOJO_AVX" redefined
<command-line>:0:0: note: this is the location of the previous definition
In file included from ../mojo/network.h:38:0,
from ../mojo/mojo.h:78,
from test.cpp:44:
../mojo/layer.h:41:10: fatal error: windows.h: No such file or directory
^~~~~~~~~~~
compilation terminated.
makefile:7: recipe for target 'test' failed
make: *** [test] Error 1
#include <windows.h>
を除去しても以下のようなエラーで進まない。
diff --git a/mojo/layer.h b/mojo/layer.h
index 4abef77..1e2e773 100644
--- a/mojo/layer.h
+++ b/mojo/layer.h
@@ -38,7 +38,7 @@
namespace mojo
{
-#include <windows.h>
+// #include <windows.h>
/*
double PCFreq = 0.0;
__int64 CounterStart = 0;
g++ -I../mojo/ -std=c++11 -fopenmp -O3 -DMOJO_OPM -DMOJO_AVX -msse4 -mavx test.cpp -o test
In file included from test.cpp:44:0:
../mojo/mojo.h:31:0: warning: "MOJO_AVX" redefined
<command-line>:0:0: note: this is the location of the previous definition
In file included from ../mojo/mojo.h:76:0,
from test.cpp:44:
../mojo/core_math.h: In function ‘void mojo::dotsum_unwrapped_2x2(const float*, const float*, float*, int)’:
../mojo/core_math.h:178:2: error: ‘_mm256_zeroupper’ was not declared in this scope
_mm256_zeroupper();
^~~~~~~~~~~~~~~~
../mojo/core_math.h:178:2: note: suggested alternative: ‘_mm_setzero_pd’
_mm256_zeroupper();
...
どうもLinux環境だとAVXのIntrinsicが使えないようなので、これを使わないようにしよう。
- AVX / SSE を使うオプションを削除する。またVGGはOpenCVを使うので除去した。
diff --git a/examples/makefile b/examples/makefile
index ee79729..70267b4 100644
--- a/examples/makefile
+++ b/examples/makefile
@@ -1,7 +1,7 @@
CC=g++
-CFLAGS_OMP= -I../mojo/ -std=c++11 -fopenmp -O3 -DMOJO_OPM -DMOJO_AVX -msse4 -mavx
+CFLAGS_OMP= -I../mojo/ -std=c++11 -O3
-all: test train_mnist train_cifar vgg
+all: test train_mnist train_cifar
test: test.cpp
$(CC) $(CFLAGS_OMP) test.cpp -o test
--- a/mojo/mojo.h
+++ b/mojo/mojo.h
@@ -28,8 +28,8 @@
#pragma once
-#define MOJO_AVX // turn on AVX / SSE3 / SIMD optimizations
-#define MOJO_OMP // allow multi-threading through openmp
+// #define MOJO_AVX // turn on AVX / SSE3 / SIMD optimizations
+// #define MOJO_OMP // allow multi-threading through openmp
//#define MOJO_LUTS // use look up tables, uses more memory
//#define MOJO_CV3 // use OpenCV 3.x utilities
//#define MOJO_CV2 // use OpenCV 2.x utilities
これでコンパイルできるようになったのでだが、次にトレーニングデータとしてCIFAR-10のデータセットをダウンロードしてこなければならない。
$ cd ../data/
$ curl -L http://www.cs.toronto.edu/~kriz/cifar-10-binary.tar.gz | tar xvz
これでシミュレーションを開始しよう。
$ ./train_cifar
== Network Configuration ====================================================
0 : I1 : input 32 32 3 identity
1 : C1 : convolution 3 16 1 elu
2 : P1 : semi_stochastic_pool 3 3
3 : C2 : convolution 3 64 1 elu
4 : P2 : semi_stochastic_pool 4 4
5 : FC2 : fully_connected 10 softmax
I1-C1, C1-P1, P1-C2
C2-P2, P2-FC2
== CIFAR-10 Epoch 1 =============================================== 0:00:00
mini batch: 16
training time: 236.644 seconds on 1 threads
model updates: 1805 (37% of records)
estimated accuracy: 43.39%
testing: 20% (13sec remaining)
...
== CIFAR-10 Epoch 129 ============================================= 7:00:58
mini batch: 16
training time: 175.415 seconds on 1 threads
model updates: 1061 (26% of records)
estimated accuracy: 68.424%
test accuracy: 67.69% (32.31% error)
saved model: ../models/snapshots/tmp_129.txt
== CIFAR-10 Epoch 130 ============================================= 7:04:10
mini batch: 16
training time: 175.767 seconds on 1 threads
model updates: 1061 (26% of records)
estimated accuracy: 68.426%
test accuracy: 67.69% (32.31% error)
saved model: ../models/snapshots/tmp_130.txt
== CIFAR-10 Epoch 131 ============================================= 7:07:23
mini batch: 16
training time: 175.754 seconds on 1 threads
model updates: 1062 (26% of records)
estimated accuracy: 68.436%
test accuracy: 67.66% (32.34% error)
saved model: ../models/snapshots/tmp_131.txt
Elvis just left the building. No further improvement in training found.
Stopping..
EPOCH 131までかかってる... しかも7時間も。さすがにAVXもなし、GPUもなしというのでかなりきつい。
でもとりあえず純粋C++で動いているので、RISC-Vとかほかのプラットフォームに移植しやすそうだし改造も簡単そうだ。