TensorFlow 2.0 Alpha : ガイド : GPU を使用する (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 03/22/2019
* 本ページは、TensorFlow の本家サイトの TF 2.0 Alpha の以下のページを翻訳した上で適宜、補足説明したものです:
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
ガイド : GPU を使用する
サポートされるデバイス
TensorFlow は CPU と GPU を含む、様々なタイプのデバイス上で計算を実行することをサポートします。それらは文字列で表わされます、例えば :
- “/cpu:0”: 貴方のマシンの CPU。
- “/device:GPU:0”: TensorFlow に見える、貴方のマシンの最初の GPU
- “/device:GPU:1”: TensorFlow に見える、貴方のマシンの 2 番目の GPU, etc.
TensorFlow 演算が CPU と GPU 実装の両者を持つ場合、演算がデバイスに割り当てられるときデフォルトでは GPU デバイスに優先権が与えられるでしょう。例えば、matmul は CPU と GPU カーネルの両者を持ちます。デバイス cpu:0 と gpu:0 を持つシステム上では、貴方がそれを他のデバイス上で実行することを明示的に要請しない限りは matmul を実行するために gpu:0 が選択されます。
デバイス配置をログ記録する
貴方の演算と tensor がどのデバイスに割り当てられたかを見い出すためには、tf.debugging.set_log_device_placement(True) を貴方のプログラムの最初のステートメントとして置きます。
tf.debugging.set_log_device_placement(True) # Creates some tensors a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3], name='a') b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[3, 2], name='b') c = tf.matmul(a, b) print(c)
次の出力を見るはずです :
Executing op MatMul in device /job:localhost/replica:0/task:0/device:CPU:0 tf.Tensor( [[22. 28.] [49. 64.]], shape=(2, 2), dtype=float32)
手動デバイス配置
貴方のために自動的に選択されたものの代わりに特定の演算に貴方が選択したデバイス上で実行して欲しい場合、デバイスコンテキストを作成するために with tf.device を使用できてそしてそのコンテキスト内の総ての演算は指定された同じデバイス上で実行されます。
tf.debugging.set_log_device_placement(True) # Place tensors on the CPU with tf.device('/cpu:0'): a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3], name='a') b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[3, 2], name='b') c = tf.matmul(a, b) print(c)
今では a と b は cpu:0 に割り当てられたことを見るでしょう。MatMul 演算のためにはデバイスは明示的に指定されていませんので、TensorFlow ランタイムは演算と利用可能なデバイス (この例では cpu:0) に基づいて一つを選択して必要であればデバイス間で tensor を自動的にコピーします。
Executing op MatMul in device /job:localhost/replica:0/task:0/device:CPU:0 tf.Tensor( [[22. 28.] [49. 64.]], shape=(2, 2), dtype=float32)
GPU メモリ増加を可能にする
デフォルトでは、TensorFlow は (CUDA_VISIBLE_DEVICES に従って) 可視の総ての GPU の GPU メモリの殆ど総てをプロセスにマップします。これはメモリ断片化を減らしてデバイス上の比較的貴重な GPU メモリリソースをより効率的に使用するために成されます。
ある場合にはプロセスに対して利用可能なメモリの一部だけを割り当てたり、プロセスにより必要とされるメモリ使用量を増やすだけが望ましいです。TensorFlow はこれを制御するために 2 つのメソッドを提供します。
最初のオプションは tf.config.gpu.set_per_process_memory_growth() メソッドを呼ぶことによりメモリ増大を有効にします、これはランタイム割り当てのために必要な GPU メモリだけを割り当てることを試みます : それは非常に小さいメモリを割り当てることから始めて、そしてプログラムが実行されてより多くの GPU メモリが必要になるにつれて、TensorFlow プロセスに割り当てられる GPU メモリ領域を拡張します。メモリを解放しないことに注意してください、何故ならばそれはより悪いメモリ断片化に繋がる可能性さえあるからです。プロセスメモリ増加を有効にするためには、貴方のプログラムの最初のステートメントにこれを置きます :
tf.config.gpu.set_per_process_memory_growth()
2 番目のメソッドは tf.gpu.set_per_process_memory_fraction() です、これは各可視な GPU が割り当てられるべきメモリの全体的な総量の割合を決定します。例えば、次により TensorFlow に各 GPU の総メモリの 40% だけを割り当てることを知らせることができます :
tf.config.gpu.set_per_process_memory_fraction(0.4)
これは TensorFlow プロセスに利用可能な GPU メモリの総量を正確に抑制したい場合に有用です。
マルチ GPU システム上で単一 GPU を使用する
貴方のシステムに一つの GPU 以上を持つ場合、デフォルトでは最少の ID を持つ GPU が選択されます。異なる GPU 上で実行したい場合には、その選択を明示的に指定する必要があります :
tf.debugging.set_log_device_placement(True) # Specify a device with tf.device('/device:GPU:2'): a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3], name='a') b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[3, 2], name='b') c = tf.matmul(a, b) print(c)
貴方が指定したデバイスが存在しない場合には、RuntimeError を得るでしょう :
RuntimeError: Error copying tensor to device: /job:localhost/replica:0/task:0/device:GPU:2. /job:localhost/replica:0/task:0/device:GPU:2 unknown device.
指定されたものが存在しない場合に TensorFlow に演算を実行するための存在しているサポートされるデバイスを自動的に選択させたいのであれば、tf.config.set_soft_device_placement(True) を呼び出すことができます。
tf.config.set_soft_device_placement(True) tf.debugging.set_log_device_placement(True) # Creates some tensors with tf.device('/device:GPU:2'): a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3], name='a') b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[3, 2], name='b') c = tf.matmul(a, b) print(c)
マルチ GPU を使用する
With tf.distribute.Strategy
マルチ GPU を使用するためのベストプラクティスは tf.distribute.Strategy を使用することです。ここに単純なサンプルがあります :
strategy = tf.distribute.MirroredStrategy() with strategy.scope(): inputs = tf.keras.layers.Input(shape=(1,)) predictions = tf.keras.layers.Dense(1)(inputs) model = tf.keras.models.Model(inputs=inputs, outputs=predictions) model.compile(loss='mse', optimizer=tf.train.GradientDescentOptimizer(learning_rate=0.2))
このプログラムは各 GPU 上で貴方のモデルのコピーを実行します、それらの間で入力データを分割します、「データ並列」としても知られています。
分散ストラテジーについてのより多くの情報については、ここで ガイド を調べてください。
Without tf.distribute.Strategy
tf.distribute.Strategy は内部的にはデバイスに渡り計算を複製することにより動作しています。各 GPU 上で貴方のモデルを構築することにより複製を手動で実装することができます。例えば :
tf.debugging.set_log_device_placement(True) # Replicate your computation on multiple GPUs c = [] for d in ['/device:GPU:2', '/device:GPU:3']: with tf.device(d): a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3]) b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[3, 2]) c.append(tf.matmul(a, b)) with tf.device('/cpu:0'): sum = tf.add_n(c) print(sum)
次の出力を見るでしょう :
Executing op MatMul in device /job:localhost/replica:0/task:0/device:GPU:0 Executing op MatMul in device /job:localhost/replica:0/task:0/device:GPU:1 Executing op AddN in device /job:localhost/replica:0/task:0/device:CPU:0 tf.Tensor( [[ 44. 56.] [ 98. 128.]], shape=(2, 2), dtype=float32)
以上