Google Colabでpython2 ~ GPUの利用
前回ブラウザ上で実行できるPython環境として、Google Colaboratory (Colab)を紹介した。メリットの1つとしてGPUが使用できることを取り上げたが、今回はGoole Colab上でのGPUの使用方法と効果について紹介する。
1. ColabノートブックでのGPU設定
基本的にはGoogle Colabのトップページの下のアクセラレターの使用:TensorFlow と GPUのページ(英語)に従って、注釈を入れる形で使用方法やGPUの効果を確認するサンプルコードについて紹介する。
まず最初にノートブックのメニューバー上の"編集"から"ノートブックの設定"をクリックすると、以下のアクセラレータを選択するポップアップがあらわれるのでGPUを選択して保存する。
これでノートブック上でGPUが使用できる状態になる。GPUの設定ができているかどうかはtf.test.gpu_device_name()
でGPU名を取得する以下のコードで確認することができる。
import tensorflow as tf device_name = tf.test.gpu_device_name() if device_name != '/device:GPU:0': raise SystemError('GPU device not found') print('Found GPU at: {}'.format(device_name))
正しく設定できていれば
Found GPU at: /device:GPU:0
となる。
2. GPU効果計測のためのサンプルコード
以上でGPUで処理することができるが、効果の確認として以下の処理でCPUとGPUの演算時間を比較する。
def cpu(): with tf.device('/cpu:0'): random_image_cpu = tf.random.normal((100, 100, 100, 3)) net_cpu = tf.keras.layers.Conv2D(32, 7)(random_image_cpu) return tf.math.reduce_sum(net_cpu) def gpu(): with tf.device('/device:GPU:0'): random_image_gpu = tf.random.normal((100, 100, 100, 3)) net_gpu = tf.keras.layers.Conv2D(32, 7)(random_image_gpu) return tf.math.reduce_sum(net_gpu)
cpu()
はcpuでの処理を実行する関数、gpu()
はGPUでの処理を実行する関数を定義している。
with tf.device()
とすることで処理するデバイスを指定する。(詳しくはtf.device | TensorFlow Core v2.7.0)
次にtf.random.normal((100, 100, 100, 3))
では指定したshape(上記は(100,100,100,3))の形式で正規分布乱数を出力する。例えばshapeに(2,2,2,3)を指定すると以下のように出力される。
import tensorflow as tf tf.random.normal((2, 2, 2, 3))
実行結果は以下の通り。
<tf.Tensor: shape=(2, 2, 2, 3), dtype=float32, numpy= array([[[[ 0.24025539, 1.32085 , -1.6566725 ], [-1.3553022 , -1.4656491 , 0.06768529]], [[-0.6647642 , 0.9501496 , 0.13946538], [-0.9395935 , 0.08838586, 0.7459039 ]]], [[[-0.17912869, 0.6915636 , -0.13298476], [-0.19780236, -0.8404351 , 0.15334088]], [[-0.13912152, 2.172381 , 0.5304954 ], [ 0.5558663 , -0.4010124 , 1.9473423 ]]]], dtype=float32)>
なお他にも細かく指定できるので、詳細は公式リファレンスtf.random.normal | TensorFlow Core v2.7.0を参照。
random_cpu_imageの意味としては100x100,RGB(3)のイメージ(画像化すると砂嵐ノイズ)100セットということになる。
次にtf.keras.layers.Conv2D(32, 7)(random_image_cpu)
は画像認識でお馴染みのコンボリューション処理を行う。
最後に配列(テンソル)の各要素の総和をとるtf.math.reduce_sum(net_gpu)
を関数としての返り値とする。
tf.math.reduce_sum()
の実行例のコードは以下のようになる。
import numpy as np arr = np.array([[0, 1, 2], [3, 4, 5]]) tf.math.reduce_sum(arr)
実行すると各要素の総和が返ってくるがオブジェクト形式(下`numpy=15'が総和)になる。数値だけ取り出す場合はtf.math.reduce_sum(arr).numpy()とする。
<tf.Tensor: shape=(), dtype=int64, numpy=15>
以上cpu()
およびgpu()
の処理をまとめると、CPUまたはGPUを選択し、100x100,RGB(3)のイメージ(画像化すると砂嵐ノイズ)100セット生成し、
生成したイメージをコンボリューションした後、配列要素の総和を返す。
Tensorflowの初期化処理をあらかじめ実行しておくことで、関数内の処理時間のみを評価できるようにするため、それぞれの関数cpu()
およびgpu()
を一度実行する。
cpu() gpu()
正しく実行されれば以下のような出力になる。
<tf.Tensor: shape=(), dtype=float32, numpy=1180.4795>
3. CPUとGPU処理時間の比較
定義した関数cpu()
とgpu()
の処理時間を比較する。この例ではtimeit
を使用してそれぞれの処理時間を評価している。
timeit --- 小さなコード断片の実行時間計測 — Python 3.10.0b2 ドキュメント
以下のコードは関数cpu()
およびgpu()
を10回実行したときに要した時間を表示とCPUに対してGPUが何倍速いかを表示する。
import timeit print('Time (s) to convolve 32x7x7x3 filter over random 100x100x100x3 images ' '(batch x height x width x channel). Sum of ten runs.') print('CPU (s):') cpu_time = timeit.timeit('cpu()', number=10, setup="from __main__ import cpu") print(cpu_time) print('GPU (s):') gpu_time = timeit.timeit('gpu()', number=10, setup="from __main__ import gpu") print(gpu_time) print('GPU speedup over CPU: {}x'.format(int(cpu_time/gpu_time)))
実行結果は以下のようになり、GPUの方がCPUよりも18倍速いという結果になった。
Time (s) to convolve 32x7x7x3 filter over random 100x100x100x3 images (batch x height x width x channel). Sum of ten runs. CPU (s): 3.630094464000024 GPU (s): 0.19144165500000554 GPU speedup over CPU: 18x
4. まとめ
今回はGoogle Colab上でGPUを利用するための設定と、GPUによる処理速度向上を確認するためのサンプルコード、実行例を紹介した。基本的にはノートブックの設定でアクセレレータの選択をGPUとするだけで使用可能で、自前のPCでGPUの設定をするよりかはるかに楽だということがわかると思う。