Calendar」の12日目の記事です。GTX960」を積んだデスクトップマシンを使ってきました。GTX960」は、GPUだけあってちゃんと使えばCPUより格段に速いのですが、最高の性能というわけではありません。Purpose)GPUや、複数のGPUで計算を並列化する「マルチGPU」に憧れがないと言えば嘘になります。GPUの1枚の価格や電気代、排熱の処理を考えると現実的でないと言う結論に落ち着いていました。今回、さくらインターネットの高火力コンピューティングが試用できたので、やってみたことをまとめます。本レポートは、10月5日から12日までの「高火力コンピューティング」試用期間中の取り組みを元にしています。記事の内容が現在の状況(初期状態)とは異なる場合があります。使用したTensorFlowのバージョンは0.10です。本エントリに掲載しているのコードは、拙著「TensorFlowはじめました」の増補改訂版の第4章の内容に準拠しています。コードの全体については、下記URLからダウンロードできます。朝、トライアル用のアカウントの認証情報(「アカウント名」と「パスワード」)が送られてきました。指定されたURLを開いて認証情報を入力すると、専用サーバーのコントロールパネルが表示されます。「TITANx4」の文字が頼もしいですね。ストレージに480GBのSSDが2基搭載されているので、巨大なデータセットにも十分に対応できそうです。(64bit)」がインストールされていました。認証情報を通知するメールには「GPUドライバはインストールされていません」とあったのですが、僕の場合は最初からGPUが使える状態になっていました。Pythonといくつかのパッケージ、CUDA(7.5)とCuDNN(5.1)、TensorFlow(0.10.0)をインストールすれば準備は完了です。学習(CIFAR-10)準備ができたので、さっそく学習をしてみます(train_vgg_adam_minibatch_distort_multi_gpus.py)。11.82GiB使ってみると確かに速いのですが、期待したほどではないという感じでした。sec/batch)きちんとしているつもりで実はGPUが働いていなかったということは前にもあったので、nvidia-smiコマンドで確認してみます。|+-------------------------------+----------------------+----------------------+ごらんの通り、GPUが一つしか動作していません。TensorFlowで複数のGPUを使うには、コード側を変更する必要があります。マルチGPUへの対応オリジナルのCIFAR-10チュートリアルのcifar10_multi_gpu_train.pyを参考に、マルチGPUで動作するようにコードを変更します。勾配の計算tf.deviceでそれぞれオペレーションを実行するデバイスを指定します。サンプルでは引数--num_gpusに指定した数のGPU上で、それぞれ勾配(gradients)の計算を行っています。それぞれのグラフの名前が重複しないように、tf.name_scopeで名前空間を区切っています。tower_grads.append(grads)この段階では実際の計算は行われていません。tower_gradsには、それぞれのGPU(tower)の計算オペレーションが格納されています。学習(訓練)最後に、勾配を使って学習を行います。name='train')ご覧の通り、それぞれのGPUで計算した勾配を_average_gradients関数に与えています。マルチGPUに対応しないコードでは、求めた勾配をそのまま学習に使っていました。global_step=global_step)に置き換えることができます。マルチGPUの場合、勾配を求める処理がそれぞれのGPUで行われるので、学習前に平均値を計算します。_average_gradientsは、勾配の平均を計算する計算グラフを追加する関数です。average_grads実行マルチGPUに対応したコードを実行すると、次のようになります。sec/batch)処理速度は、単純に約4倍になりました。nvidia-smiを実行すると、すべてのGPUが動作しているのがわかります。|+-------------------------------+----------------------+----------------------+すべてのGPUが動作しているのですが、少しばらつきがあります。0番目のGPUの利用率が高く、他のGPUの利用率が低い気がします。前の変更では、データの読み込み(Cifar10Reader)とミニバッチにまとめる処理(tf.train.batch)についてはGPUを指定しませんでした。データの読み込み処理などの「インプットパイプライン」は、0番目のGPUでのみ実行されていて、そのため負荷にばらつきが出ていると考えました。そこでインプットパイプラインも、それぞれのGPUで実行するように変更しました。変更後のコードを実行した結果、nvidia-smiの結果は次のようになりました。|+-------------------------------+----------------------+----------------------+それぞれのGPUの負荷のばらつきは抑えられ、それに伴ってサンプルの処理速度も上がりました。GPUの利用率100%には到達しませんでした。試しにバッチサイズを、それまでの64から128に変更しても、あまり大きな変化はありませんでした。X」の処理能力を最大限引き出すほどの負荷を与えられなかったためと考えています。|+-------------------------------+----------------------+----------------------+終わりにいかがだったでしょうか。さくらインターネットの高火力コンピューティング、凄さの片鱗こそ見えたものの、僕の力不足で火力を上げることができないまま、試用期間が終わってしまいました。GTX960」のメモリ(2GB)に納めるのに苦労しています。バッチサイズを減らしたりモデルの軽量化を頑張ってようやくメモリに収まっても1ステップにかかる学習の負荷が大きく、学習は遅々として進みません。Calendar」13日目の担当はkatsugenerationさんです。katsugenerationさん、よろしくお願いします。