MacBook Air(or Pro)でGPUを外付けしChainerを動作させるまでの手順

はじめに

本記事は、大規模な学習はクラウドで、デバックはローカルで、(ついでに小規模な学習も)と言う人向けの記事です。
目的は、Mac(MacBook AirMacBook Pro)で深層学習を行う環境を整えることになります。

グラフィックカード、深層学習用のライブラリ(Chainer)の順で、準備をします。

グラフィックカードの準備

私は、ノート型のMacを使っているので、GPUは外付けにしました。
GPUは、深層学習用のライブラリが動作するNVIDIAのGTXシリーズの中から選びます。
最近、アップルが外付けGPUを発表しましたが、AMD Radeonなので、今回の目的には合いません。
External Graphics Development Kit - Apple Developer

既製品を利用する場合

GTX 1070が搭載されているので、今回の目的にうってつけだと思います。
www.gigabyte.com

自分で組み立てる場合

私が環境を構築した当時、上記の製品は売っていなかったため、パーツを買ってきて組み立てました。
この方法は、System Integrity Protection(SIP)を無効化する必要が出てきます。気にする人は止めておきましょう。

まず、選択するのは以下の3点です。

選ぶ時のポイント

パーツ選びのポイントを解説していきます。

まずは自分の目的に沿った性能が得られるか、を考えます。
私は、画像系の深層学習も手元でちょっと動かしてみたかったので、メモリが8GByteあることと、速度面(pascalアーキテクチャでそこそこ早いもの)と言う理由で、GTX 1070を選択しました。また、akitio thunder2で動作させたかったので、short modelを選んでいます。
具体的には以下の製品を購入しました。
http://www.kuroutoshikou.com/product/graphics_bord/nvidia/gf-gtx1070-e8gb_oc_short/

  • Thunderboltに対応したPCIeの外付けボックス(enclosures)

まずは、thunderboltの2系か3系かを、選択します。
自分の利用しているMacBook Air(もしくはpro)のインタフェースに適合するのが一番良いと思います。ただ、変換コネクタもあるので、そこまで気にする必要もないですね。
(ちなみにMacBookは、そもそもthunderboltに対応していません。)
次に、選択したグラフィックカードが箱に収容できるか、と言うのも大切なポイントです。
私は、自分のMacBook Airがthunderbolt2系だったので、akitio thunder2を選びました。ただし、akitio thunder2は、小さめなので収容できるグラボに制限が出てしまうのと、電源を別に購入しないといけないので、購入する場合は注意してください。

  • 電源

そもそも、PCIeの外付けボックスに、初めから搭載されている電源の出力で賄えるのであれば、購入する必要はありません。
購入する場合、当たり前ですが、グラフィックカードの消費電力を賄えるか、を考えて購入します。
GTX 1070であれば、NVIDIAの公式HPにgraphics card powerが150Wとあるので、以下の252Wの電源を購入しました。
http://www.mouser.jp/ProductDetail/Mean-Well/GST280A12-C6P/?qs=XfZQyRplo5S6bkFXOs4q7w==
また、購入するグラフィックカードの補助給電スロットに合うように、変換コネクタも購入します。
最近のグラボは性能が良いので、PCIeの6ピンが2つもしくは、8ピンになっていると思います。
私の購入したGTX 1070は、PCIeの8ピンでした。
上記の電源であれば、PCIeの6ピンで出力するので、6ピン8ピンの変換ケーブルを購入しました。

組み立て
  • 買ってきたPCIeの外付けボックス、グラフィックカード、電源をつなぎます。
  • System Integrity Protection(SIP)を解除します。
    • Macをシャットダウンします。
    • Macの起動時に「command + Rキー」を押して、リカバリモードに入ります。
    • ターミナルを起動して、以下のコマンドを打ち込むことで無効化できます。
      • csrutil disable
    • 元に戻す時は、以下のコマンドです。
      • csrutil enable
  • Macを再起動し、以下のautomate-eGPU.shを実行します。
  • MacとPCIeのボックスを、thunderboltケーブルで接続します。
  • Macを再起動します。

「このMacについて」から「システムレポート」を呼び出し、グラフィックスカード欄に購入したグラボが記載されていれば認識されています。
f:id:marmarossa:20170903004029j:plain

深層学習用ライブラリ(Chainer)のインストール

大雑把に言うと以下のコンポーネントが必要になります。

  • CUDA toolkit
    • NVIDIAGPUGPGPU目的で使うために必要です。
    • また、XcodeとCommand-Line Toolsも必要になります。
  • cuDNNのインストール
    • GPUを深層学習用に最適化して利用するために必要です。
  • CuPy
    • CUDA上で計算を行うNumPyサブセットです。
  • Chainer
    • 深層強化学習用のライブラリです。

CUDA toolkitのインストール

cuDNNのインストール

  • NVIDIAのサイトからダウンロードします。 (要:ユーザー登録)
  • DLしたファイルを解凍し、必要なファイルをコピーします。(コピー先は、自分がCUDA toolkitをインストールした先に読み換えてください。)
    • tar xzvf (落としたcuDNNの名前).tar (cudaというディレクトリが作成される)
    • cd cuda
    • sudo cp include/* /usr/local/cuda/include/
    • sudo cp lib/* /usr/local/cuda/lib/

環境変数の設定

(ここも、各自のCUDA toolkitの場所に読み換えてください)

  • 以下を、.bash_profileに書いておきます(以下はbashの例)。
    • CUDA_PATH=/usr/local/cuda
    • PATH=$PATH:/usr/local/cuda/bin
    • DYLD_LIBRARY_PATH=/usr/local/cuda/lib:$DYLD_LIBRARY_PATH

CuPyのインストール

  • 以下のサイトを参考に、インストールします。
  • 具体的には、以下のコマンドです。
    • sudo pip install -U setuptools
    • pip install cupy --no-cache-dir
  • 既に、cupyが入っている方は、一度uninstallしてください。

Chainerのインストール

効果測定

Chainerのサンプル(chainer/examples at master · chainer/chainer · GitHub)から、mnistを選んで比較してみました。
サンプルの中のtrain_mnist.pyの実行結果です。
当たり前ですが、最終的に得られる精度に差はありません。
ただ、学習に必要な時間は、CPUが1エポック50秒程度かかっているのに対し、GPUは、5秒程度と10倍ほど高速になっているのが確認できました。

以下がCPUを使った場合の結果です。
# unit: 1000
# Minibatch-size: 100
# epoch: 20

epoch main/accuracy validation/main/accuracy elapsed_time
1 0.942133 0.9699 42.2322
2 0.97755 0.9739 86.9796
3 0.984867 0.9794 131.715
4 0.987483 0.9823 176.681
5 0.990617 0.9802 222.018
6 0.992367 0.98 276.583
7 0.992017 0.9809 324.01
8 0.994883 0.9815 370.21
9 0.995067 0.9807 417.02
10 0.99425 0.984 464.117
11 0.996317 0.9784 511.821
12 0.9959 0.9813 560.13
13 0.996567 0.9839 608.949
14 0.996033 0.9824 659.155
15 0.996433 0.9829 709.139
16 0.997783 0.9819 759.985
17 0.996917 0.9826 811.511
18 0.997167 0.9804 863.433
19 0.9971 0.9753 916.173
20 0.996767 0.982 969.896

こちらがGPUを使った場合。
# unit: 1000
# Minibatch-size: 100
# epoch: 20

epoch main/accuracy validation/main/accuracy elapsed_time
1 0.943417 0.9706 7.06982
2 0.977766 0.971 12.0191
3 0.984982 0.9796 16.8749
4 0.987398 0.9782 21.8097
5 0.991315 0.9788 26.8118
6 0.991865 0.9819 31.9384
7 0.994015 0.9802 36.8659
8 0.992449 0.9815 41.8097
9 0.994632 0.9808 46.9009
10 0.995415 0.9803 51.9401
11 0.995549 0.983 57.0252
12 0.995315 0.9814 62.0933
13 0.997849 0.9811 67.0458
14 0.996182 0.9831 72.1063
15 0.996398 0.978 77.0816
16 0.996449 0.9836 81.9985
17 0.997199 0.9809 87.0473
18 0.996616 0.9826 91.9781
19 0.998866 0.9825 96.8835
20 0.996532 0.9808 101.705