Intel Chainerを使ってみる
Disclaimer: まだまだExperimentalな状態のものを勝手に使っているだけなので、ちゃんとすべての性能をひきだせていない可能性があります。また、導入手順も変更がある可能性が高いです。
Intel Chainerとは
Intelが公式でChainerからforkした、Intel CPU向けの最適化を施したChainerです。最近Chainer公式などでも言及されるようになりました。
Intel Chainerをインストールする
Prerequisite
今回は2018/1/1当時のmaster_v3ブランチを使います。
環境はUbuntu 16.04、gcc (Ubuntu 5.4.0-6ubuntu1~16.04.5)で、Python 3.5.31で新しいpyenv virtualenv環境を使っています。
CPUはIntel(R) Core(TM) i5-4258U CPU @ 2.40GHz
で、ぎりぎりMKL-DNNの対象内です。(なお、MKL-DNNはXeon/Xeon Phiを主ターゲットとしているため、この条件ではMKL-DNNを活かしきれていない可能性があります。)
インストール手順
必要ライブラリをインストールします。
setup.py
から直接必要なライブラリをインストールする形式になっているので、インストールするライブラリは最小限ですみます。
sudo apt install swig3.0
pip install protobuf numpy six filelock
Intel Chainerをダウンロードします。
git clone https://github.com/intel/chainer.git intel-chainer
cd intel-chainer
git checkout 537484c0113c790fd09affbcd97fa20e9bf6da77
gcc5.4と、現時点でIntel Chainer同梱のMKL-DNNのだとバグを踏むため、異なるバージョンのMKL-DNNを指定します。
diff --git a/dnn_setup.py b/dnn_setup.py
index 0805379..79f9139 100644
--- a/dnn_setup.py
+++ b/dnn_setup.py
@@ -9,7 +9,7 @@ subdir = 'mkldnn'
# Sepcify prefix under which you put ipl_mkldnn
# prefix = '/usr/local'
mkldnn_root = external.mkldnn.root()
-mkldnn_version = 'ba482eca9459e3b9a8256ab07f9afa41dba34b9e'
+mkldnn_version = 'v0.12'
def prepare_mkldnn():
python setup.py install
を実行してインストールします。指定のインストール場所他、~/.chainer/lib
と~/.chainer/include
に関連ライブラリがインストールされます。
試してみる
MNIST
まずはhello worldというということでmnistです。examples/mnist
にてpython train_mnist.py
を実行します。本例はLinear/ReLUから構成されています。
Time (s)2 | Validation loss | |
---|---|---|
Intel Chainer | 547.4 | 0.109 |
Normal Chainer | 671.7 | 0.0982 |
うーーーーーん、微妙です。
MKL-DNNの詳細はしらないのですが、通常RNN/CNNのほうが工夫しやすいので、RNN/CNNのほうが差がでるかも?
CIFAR
examples/cifar
にてpython train_mnist.py -g -1
を実行します。
本例はCNN/BN/max pooling/ReLUから構成されます。
Time (s)3 | Validation loss | |
---|---|---|
Intel Chainer | 1413 | 2.08 |
Normal Chainer | 3966 | 2.15 |
このくらいになってくれると気持ちがよいですね。実に**0.36%**の時間で済んでいます。これくらい差があれば、導入するメリットがありそうですね。
PTB
examples/ptb
にてpython train_ptb.py
を実行します。本例はEmbedID/LSTM/Linearから構成されます。
Time (s)4 | Train loss | |
---|---|---|
Intel Chainer | 2598 | 6.54 |
Normal Chainer | 2312 | 6.53 |
あれれ・・・むしろ遅くなっていますね。適当にググってみたところ、MKL-DNNでは現状LSTMはサポートしてなさそうなので、当然Intel Chainerで速くなるわけない、といったところでしょうか。
なお、EmbedID
がそのままでは動かなかったので、次のような変更を加えています。
--- a/chainer/functions/connection/embed_id.py
+++ b/home/koreyou/.pyenv/versions/intel-chainer/lib/python3.5/site-packages/chainer/functions/connection/embed_id.py
@@ -72,8 +72,11 @@ class EmbedIDGrad(function_node.FunctionNode):
if xp is numpy:
# It is equivalent to `numpy.add.at(gW, x, gy)` but ufunc.at is
# too slow.
- for ix, igy in six.moves.zip(x.ravel(),
- gy.reshape(x.size, -1)):
+ x_ravel = x.ravel()
+ gy_reshape = gy.reshape(x.size, -1)
+ for i in six.moves.xrange(len(x_ravel)):
+ ix = x_ravel[i]
+ igy = gy_reshape[i]
if ix == self.ignore_label:
continue
gW[ix] += igy