ひとことで言うと
格安ゲーミングPC(Windows)を購入して、
Anacondaの仮想環境でCPU/GPUを切り替えられるようにして、
Tensorflow-GPU(v2.0)のコードを動かして、
ColaboratoryのCPU/GPUも含めた4パターンで、
性能比較をしてみたよ。
性能比較結果とWindows版環境構築手順をまとめておくね。という記事。
- 機械学習にはGPUが有効だよ、ってよく聞く
- ゲーミングPCにはGPUがある、そして最近安い
⇒ ゲーミングPCのGPUを機械学習に使ってみよう!
ということで、Windows上でのGPU環境構築を実施したが、
ハマりどころが多く大変だった。
欲しいゲーミングPCを「機械学習用だから!」と言って
買う言い訳になる決定版としての記事。
GPUの性能の違いが、学習時間の決定的差になるということを・・・教えてやる!
機械学習GPU環境の5つの選択肢と、私見
GPU有り自作PCにubuntu
- 機械学習ガチ勢にオススメ、高性能
- 高額になりがち(全て合わせると30万円くらい?)
普段使いのWindowsやMacと別に買うとさらに大きな出費- 王道であるため、動かしやすさ的にも良い
- ※ゲーミングPCのOSから入れ替えるパターンもコレ
Google Colaboratory
- 初心者のお試し~上級者まで幅広く対応
- 無料で、高性能GPUが使える
- セットアップの手間いらず。Driveとの連携も便利
- 一定時間ごとのリセットは気になる
- Windows/Mac/Chromebookでもどこからでも使える!
NVIDIA Jetson Nano
- 中級者以上。または、初心者のお試しでも面白い
- 低価格(2万円くらい)だが性能もそれなり
- GPUメモリの上限で学習出来る上限が違う点は要注意
- 本体だけは安いが周辺機器も0から揃えると面倒
- IoT機器としての利用目的ならコレ一択
- (どちらかというと学習用よりPredict用な気がする)
GPU版のクラウドインスタンス or サービス利用
- 従量課金なので初心者向けと思わせて実は違う
- 実行環境として使う場合、クラウド破産に注意
- 簡単な開発環境として使う場合、ロックオンされがち
- サービスにより様々
ゲーミング(ノート)PC
- ダークホース的存在。通常はWindowsなのをどう見るか?
- 筐体の価格は、セット販売なので同性能での比較なら安い
- 10万円~30万円くらい?
- 機械学習以外の用途にも使うならばコレ一択
というか、ゲームにも使うなら100%コレしかない
Why ゲーミングノートPCでやるの??
個人的にデスクトップよりもノート派で、別目的のマシンを
機械学習へも転用するため、ということで答えが出ているが
PCを購入するタイミングで試してみたいという遊び心。
特に機械学習のガチ勢でもないので高額高性能なマシンは不要。
最安値クラスのゲーミングノートPC(10万円ほど)を購入して、
機械学習にも使ってみると、
どんな感じの使い勝手になるのか?を勉強がてら試した。
Colaboratoryが素晴らしいとはいえ、用途によっては
12時間で切れないローカル環境も有用であるとも考えられた。
本稿の記載目的
先駆者が多そうな気がしたが、
意外と大変だったためまとめておく。
機械学習 ⇒ GPU
GPU ⇒ ゲーミングPC
というイメージを持つ人は多いだろう。
最近はゲーミングPCも安くなってきていて、
機械学習用ではなく購入したけど、転用できないかなー、
と思っている人も結構いるのではないか?
または、これからの時代は機械学習が重要なので、PC買うときには、
GPUを付けておいた方が良いかも?とか思っている人も居るかもしれない。
実際、ちょっとGPUが付いたノートPC、も増えてきている。
しかし、本稿のようにこの三つを紐づけた情報はかなり少ないという印象。
機械学習の上級者は当然ubuntu上での話が多く、
一方で、ゲーミングPCを転用しようなどという
私を含めた不届きな初心者が、
Windows上で環境構築するのはハマりやすく大変なためだろう。
また、機械学習系の環境変化は激しく、
Tensorflow2系の情報は、1系よりもまだだいぶ少ない。
そこで、本稿のような
Windows × GPU × Tensorflow2.0 × Anaconda
の環境構築手順をまとめておいても良いと考えた。
また、Colaboratoryとの性能比較含めて、
他の環境でも転用できる情報やコードも多い。
予想以上に大変だったので同様にハマる人への一助になれば。
初心者の情報交換としての記事。
始める前から、重大な誤算有り
機械学習環境の構築は、
ubuntu上、Dockerが楽である、という評判と、
「WSL2」によってWindowsでもDockerが動かしやすい、
という話を聞いて、結構簡単に作れるかも?と誤解していた。
実は、WSL2は2020年3月時点では、GPUデバイスに対応していない。
(★2020/06追記:WSL2のGPU対応は正式に追加されました。)
(Windows 10 Insider Preview Build 20150 以降のバージョンで利用可能)
そのため、GPU利用環境はWindowsベースで構築する必要がある。
ただし、WSL2からWindowsで構築したPython環境を
呼び出し実行できるので、疑似的にWindows上で
ubuntuやDocker利用環境のように使うことは可能。
※本稿ではWSL2の話は記載しない
今回結局Windows上で素で構築することになって大変だった。
なお、もしこれからマシンを購入しようとしている場合、
NVIDIA製のGPUにしておくことは
情報量的な意味でほぼ必須なので注意。
NVIDIAのノートPC向けの主要なGPUの性能は
良い方から順番に以下の感じ。
まずコレが初心者には超分かりにくい
- GeForce RTX 2080
- GeForce RTX 2070
- GeForce GTX 1070
- GeForce GTX 1660 Ti
- GeForce RTX 2060
- GeForce GTX 1080
- GeForce GTX 1060
- GeForce GTX 1650
- GeForce GTX 1050 Ti
- GeForce MX 350
- GeForce GTX 1050
- GeForce MX 250
デスクトップPC向けであれば以下の順。
- Titan RTX
- GeForce RTX 2080 Ti
- Titan V
- GeForce RTX 2080 SUPER
- Titan Xp
- GeForce RTX 2080
- GeForce GTX 1080 Ti
- Titan X
- GeForce RTX 2070 SUPER
- GeForce RTX 2060 SUPER
- GeForce GTX 1080
- GeForce RTX 2070
- GeForce GTX 1070 Ti
- GeForce RTX 2060
- GeForce GTX 980 Ti
- GeForce GTX 1070
参考: https://pcfreebook.com/article/459993300.html
今回構築した環境のバージョン情報
- Windows10 Home
- GPU = GTX1650
- Anaconda Python = 3.7
- tensorflow-gpu = 2.0.0
- CUDA = 10.0
- cuDNN = v7.6.5(cudnn-10.0-windows10-x64-v7.6.5.32)
環境構築手順の全体像
- 各ライブラリのバージョン決定方法
- Anacondaの導入 / 仮想環境やJupyterの設定方法
- Python仮想環境の構築(CPU版)
- Tensorflow2.0のサンプルコードをCPU版で流す
- Python仮想環境の構築(GPU版)
- CUDA, cuDNN, ドライバのインストール
- Tensorflow2.0のサンプルコードをGPU版で流す
- (Errorが発生して大変だった話)
- ColaboratoryのCPU/GPU版も含めて、性能比較
バージョンの決定方法(最重要)
tensorflow-gpu, CUDA, cuDNN,の
3つのバージョンを完璧に合わせる必要がある。
これを怠ると、例えば以下のような意味不明エラーの嵐に悩まされる。
UnknownError: Failed to get convolution algorithm. This is probably because cuDNN failed to initialize, so try looking to see if a warning log message was printed above.
Tensorflowの公式サイトを確認する。
https://www.tensorflow.org/install/source_windows
2020/03当時、
Tensorflow2.1.0が最新であるものの、
テスト済みのビルド構成(Windows版)では、
2.0.0が最新であったため、2.0.0を採用。
Tensorflowのコードは、1系と2系で異なる点が多いため、
実行したいコードに合わせて、1系と2系は選ぶべし。
が、以下の記載を信じて痛い目にあった。
バージョン Python バージョン コンパイラ ビルドツール cuDNN CUDA
tensorflow_gpu-2.0.0 3.5~3.7 MSVC 2017 Bazel 0.26.1 7.4 10
正解は、CUDA10.0系に対するcuDNNのバージョンは7.6系。
7.4系だと上述の意味不明エラーが生じる。
そして、このエラーには複数の原因候補があり、
バージョン違い以外のケースでも多々発生するため、
原因の切り分けの難易度が高い。
参考: https://github.com/tensorflow/tensorflow/issues/24496
※さらに、Tensorflow公式サイトのコードを
そのまま動かすだけでも上記issuesにある
追記が必要という鬼畜っぷり。
Anaconda Python3.7版のインストール
基本的にはデフォルト設定のままでインストールを進める。
CondaのPython仮想環境の使い方
CPU版/GPU版を気軽に使い分けたい、
別バージョンを試したい、などの用途だけでなく、
環境構築時のリトライのしやすさなども含めて、
Pythonの仮想環境を用いて構築を進めると良い。
Anaconda Comand Prompt 上で下記のように操作する。
# 以下のコマンドで仮想環境MyEnvNameを作る。
conda create -n MyEnvName python=3.7
# 以下のコマンドで仮想環境をアクティブにする。
conda activate MyEnvName
# ⇒コマンドラインの左側の「(base)」が、
# 「(MyEnvName)」に変わることが確認できる。
# 以下のコマンドで現在の仮想環境一覧が確認できる。
conda env list
# 以下のコマンドで対象の仮想環境を削除できる。
conda remove -n MyEnvName --all
# なお、Anaconda Navigator の左側のメニューからも見える。
上記以外のコマンドについては、下記が詳しい。
https://qiita.com/naz_/items/84634fbd134fbcd25296
Jupyterから、対象の仮想環境に接続する方法
Anaconda Comand Prompt 上で疎通をとってから最後に、
Jupyterからその仮想環境を使えるように設定するほうが望ましい。
よって本手順は最後に実施した方が良い。
(が、普段仮想環境の作成とセットで実行する場合も
多々あるため、仮想環境作成の直下に書いておく)
下記のコマンドで、Jupyter側から仮想環境が見えるようにしよう。
# ipython(Jupyter)はbaseに入っているため、
# 下記のコマンドで一度baseに戻る。
conda activate base
# --nameで仮想環境名,--display-nameで表示名を設定する。
ipython kernel install --user --name=MyEnvName --display-name=MyEnvName
# ⇒ 下記のフォルダにJupyterの接続設定が作成される。(隠しフォルダを表示すること)
# C:\Users\[ユーザ名]\AppData\Roaming\jupyter\kernels
このままも一見Jupyter側から仮想環境に繋げられるのだが、
実は下記の設定ファイルに誤りがあるために、修正が必要。
python.exeの起動パスを、Anacondaの仮想環境側に変更する。
◇対象ファイル:
C:\Users\[ユーザ名]\AppData\Roaming\jupyter\kernels\MyEnvName\kernel.json
◇修正前:
"C:\\Users\\[ユーザ名]\\anaconda3\\python.exe",
◇修正後:
"C:\\Users\\[ユーザ名]\\Anaconda3\\envs\\MyEnvName\\python.exe",
さらに、kernel.json
に記載されている呼び出し引数の、
ipykernel_launcher
を仮想環境側に追加する必要がある。
Anaconda Comand Promptで下記のように実行する。
conda activate MyEnvName
pip install ipykernel
参考:https://qiita.com/howahowa/items/480607a06264426f24ed
この状態で Anaconda Navigator ⇒ JupyterNotebookを起動すると、
「New」や新しいノートブックを作成する際に、
「Python3」だけでなく、「MyEnvName」が選択肢として増えている。
または、既にPython3で作成済みのipynbについても、
Kernel ⇒ Change kernel を選ぶと、
MyEnvName の方にkernelを変更することが出来る。
もし、Jupyterからのkernel選択実行と、
Anaconda Comand Promptの仮想環境選択実行との
結果が異なってしまう場合は、
下記のスクリプトを実行して、使っているPythonや
ライブラリなどのパスを確認すると良いだろう。
import sys
print(sys.prefix)
print(sys.path)
また、Jupyterではブラウザを閉じただけでは
裏でプロセスはまだ残っているため、
「running」のタブから実行中プロセスを確認し、
一度全てをShutdownし、
Jupyter自身も終了させてから再起動すると、
きちんと設定が反映され、正しい動作となる場合も多い。
普段においても、GPUは「占有型」でデバイスを使うようなので、
他のGPU実行プロセスを残さないように、
適宜Shutdownしておいた方が良いだろう。
Tensorflowのインストール(CPU版)
まずは、CPUのみを利用した
Tensorflow実行用仮想環境を構築し、疎通をとろう。
conda create -n cpuenv python=3.7
conda activate cpuenv
pip install tensorflow==2.0.0
備考:pipとcondaは混ぜて使わなければ、
Anacondaでもパッケージの管理は全てpipでも良い。
(どちらでも大差はない、と思う)
なお、Tensorflowの公式サイトではpip準拠である。
Tensorflowの導入後、conda list, pip list で違いを見ると、
conda のほうがtensorflow系の依存ライブラリを
頑張ってインストールしている感があるが、
特に手数が変わるわけではない。
本稿では基本はpip側で実施するが、どこかをcondaで実施する場合、
すべてをcondaで統一したほうが良い。
Tensorflow2.0の上級者向けチュートリアルコードの実行(CPU版)
1ファイルだけで完結して実行できる一発実行コードを準備する。
Tensofrflow公式の 「エキスパートのための TensorFlow 2.0 入門」
のコードをつなぎ合わせて、時間計測用のコードを挿入し、
以下のように1ファイルにまとめて実行する。
参考:https://www.tensorflow.org/tutorials/quickstart/advanced
Jupyter Notebookの設定が済んでいる場合は、
下記のコードを直接1セルに貼り付けて実行、でもOK
python tensorflow-tutorial-ex.py
# > ~~途中結果省略~~
# > 今回のCPU版での実行時間は下記の通り。
# > 実行時間:143.45523118972778[秒]
#https://www.tensorflow.org/tutorials/quickstart/advanced
#Tensofrflow公式「エキスパートのための TensorFlow 2.0 入門」
from __future__ import absolute_import, division, print_function, unicode_literals
import tensorflow as tf
from tensorflow.keras.layers import Dense, Flatten, Conv2D
from tensorflow.keras import Model
## UnknownError: Failed to get convolution algorithm. This is probably because cuDNN failed to initialize への対策
# gpu_devices = tf.config.experimental.list_physical_devices('GPU')
# for device in gpu_devices: tf.config.experimental.set_memory_growth(device, True)
#MNISTデータセットをロードして準備します。
mnist = tf.keras.datasets.mnist
#ダウンロード終了後からの実行時間計測のために追加します。
import time
start_time = time.time()
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
# Add a channels dimension
x_train = x_train[..., tf.newaxis]
x_test = x_test[..., tf.newaxis]
#データセットをシャッフルし、バッチ化するためにtf.dataを使います。
train_ds = tf.data.Dataset.from_tensor_slices(
(x_train, y_train)).shuffle(10000).batch(32)
test_ds = tf.data.Dataset.from_tensor_slices((x_test, y_test)).batch(32)
#Kerasのmodel subclassing APIを使ってモデルを作りtf.kerasます。
class MyModel(Model):
def __init__(self):
super(MyModel, self).__init__()
self.conv1 = Conv2D(32, 3, activation='relu')
self.flatten = Flatten()
self.d1 = Dense(128, activation='relu')
self.d2 = Dense(10, activation='softmax')
def call(self, x):
x = self.conv1(x)
x = self.flatten(x)
x = self.d1(x)
return self.d2(x)
# モデルのインスタンスを作成
model = MyModel()
#訓練のためにオプティマイザと損失関数を選びます。
loss_object = tf.keras.losses.SparseCategoricalCrossentropy()
optimizer = tf.keras.optimizers.Adam()
#モデルの損失と正解率を計測するためのメトリクスを選択します。これらのメトリクスはエポックごとに値を集計し、最終結果を出力します。
train_loss = tf.keras.metrics.Mean(name='train_loss')
train_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(name='train_accuracy')
test_loss = tf.keras.metrics.Mean(name='test_loss')
test_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(name='test_accuracy')
# tf.GradientTapeを使ってモデルを訓練する関数を定義します。
@tf.function
def train_step(images, labels):
with tf.GradientTape() as tape:
predictions = model(images)
loss = loss_object(labels, predictions)
gradients = tape.gradient(loss, model.trainable_variables)
optimizer.apply_gradients(zip(gradients, model.trainable_variables))
train_loss(loss)
train_accuracy(labels, predictions)
# モデルをテストする関数を定義します。
@tf.function
def test_step(images, labels):
predictions = model(images)
t_loss = loss_object(labels, predictions)
test_loss(t_loss)
test_accuracy(labels, predictions)
EPOCHS = 5
for epoch in range(EPOCHS):
for images, labels in train_ds:
train_step(images, labels)
for test_images, test_labels in test_ds:
test_step(test_images, test_labels)
template = 'Epoch {}, Loss: {}, Accuracy: {}, Test Loss: {}, Test Accuracy: {}'
print (template.format(epoch+1,
train_loss.result(),
train_accuracy.result()*100,
test_loss.result(),
test_accuracy.result()*100))
# 次のエポック用にメトリクスをリセット
train_loss.reset_states()
train_accuracy.reset_states()
test_loss.reset_states()
test_accuracy.reset_states()
# 計測した結果を出力
tat_time = time.time() - start_time
print ("実行時間:{0}".format(tat_time) + "[秒]")
Tensorflowのインストール(GPU版)
インストールするライブラリ名に「-gpu」を付ける以外は、
全てCPU版と同様の手順である。
conda create -n gpuenv python=3.7
conda activate gpuenv
pip install tensorflow-gpu==2.0.0
しかし、この状態のままで先述のコードを実行すると、
例えば以下のようなエラーがでる。
W tensorflow/stream_executor/platform/default/dso_loader.cc:55] Could not load dynamic library 'cudart64_100.dll'; dlerror: cudart64_100.dll not found
~~~中略~~~
tensorflow.python.framework.errors_impl.InternalError: cudaGetDevice() failed. Status: cudaGetErrorString symbol not found.
このようなdllが見つからない系のエラーが出る場合は、
以下のように、Anaconda Prompt からコマンドで、dllが存在するか、また、
そのpathが通っているかを確認することができる。
今回はまだ何も入れていないので、まずはCUDAやcuDNNをインストールする。
where cudart64_100.dll
# > 情報: 与えられたパターンのファイルが見つかりませんでした。
引き続き、CUDA, cuDNN, Nvidia Driver を
インストールしてからまたコード実行に戻ってこよう。
新旧混在/玉石混合のインストール手順情報が多いなかで、
最も参考になるサイトは下記のサイト。
https://www.kkaneko.jp/tools/win/tensorflow2.html
環境構築系でエラーが生じた場合は、一度確認すると良い。
CUDAのダウンロードとインストール
CUDAはNVIDIAが開発している、
GPUによる並列計算処理のための開発環境。
最新版はえてしてバージョンがあっていないので、
以下のアーカイブサイトから
自身のバージョンに合ったものを探す(今回は10.0)
https://developer.nvidia.com/cuda-toolkit-archive
自分のマシンのGPUの型番に応じたファイルであるため、
あらかじめGPUのデバイス名を確認しておこう。
今回の構築で使ったのは以下のファイル。
cuda_10.0.130_411.31_win10.exe
インストール時には、そのインストールオプションで、
「高速(推奨)」ではなく、「カスタム(詳細)」を選び、
「ドライバーコンポーネントの選択」から、
CUDA - Visual Studio Integration
のチェックを外しておくと少し幸せ。
(関連するVisualStudioが無いよ、みたいな
警告を受けなくて済む)
VisualStudioが必要だというインストール手順も多いが、
重くてインストールが手間になるので、
モジュールのリコンパイルをしない場合は、
VisualStudio関連は必須ではないハズ。
最悪でもbuildtoolだけインストールすればいい。
cuDNNのダウンロードとインストール
cuDNN はCUDA Deep Neural Network library の略。
ニューラルネットワーク計算を高速に行うためのライブラリー。
https://developer.nvidia.com/cudnn
ダウンロードのためには無料で簡単なユーザ登録が必要。
ユーザ登録後、再度上記のページを開き、
cuDNN Download に進む。
今回の環境で使ったのは下記のファイル
cudnn-10.0-windows10-x64-v7.6.5.32.zip
【重要】CUDAのバージョン(10.0)と、cudnnのバージョン(7.6)の
掛け算のパターンでファイルが違うため、良く確認すること。
Tensorflowのバージョンごとに、稼働確認がとれている組み合わせが違うため、
使用するTensorflowのバージョン(2.0.0)に対応したものを選ぶ必要がある。
https://www.tensorflow.org/install/source_windows
上記公式サイトで確認出来るハズだが、
今回は7.4⇒7.6に変更する必要があった模様。
ダウンロードしたファイルを解凍すると、
cudaフォルダの下に、以下が格納されている。
bin/cudnn64_7.dll
include/cudnn.h
lib/x64/cudnn.lib
NVIDIA_SLA_cuDNN_Support.txt
そのままのファイル構成のまま、以下のフォルダにコピーする。
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.0
なお、後でどのバージョンを使っているのか分からなくなった場合は、
include/cudnn.h をテキストエディタで開いて57行目あたりに書いてある。
インストール終了後、一度Anaconda Prompotを再起動し、
下記のコマンドを実行し、cudaのバージョンを再確認する。
(gpuenv) C:\Users\[ユーザ名]>nvcc -V
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2018 NVIDIA Corporation
Built on Sat_Aug_25_21:08:04_Central_Daylight_Time_2018
Cuda compilation tools, release 10.0, V10.0.130
先ほどは取得できなかったdllも認識されているハズ。
(gpuenv) C:\Users\[ユーザ名]>where cudart64_100.dll
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.0\bin\cudart64_100.dll
もし、認識されていない場合、
システム環境変数の「path」を参照し、
下記のパスが設定されているかどうかを確認しよう。
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.0\bin
Nvidia Driver のアップデート(必要に応じて)
Nvidia Driverは、原則新しいバージョンが入っていれば問題ない。
CUDAに対応して、どのバージョンのドライバが必要かは、
下記の公式ページに一覧表がある。
https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html
大体は、PC購入時点の最新版のドライバが入っていると思うので、
ここは省略しても良い可能性が高いと思われる。
バージョンの確認方法は、
WindowsアプリケーションのNVIDIAコントロールパネルを開き、
ヘルプ⇒システム情報⇒コンポーネント
⇒NVCUDA.DLLを確認する。
製品名:NVIDIA CUDA 10.0.132 driver
ファイルのバージョン:25.21.14.1971
この右側の、41971の部分がDriverのバージョン。
または、nvidia-smiコマンドでも同様に確認できる。
(gpuenv) C:\Users\[ユーザ名]>nvidia-smi
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 419.71 Driver Version: 419.71 CUDA Version: 10.0 |
|-------------------------------+----------------------+----------------------+
| GPU Name TCC/WDDM | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
| 0 GeForce GTX 1650 WDDM | 00000000:01:00.0 Off | N/A |
| N/A 41C P8 1W / N/A | 134MiB / 4096MiB | 0% Default |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: GPU Memory |
| GPU PID Type Process name Usage |
|=============================================================================|
| No running processes found |
+-----------------------------------------------------------------------------+
GPUを使用中に上記のnvidia-smiコマンドをたたくことで、
その実行中プロセスやメモリ利用量等を確認できるため、
以降の手順中でも適宜たたいてみるのがオススメ。
GPU版Tensorflowの疎通確認
Anaconda Prompt にて、GPU版仮想環境をactivateして、
以下のように順番にコマンドを実行する。
conda activate gpuenv
python -c "import tensorflow as tf; print(tf.__version__)"
python -c "from tensorflow.python.client import device_lib; print(device_lib.list_local_devices())"
結果、tensorflowのバージョン2.0.0と、
以下のようなGPUデバイスの表示が出れば成功。
CPU版では、device_type: "CPU" のところまでしか出ない。
GPUが認識されていれば、その型番が表示されるハズ。
~途中省略~
Created TensorFlow device (/device:GPU:0 with 2913 MB memory) -> physical GPU (device: 0, name: GeForce GTX 1650, pci bus id: 0000:01:00.0, compute capability: 7.5)
[name: "/device:CPU:0"
device_type: "CPU"
memory_limit: 268435456
locality {
}
incarnation: 4688799603900704883
, name: "/device:GPU:0"
device_type: "GPU"
memory_limit: 3055235892
locality {
bus_id: 1
links {
}
}
incarnation: 15201502304566343823
physical_device_desc: "device: 0, name: GeForce GTX 1650, pci bus id: 0000:01:00.0, compute capability: 7.5"
]
また、もし失敗している場合でも、上記の実行ログ中で、
どのdllの呼び出しに失敗しているのか確認出来るハズ。
ここまでで、環境構築できたよお疲れ様、
と言っている手順情報が多々見受けられるのは、
良くない風潮だと思う。
下記のUnknownErroの件や、性能比較しないと
本当にGPUが適用されているか分かりにくいから。
あと、順調に環境構築進める手順だけでなく、
発生したエラーと解決方法や確認方法も書いて欲しい。
チュートリアルコードの実行(GPU版)(※UnknownError対応)
早速、この環境でさきほどのCPU版の疎通用コードを実行する。
python tensorflow-tutorial-ex.py
GPU版の疎通が実施できていても、以下のようなエラーになる。
~~途中省略~~
W tensorflow/core/common_runtime/base_collective_executor.cc:216] BaseCollectiveExecutor::StartAbort Unknown: Failed to get convolution algorithm. This is probably because cuDNN failed to initialize, so try looking to see if a warning log message was printed above.
[[{{node my_model/conv2d/Conv2D}}]]
Traceback (most recent call last):
File "tensorflow-tutorial-ex.py", line 85, in <module>
train_step(images, labels)
~~途中省略~~
line 67, in quick_execute
six.raise_from(core._status_to_exception(e.code, message), None)
File "<string>", line 3, in raise_from
tensorflow.python.framework.errors_impl.UnknownError: Failed to get convolution algorithm. This is probably because cuDNN failed to initialize, so try looking to see if a warning log message was printed above.
~~途中省略~~
Function call stack:
train_step
この、UnknownError がめちゃくちゃ厄介で、
複数の要因で似たエラーが発生しうる。
詳細は以下参照:
https://github.com/tensorflow/tensorflow/issues/24496
ざっくり言うと、以下のようなパターンがある模様。
- Tensofrow,CUDA,cuDNNのバージョン不整合
- インストール手順不正、DLL不足など
- 別スレッドでGPU使用プロセスが残っていた場合など、
2回目の実行などでGPUメモリ不足(一回目は成功する) - GPUメモリの割り当て方の指定方法の問題(※コード修正のみで対応可能)
余談:
このエラー修正が最も時間がかかった。
インストール手順も確認して何度か修正してやり直したが、
結果的にはバージョン不整合&コードの問題の二重トラブル。
どちらもTensorflowの公式サイトからの情報をもとに
実施した部分であったため、判明が遅れてしまった。
Windows版の情報はあまりアテにしてはいけない。
さらに、修正後もJupyterから実行すると再発しやすい。
「別スレッドでGPU使用プロセスが残っていた場合」が該当。
単純なRunning⇒shutdownのプロセスキルだけでは
何かが残っているのか、最悪PC再起動しないといけない。
このこともあり、疎通完了まではJupyter以外で実施がオススメ。
コード修正のみで対応するためには、
import文の下に、以下のようなコードを追加する。
(tensorflow2系の場合。1系の場合は参照先URLをご確認)
※前出のコードには既にコメントアウト状態で貼ってあるので、
コメントアウトを解除すればOK
# UnknownError: Failed to get convolution algorithm. This is probably because cuDNN failed to initialize への対策
gpu_devices = tf.config.experimental.list_physical_devices('GPU')
for device in gpu_devices: tf.config.experimental.set_memory_growth(device, True)
Keras関連のサンプルコードを実行する場合も、
バックエンドでTensorflowを使用するため、
最初のほうで同様のコードを実行しておくと、
UnknownErrorが防止できるハズ。
UnknownError対策用のコードは、keras利用の場合は、
以下のようなコードになるかもしれない(未確認)
# Allowing GPU memory growth
#config = tf.ConfigProto() #V1のコード
config = tf.compat.v1.ConfigProto()
config.gpu_options.allow_growth = True
#tf.keras.backend.set_session(tf.Session(config=config)) #V1のコード
tf.compat.v1.keras.backend.set_session(tf.compat.v1.Session(config=config));
実施した結果、今回は下記の時間で終了した。
実行時間:29.763328075408936[秒]
CPU版が、約143秒に対して、
GTX1650でのGPU版が、約30秒なので、
かなり早くなったように思える。
ただし、単純にこの割合で早くなるのではなく、
実行するコードの内容にもかなり依存する点は注意。
例えば、公式サイトの初心者向けクイックスタートのコードを使うと、
https://www.tensorflow.org/tutorials/quickstart/beginner
CPU版:約14秒
GPU版:約18秒
と逆転してしまう。(初期化等の時間を雑に扱っているせいもある)
実際に実行したコードは下記の通り。
#https://www.tensorflow.org/tutorials/quickstart/beginner
from __future__ import absolute_import, division, print_function, unicode_literals
import tensorflow as tf
mnist = tf.keras.datasets.mnist
#ダウンロード終了後からの実行時間計測のために追加します。
import time
start_time = time.time()
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(x_train, y_train, epochs=5)
model.evaluate(x_test, y_test, verbose=2)
# 計測した結果を出力
tat_time = time.time() - start_time
print ("実行時間:{0}".format(tat_time) + "[秒]")
こちらのコードでは、GPU版もCPU版と
全く同じコードで動作するので簡単な疎通にもオススメ。
ついでにもう一つ、比較用/疎通用に使えるコードを乗せておく。
fashion_mnistの分類問題の短めのコード。
これまでのサンプルと同様に、JupyterやColabのセルにコピペや、
.pyファイルにしてそのまま実行が可能で使いやすいと思う。
#参考:https://github.com/tensorflow/tensorflow/issues/34888
import tensorflow as tf
#UnknownError回避用
gpu_devices = tf.config.experimental.list_physical_devices('GPU')
for device in gpu_devices: tf.config.experimental.set_memory_growth(device, True)
import numpy as np
print("Num GPUs Available: ", len(tf.config.experimental.list_physical_devices('GPU')))
from tensorflow import keras
fashion_mnist = keras.datasets.fashion_mnist
#ダウンロード終了後からの実行時間計測のために追加します。
import time
start_time = time.time()
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
train_images = train_images / 255.0
test_images = test_images / 255.0
train_images = np.expand_dims(train_images, axis=3)
test_images = np.expand_dims(test_images, axis=3)
model = tf.keras.Sequential()
model.add(tf.keras.layers.Conv2D(filters=64, kernel_size=2, padding='same', activation='relu', input_shape=(28,28,1)))
model.add(tf.keras.layers.MaxPooling2D(pool_size=2))
model.add(tf.keras.layers.Dropout(0.3))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(256, activation='relu'))
model.add(tf.keras.layers.Dropout(0.5))
model.add(tf.keras.layers.Dense(10, activation='softmax'))
model.summary()
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(train_images, train_labels, batch_size=64, epochs=10, validation_data=(test_images, test_labels))
# 計測した結果を出力
tat_time = time.time() - start_time
print ("実行時間:{0}".format(tat_time) + "[秒]")
Colaboratoryで実行した場合との比較結果
さてこのように、WindowsでGPUを使おうとすると
かなり面倒&ハマりやすい手順が必要になってしまう。
ubuntuならばNVIDIA Dockerが最短として、
残念ながらWindowsのWSL1,2では
本記事執筆時点ではまだGPUイメージは使えないと聞くため、
「一般的なパッケージング済みのゲーミングPC(Windows)」
をGPU有り機械学習にも使おうとすると、
まだこの手順はしばらく現役だと思われる。
※WSLでDocker利用可能 ≠ NVIDIA Docker利用可能、
は大きな誤算であった。
ColaboratoryにはこのGPU設定済み環境が、
無料で使える状態で用意してある。
改めてColaboratoryの偉大さを感じる。
ついでに、あくまで参考まで、
簡単な実行時間の比較計測を行ってみた。
性能比較結果一覧表
環境 - CPU/GPU情報 | 初心者Tutorial | 上級者Tutorial | fashion_mnist |
---|---|---|---|
CPU(Local) i7-9750H 2.60GHz | 約14秒 | 約143秒 | 約289秒 |
GPU(Local) GTX1650 | 約19秒 | 約 29秒 | 約 77秒 |
CPU(Colab) Xeon(R) 2.20GHz | 約23秒 | 約291秒 | 約760秒 |
GPU(Colab) Tesla P100 | 約24秒 | 約 18秒 | 約 46秒 |
評価に使ったどのコードも本稿に乗せており、
データセットのダウンロードも付いているので、
既に環境をお持ちの方は、お手元でも走らせてみると
さらに楽しめるかもしれない。
なお、Colaboratoryではtensorflowのバージョンは、
デフォルトでは「1.15.0」であり、
最初に下記の専用コマンドで「2.1.0」に
変更してから実行している。
ローカル側と多少ずれるが同じ2系だしそのまま動いた。
ただし、2020年3月27日~、デフォルトが2系になるとのことなので、
以降はこのコマンドは不要。(※逆に1系にしたい場合に使うことになる)
%tensorflow_version 2.x
import tensorflow as tf
print(tf.__version__)
Colaboratoryでは、ランタイムに接続するたびに、
どのスペックのマシンが当たるかはムラがあるため、
今回引けたマシンの情報を書いておく。
CPU(Colab) ⇒ Intel(R) Xeon(R) CPU @ 2.20GHz ×2
GPU(Colab) ⇒ Tesla P100-PCIE-16GB (最も良いヤツ?)
よって、実行時間の秒数は、あくまで参考値である。
詳細なマシンスペック情報は、以下のコマンドで確認が可能。
!cat /proc/cpuinfo
!cat /proc/driver/nvidia/gpus/0000:00:04.0/information
!nvidia-smi
なお、私のゲーミングノートPCの情報は下記の通り。
CPU = Intel(R)Core(TM)i7-9750H CPU 2.60GHz
GPU = GeForce GTX 1650
ゲーミングノートPCとして、2020年時点で最安値エントリークラス。
10万円ほどで購入。GTX1050やMX250よりは良いので最低性能ではない。
余談:
最近では、特にゲーム用の虹色に光るようなヤツでなくても、
MX250などの小さなGPUを積んでいたり、GPU搭載でありながら、
かなりの薄型、普通のノートPCのようなビジネスも可のモデルが
増えてきており、今後普通のノートPCにおいても、
ちょっとGPU積んでます、みたいなモデルが増えてくるかもしれない。
それにしても、ちょっと前までは考えられないくらい、
ゲーミングノートPCも安く&薄くなったような気がする。
性能比較結果としてはやはり、(12時間/90分の問題を考慮しなければ)
Colaboratory(GPU)の利便性&性能が際立っていた。
また、長時間利用したい場合でも、近い将来、
有償版の Colab Pro が日本でも使えるようになればさらに便利になりそう。
余談:
Colab Pro は$9.99/月ほど払うと、
より速いGPU/より長期間の使用/より多くのメモリ、で使えるらしい。
2020年3月時点では、アメリカ在住者向けにしか解放しておらず、
日本のクレジットカードでは登録出来ない模様。
感想/結論
ColaboratoryのGPUは良いものを使っている、
というのがどの程度のものなのか、
また、CPUとGPUでの実行時間の違いがどう出るのか、
実体験として理解することが出来た。
やっぱりColaboratoryがGPU利用としては最強感。
Windows環境(ゲーミングノートPC)でもGPUを使う方法と、
そのトラブルシュートをまとめることが出来た。
Anacondaの仮想環境の切り替え方法や、
Tensorflow2.0の一発時間計測実行コードも役立つかもしれない。
Macユーザも七色に光る怪しいマシンを買ってみてはいかがか?
機械学習のためにゲーミングノートPCを買って、
お勉強したあとはいっぱいゲームをしよう!!
以上。