Monthly Archives: 8月 2014

(22) cuda-convnet2はやってみれない (T_T)

2014年7月17日、cuda-convnet の作者が cuda-convnet2 なるプログラムをGIT上に公開した。
現在も開発が進行中で、その様子はこちら(↓)で眺められる。
https://github.com/akrizhevsky/cuda-convnet2
20140822_01

これはぜひやってみよう!

と意気揚々とプログラムをダウンロードし、
  必要なライブラリをインストールし、
    ビルドが成功し、

いざ実行!

=========================
Running on CUDA device(s) 0
Current time: Fri Aug 22 21:51:07 2014
Saving checkpoints to /home/user/cuda/cuda-convnet2/save/cifar-10/ConvNet__2014-08-22_21.51.06
=========================
src/nvmatrix.cu(394) : getLastCudaError() CUDA error : kSetupCurand: Kernel execution failed : (8) invalid device function .

エラーで止まった (TT)

いろいろ調べると、コンパイル時に指定した Compte Capability version が、
マシンに搭載している GPUと合っていないことが原因のようだ。

そこで…
うちの新しい GTX-760 の Compute Capabilityを調べてみる。
これには NVIDIA_CUDA-6.0_Samples に付属の deviceQuery コマンドが使える。

[user@]$ ./deviceQuery
./deviceQuery Starting...

 CUDA Device Query (Runtime API) version (CUDART static linking)

Detected 1 CUDA Capable device(s)

Device 0: "GeForce GTX 760"
  CUDA Driver Version / Runtime Version          6.0 / 6.0
  CUDA Capability Major/Minor version number:    3.0
  Total amount of global memory:                 2047 MBytes (2146762752 bytes)
  ( 6) Multiprocessors, (192) CUDA Cores/MP:     1152 CUDA Cores
  GPU Clock rate:                                1058 MHz (1.06 GHz)
  Memory Clock rate:                             3004 Mhz
  Memory Bus Width:                              256-bit
  L2 Cache Size:                                 524288 bytes
 :

うちのは Compute Capability version 3.0 なのだそうだ。

では、cuda-convnet2 を Compute Capability ver.3.0 指定でビルドしてみる。
MakeFile中で以下のように書かれているところを探し、すべて3.0指定に書き換えた。

GENCODE_SM35    := -gencode arch=compute_35,code=sm_35
GENCODE_FLAGS   := $(GENCODE_SM35)

再度ビルドを実行する。

[user@]$ ./build.sh clean
[user@]$ ./build.sh

今度こそは!
と cuda-convnet2 で Cifar-10 自動認識を起動!

すると…

さっきよりもヤバゲなエラーが出た (T^T)

=========================
Running on CUDA device(s) 0
Current time: Fri Aug 22 22:00:59 2014
Saving checkpoints to /home/user/cuda/cuda-convnet2/save/cifar-10/ConvNet__2014-08-22_22.00.58
=========================
1.1 (0.00%)...python: src/nvmatrix.cu:1473: virtual cudaTextureObject_t NVMatrix::getTextureObject(): Assertion `_texObj != 0' failed.
Error signal 6:
/home/user/cuda/cuda-convnet2/cuda-convnet2/cudaconvnet/_ConvNet.so(_Z13signalHandleri+0x26)[0x7fb5b9f2a3e6]
/lib64/libc.so.6[0x35e22329a0]
/lib64/libc.so.6(gsignal+0x35)[0x35e2232925]
/lib64/libc.so.6(abort+0x175)[0x35e2234105]
/lib64/libc.so.6[0x35e222ba4e]
/lib64/libc.so.6(__assert_perror_fail+0x0)[0x35e222bb10]
./nvmatrix/libnvmatrix.so(_ZN8NVMatrix16getTextureObjectEv+0x147)[0x7fb5b8c15f67]
./cudaconv3/libcudaconv.so(_Z11_filterActsR8NVMatrixS0_S0_iiiiiiiffb+0x5c25)[0x7fb5b7f984e5]
./cudaconv3/libcudaconv.so(_Z14convFilterActsR8NVMatrixS0_S0_iiiiiiiff+0x30)[0x7fb5b7f9dd30]
/home/user/cuda/cuda-convnet2/cuda-convnet2/cudaconvnet/_ConvNet.so(_ZN9ConvLayer9fpropActsEifji+0x18e)[0x7fb5b9ee5d8e]
/home/user/cuda/cuda-convnet2/cuda-convnet2/cudaconvnet/_ConvNet.so(_ZN5Layer5fpropERSt3mapIiP8NVMatrixSt4lessIiESaISt4pairIKiS2_EEEji+0x240)[0x7fb5b9ef2ab0]
/home/user/cuda/cuda-convnet2/cuda-convnet2/cudaconvnet/_ConvNet.so(_ZN5Layer5fpropEji+0x23f)[0x7fb5b9ef2d4f]
/home/user/cuda/cuda-convnet2/cuda-convnet2/cudaconvnet/_ConvNet.so(_ZN13ConvNetThread3runEv+0x17d)[0x7fb5b9f44d6d]
/home/user/cuda/cuda-convnet2/cuda-convnet2/cudaconvnet/_ConvNet.so(_ZN6Thread18start_pthread_funcEPv+0x9)[0x7fb5b9ef7b69]
/lib64/libpthread.so.0[0x35e26079d1]
/lib64/libc.so.6(clone+0x6d)[0x35e22e8b5d]
CUDA error at src/nvmatrix.cu:522 code=29(cudaErrorCudartUnloading) "cudaSetDevice(d)"
Error signal 11:
/home/user/cuda/cuda-convnet2/cuda-convnet2/cudaconvnet/_ConvNet.so(_Z13signalHandleri+0x26)[0x7fb5b9f2a3e6]
/lib64/libc.so.6[0x35e22329a0]
/lib64/libc.so.6(exit+0x35)[0x35e2235d75]
./nvmatrix/libnvmatrix.so(+0x30886)[0x7fb5b8c15886]
/home/user/cuda/cuda-convnet2/cuda-convnet2/cudaconvnet/_ConvNet.so(_ZN14DataCopyThread3runEv+0x4ac)[0x7fb5b9ee3b9c]
/home/user/cuda/cuda-convnet2/cuda-convnet2/cudaconvnet/_ConvNet.so(_ZN6Thread18start_pthread_funcEPv+0x9)[0x7fb5b9ef7b69]
/lib64/libpthread.so.0[0x35e26079d1]
/lib64/libc.so.6(clone+0x6d)[0x35e22e8b5d]

エラーの内容を見ると、どうやらうちのGTX760では未サポートの機能を使おうとしている様子…

そこで cuda-convnet2 のホームページを改めて見てみると…
20140822_02

Compute Capability 3.5以上じゃないとダメ

と書いてあった…

2014年8月現在、GTX780を手に入れるには 6万円前後のお金が必要だ…
先日Xeon x5570 x2 マシンを 6万円で購入したので、手元にお金は残っていない…

cuda-convnet2 はヤフオクで GTX780が2万円台に値下がりするまでしばらくあきらめよう(T^T)


参考情報

CUDA ZONEのページに GPU型番別の Compute Capavility Version一覧が載っている。
https://developer.nvidia.com/cuda-gpus20140822_03

(21) GTX650からGTX760に変えてみる

ヤフオクを眺めていたらよさげなワークステーションが安価で出品されていたのでこれを購入した。
スペックは以下の通り。これで6万円弱は安い!
・CPU: Xeon X5570 x 2個 (全16core)
・memory: 24GB
・GPU: Quadro 4000

このワークステーション、電源にも余裕があるので GPU2枚組を目論んで 2万円弱のGTX760も落札した。
今使っているGTX650のCudaCore数が384個、これに対してGTX760は1152個、なんと3倍!

比較その1: cuda-convnet

まずはcuda-convnetで速度性能を比較してみた。
対象は (15) cuda-convnetでMNIST自動認識(その2) で動かしたちょっとリッチなネットワークを100epochsとした。

結果1: 旧マシン(intel core-i3 3220, GTX650)

START: 2014年  8月 18日 月曜日 15:23:48 JST
======================Test output======================
logprob:  0.034047, 0.010900
END:   2014年  8月 18日 月曜日 15:30:26 JST

100epochsの処理時間は 398秒 、エラー率は 0.011だった。

結果2: 新マシン(intel Xeon x5570 x 2, GTX760)

START: 2014年  8月 18日 月曜日 15:24:10 JST
======================Test output======================
logprob:  0.034883, 0.010300
END:   2014年  8月 18日 月曜日 15:26:47 JST

100epochsの処理時間は 157秒 、エラー率は 0.010だった。

両者の処理時間の差は 398 : 157 だから 2.5 : 1 だった。
約8万円の投資で2.5倍に高速化した。 微妙…

比較その2: Caffe

次に caffeで速度性能を比較してみた。
対象は (20) CaffeでMNIST自動認識(その1) で動かしたCaffe付属サンプル 10,000batchesとした。

結果1: 旧マシン(intel core-i3 3220, GTX650)

I0813 20:23:56.937985  4618 solver.cpp:165] Solving LeNet
I0813 20:23:56.937995  4618 solver.cpp:232] Iteration 0, Testing net (#0)
I0813 20:23:58.769482  4618 solver.cpp:270] Test score #0: 0.0427
I0813 20:23:58.769534  4618 solver.cpp:270] Test score #1: 2.30319
======================Test output======================
I0813 20:30:07.157430  4618 solver.cpp:270] Test score #0: 0.9911
I0813 20:30:07.157462  4618 solver.cpp:270] Test score #1: 0.0283371
I0813 20:30:07.157470  4618 solver.cpp:218] Optimization Done.
I0813 20:30:07.157475  4618 caffe.cpp:102] Optimization Done.

10,000batchesの処理時間は 371秒 、正解率は 99.1%だった。

結果2: 新マシン(intel Xeon x5570 x 2, GTX760)

I0820 07:33:07.595406  9520 solver.cpp:165] Solving LeNet
I0820 07:33:07.595415  9520 solver.cpp:232] Iteration 0, Testing net (#0)
I0820 07:33:08.551427  9520 solver.cpp:270] Test score #0: 0.0566
I0820 07:33:08.551476  9520 solver.cpp:270] Test score #1: 2.30261
======================Test output======================
I0820 07:36:17.788245  9520 solver.cpp:270] Test score #0: 0.9914
I0820 07:36:17.788260  9520 solver.cpp:270] Test score #1: 0.0278619
I0820 07:36:17.788269  9520 solver.cpp:218] Optimization Done.
I0820 07:36:17.788275  9520 caffe.cpp:102] Optimization Done.

10,000batchesの処理時間は 189秒 、エラー率は 99.1%だった。

両者の処理時間の差は 371 : 189 だから 1.96 : 1 だった。
約8万円の投資で1.96倍に高速化した。 微妙…

PS.
GPU2枚組を目論んだが、GTX760が補助電源を2口も使ってしまい、電源コネクタが不足…
残念ながら古いQuadroは外すことになった…
今度差し替えてQuadroでも計測してみよう。

(20) CaffeでMNIST自動認識(その1)

(19) Caffeをインストール で Caffeがインストールできた。
今回は Caffe に付属しているサンプルを使って実際に Caffeを GPU上で動作させてみる。

なんと!
Caffeの実行サンプルには MNIST用トレーニング環境 が付属している。

このサンプルの使用手順は、以下のページに詳しく書かれている。
http://caffe.berkeleyvision.org/gathered/examples/mnist.html
20140813_04

(1) MNISTデータをダウンロード

まずはMNISTデータをダウンロードする。
Caffeを GITで取得&展開したディレクトリを CAFFE_ROOT とすれば、
$CAFFE_ROOT/data/mnist
にMNISTデータをダウンロードしておく。

この作業は get_mnist.sh に書かれているので、このスクリプトを実行すればよい。

$ cd $CAFFE_ROOT/data/mnist
$ ./get_mnist.sh

自分の作業環境の場合、先に (1) MNIST画像データをダウンロード で同データをダウンロード済みなので、今回この作業はいらない。

(2) トレーニング用データを作成

Caffeでは、MNISTデータを Caffeの入力データ形式に変換するプログラムを提供してくれている。
このプログラムの実行は create_mnist.sh に書かれている。

$ cd $CAFFE_ROOT/example/mnist
$ ./create_mnist.sh

このスクリプトを実行した結果、以下のように学習データ、テストデータの LevelDB が作られた。
LevelDBは googleが公開している key-value形式の汎用データストアプログラムだ。

$ ls -F | grep /
mnist-test-leveldb/
mnist-train-leveldb/

(3) トレーニング開始

チュートリアルのページには、超パラメーターの記述方法の説明が書かれている。
これらは後で熟読するとして、まずはトレーニングを実行してみたい。
トレーニング実行は train_lenet.sh に書かれている。

$ cd $CAFFE_ROOT/example/mnist
$ ./train_lenet.sh

このスクリプトの中身はこれ(↓)だけ。caffe実行プログラム caffe を起動している。

TOOLS=../../build/tools
$TOOLS/caffe train --solver=lenet_solver.prototxt

(4) トレーニング実行中

トレーニング実行中はトレースログが表示される。表示内容は以下の通り。

Iteration N, loss N batchの学習データの loss function value
Iteration N, lr N batchの learning rate
Test score #0 テストデータの正解率(0.0 ~ 1.0)
Test score #1 テストデータの loss function value

実際の表示内容はこちら(↓)

I0813 20:23:56.937985  4618 solver.cpp:165] Solving LeNet
I0813 20:23:56.937995  4618 solver.cpp:232] Iteration 0, Testing net (#0)
I0813 20:23:58.769482  4618 solver.cpp:270] Test score #0: 0.0427
I0813 20:23:58.769534  4618 solver.cpp:270] Test score #1: 2.30319
I0813 20:23:58.802779  4618 solver.cpp:195] Iteration 0, loss = 2.30285
I0813 20:23:58.802830  4618 solver.cpp:365] Iteration 0, lr = 0.01
I0813 20:24:02.135016  4618 solver.cpp:195] Iteration 100, loss = 0.339029
I0813 20:24:02.135049  4618 solver.cpp:365] Iteration 100, lr = 0.00992565
I0813 20:24:05.467381  4618 solver.cpp:195] Iteration 200, loss = 0.172438
I0813 20:24:05.467414  4618 solver.cpp:365] Iteration 200, lr = 0.00985258
I0813 20:24:08.799804  4618 solver.cpp:195] Iteration 300, loss = 0.197514
I0813 20:24:08.799839  4618 solver.cpp:365] Iteration 300, lr = 0.00978075
I0813 20:24:12.132412  4618 solver.cpp:195] Iteration 400, loss = 0.0895801
I0813 20:24:12.132447  4618 solver.cpp:365] Iteration 400, lr = 0.00971013
I0813 20:24:15.431949  4618 solver.cpp:232] Iteration 500, Testing net (#0)
I0813 20:24:17.205533  4618 solver.cpp:270] Test score #0: 0.9634
I0813 20:24:17.205569  4618 solver.cpp:270] Test score #1: 0.110554

(5) トレーニング終了

付属のMNISTサンプルの繰り返しトレーニング回数は 10,000[batch]だった。※10,000[epoch]ではない!
これは lenet_solver.prototxtmax_iter: 10000 で指定されている。
10,000[batch]終了時の最終結果は以下の通り。

テストデータの正解率は 99.1% と高い!

I0813 20:30:05.385545  4618 solver.cpp:287] Snapshotting to lenet_iter_10000
I0813 20:30:05.389729  4618 solver.cpp:294] Snapshotting solver state to lenet_iter_10000.solverstate
I0813 20:30:05.403728  4618 solver.cpp:213] Iteration 10000, loss = 0.00444134
I0813 20:30:05.403760  4618 solver.cpp:232] Iteration 10000, Testing net (#0)
I0813 20:30:07.157430  4618 solver.cpp:270] Test score #0: 0.9911
I0813 20:30:07.157462  4618 solver.cpp:270] Test score #1: 0.0283371
I0813 20:30:07.157470  4618 solver.cpp:218] Optimization Done.
I0813 20:30:07.157475  4618 caffe.cpp:102] Optimization Done.

Caffeでは繰り返し数をbatch数で指定する(EPOCH数では指定しない)

その理由は、こちらのページでCaffe開発者の方が言及されている。
https://github.com/BVLC/caffe/issues/59
20140824_01

付属のMNIST学習サンプルの場合、繰り返し数は lenet_solver.prototxtmax_iter: 1000010000[batch] に設定されている。1バッチの画像データ枚数は lenet_train_test.prototxtbatch_size: 64 で、TRAIN用は 64[images] に設定されている。

このことから…
MNISTの学習用データが 50,000枚 なので、1[epoch]は 50,000 ÷ 64781[batch] となる。
繰り返し回数指定が 10,000[batch] なので、10,000 ÷ 78112[epoch] となる。
※max_iter:10000は、10000epochではないのだ。

(19) Caffeをインストール

(18) GPU実装版の機械学習ツール に記したツールの中で、一番上に書かれている
Caffe なるツールを試してみたい。

公式サイトはここ(↓)
http://caffe.berkeleyvision.org/
20140813_02

インストール

Installation instructions のページに書かれている手順に従い、依存するライブラリ類からインストールする。
いつものように「あれがない、これがない」への対応が続く…
http://caffe.berkeleyvision.org/installation.html

確認

インストール完了後、make runtest でテストする。
718テストが成功しているので問題なしか?

20140813_03

次回は実際にトレーニングを動かしてみたい!

(18) GPU実装版の機械学習ツール

NVIDIAのmachine learningのページには、GPU実装版の機械学習ツールが紹介されている。
先に試してみた cuda-convnet もこの中の一つだ。

以下のページの中段に7種類が紹介されている。
http://www.nvidia.com/object/machine-learning.html
20140813_01

cuda-convnet以外のものも試してみよう!