Quantcast
Channel: youwhtの記事 - Qiita
Viewing all articles
Browse latest Browse all 29

ゲーミングPCで機械学習をして、CPU/GPUの性能の違いをColaboとも比較してみた話【Windowsの機械学習環境構築手順決定版。TF2.0対応】

$
0
0

ひとことで言うと

格安ゲーミング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デバイスに対応していない
そのため、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

参考: 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:Failedtogetconvolutionalgorithm.ThisisprobablybecausecuDNNfailedtoinitialize,sotrylookingtoseeifawarninglogmessagewasprintedabove.

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版のインストール

https://www.anaconda.com/distribution/#download-section

基本的にはデフォルト設定のままでインストールを進める。

CondaのPython仮想環境の使い方

CPU版/GPU版を気軽に使い分けたい、
別バージョンを試したい、などの用途だけでなく、
環境構築時のリトライのしやすさなども含めて、
Pythonの仮想環境を用いて構築を進めると良い。

Anaconda Comand Prompt 上で下記のように操作する。

AnacondaComandPromptでの操作
# 以下のコマンドで仮想環境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側から仮想環境が見えるようにしよう。

AnacondaComandPromptでの操作
# 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で下記のように実行する。

AnacondaComandPromptでの操作
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や
ライブラリなどのパスを確認すると良いだろう。

パス確認用のPythonスクリプト
importsysprint(sys.prefix)print(sys.path)

また、Jupyterではブラウザを閉じただけでは
裏でプロセスはまだ残っているため、
「running」のタブから実行中プロセスを確認し、
一度全てをShutdownし、
Jupyter自身も終了させてから再起動すると、
きちんと設定が反映され、正しい動作となる場合も多い。

普段においても、GPUは「占有型」でデバイスを使うようなので、
他のGPU実行プロセスを残さないように、
適宜Shutdownしておいた方が良いだろう。

Tensorflowのインストール(CPU版)

まずは、CPUのみを利用した
Tensorflow実行用仮想環境を構築し、疎通をとろう。

AnacondaComandPromptでの操作
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

AnacondaComandPromptでの操作
python tensorflow-tutorial-ex.py
# > ~~途中結果省略~~# > 今回のCPU版での実行時間は下記の通り。# > 実行時間:143.45523118972778[秒]
tensorflow-tutorial-ex.py
#https://www.tensorflow.org/tutorials/quickstart/advanced
#Tensofrflow公式「エキスパートのための TensorFlow 2.0 入門」
from__future__importabsolute_import,division,print_function,unicode_literalsimporttensorflowastffromtensorflow.keras.layersimportDense,Flatten,Conv2Dfromtensorflow.kerasimportModel## 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#ダウンロード終了後からの実行時間計測のために追加します。
importtimestart_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ます。
classMyModel(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')defcall(self,x):x=self.conv1(x)x=self.flatten(x)x=self.d1(x)returnself.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.functiondeftrain_step(images,labels):withtf.GradientTape()astape: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.functiondeftest_step(images,labels):predictions=model(images)t_loss=loss_object(labels,predictions)test_loss(t_loss)test_accuracy(labels,predictions)EPOCHS=5forepochinrange(EPOCHS):forimages,labelsintrain_ds:train_step(images,labels)fortest_images,test_labelsintest_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_timeprint("実行時間:{0}".format(tat_time)+"[秒]")

Tensorflowのインストール(GPU版)

インストールするライブラリ名に「-gpu」を付ける以外は、
全てCPU版と同様の手順である。

AnacondaComandPromptでの操作
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をインストールする。

AnacondaComandPromptでの操作
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のバージョンを再確認する。

AnacondaComandPromptでの操作
(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も認識されているハズ。

AnacondaComandPromptでの操作
(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コマンドでも同様に確認できる。

AnacondaComandPromptでの操作
(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して、
以下のように順番にコマンドを実行する。

AnacondaComandPromptでの操作
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

import文の下に追加するコード
# UnknownError:  Failed to get convolution algorithm. This is probably because cuDNN failed to initialize への対策
gpu_devices=tf.config.experimental.list_physical_devices('GPU')fordeviceingpu_devices:tf.config.experimental.set_memory_growth(device,True)

Keras関連のサンプルコードを実行する場合も、
バックエンドでTensorflowを使用するため、
最初のほうで同様のコードを実行しておくと、
UnknownErrorが防止できるハズ。

UnknownError対策用のコードは、keras利用の場合は、
以下のようなコードになるかもしれない(未確認)

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__importabsolute_import,division,print_function,unicode_literalsimporttensorflowastfmnist=tf.keras.datasets.mnist#ダウンロード終了後からの実行時間計測のために追加します。
importtimestart_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.0model=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_timeprint("実行時間:{0}".format(tat_time)+"[秒]")

こちらのコードでは、GPU版もCPU版と
全く同じコードで動作するので簡単な疎通にもオススメ。

ついでにもう一つ、比較用/疎通用に使えるコードを乗せておく。
fashion_mnistの分類問題の短めのコード。
これまでのサンプルと同様に、JupyterやColabのセルにコピペや、
.pyファイルにしてそのまま実行が可能で使いやすいと思う。

fashion_mnist
#参考:https://github.com/tensorflow/tensorflow/issues/34888
importtensorflowastf#UnknownError回避用
gpu_devices=tf.config.experimental.list_physical_devices('GPU')fordeviceingpu_devices:tf.config.experimental.set_memory_growth(device,True)importnumpyasnpprint("Num GPUs Available: ",len(tf.config.experimental.list_physical_devices('GPU')))fromtensorflowimportkerasfashion_mnist=keras.datasets.fashion_mnist#ダウンロード終了後からの実行時間計測のために追加します。
importtimestart_time=time.time()(train_images,train_labels),(test_images,test_labels)=fashion_mnist.load_data()train_images=train_images/255.0test_images=test_images/255.0train_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_timeprint("実行時間:{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上級者Tutorialfashion_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系にしたい場合に使うことになる)

Colaboratoryでのtensorflowバージョン変更用
%tensorflow_version2.ximporttensorflowastfprint(tf.__version__)

Colaboratoryでは、ランタイムに接続するたびに、
どのスペックのマシンが当たるかはムラがあるため、
今回引けたマシンの情報を書いておく。
CPU(Colab) ⇒ Intel(R) Xeon(R) CPU @ 2.20GHz ×2
GPU(Colab) ⇒ Tesla P100-PCIE-16GB (最も良いヤツ?)
よって、実行時間の秒数は、あくまで参考値である。

詳細なマシンスペック情報は、以下のコマンドで確認が可能。

Colaboratoryのスペック確認(下二つはGPU用)
!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を買って、
お勉強したあとはいっぱいゲームをしよう!!

以上。


Viewing all articles
Browse latest Browse all 29

Trending Articles