LoginSignup
96
109

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-03-28

ひとことで言うと

格安ゲーミング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 上で下記のように操作する。

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スクリプト
import sys
print(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__ 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版と同様の手順である。

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')
for device in gpu_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__ 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ファイルにしてそのまま実行が可能で使いやすいと思う。

fashion_mnist
#参考: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系にしたい場合に使うことになる)

Colaboratoryでのtensorflowバージョン変更用
%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 (最も良いヤツ?)
よって、実行時間の秒数は、あくまで参考値である。

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

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を買って、
お勉強したあとはいっぱいゲームをしよう!!

以上。

96
109
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
96
109