ytbilly3636’s 研究備忘録

機械学習,Python,ガンダムなど

NumPyを使うと幸せになれるかも2: CuPyを使う

こんにちは.

今回の記事はシリーズ第2段です. 厳密に言えばNumPyの話ではなく, Chainerに含まれている行列演算モジュールCuPyの話です.

CuPy解説

CuPyとはNumPyの機能をCUDA上で動かせるというもの. 使い方はnumpyをcupyで置き換えれば良いとのこと. そんなに簡単に使えるのなら使わない手はないと思い, NumPyで実装したあるコードをCuPyで置き換えてみましたが……

遅い……

ということで検証してみました.

環境

項目 詳細
OS Ubuntu 14.04
CPU i5-3570
GPU GTX970

コード

numpyとcuda.cupyの速度を行列積で比較してみました. cuda.cupyは何もしないバージョンとto_gpu()をするバージョンの2つを比較しました.

# -*- coding: utf-8 -*-

import numpy as np
import chainer
import chainer.cuda.cupy as cp
import time

# MNISTを読み込み
# 784次元のベクトル
train, test = chainer.datasets.get_mnist()

s1 = time.time()
np_ar1 = np.array(train[0][0])
np_ar2 = np.array(train[1][0])
a1 = np_ar1.dot(np_ar2.T)

s2 = time.time()
cp_ar1 = cp.array(train[0][0])
cp_ar2 = cp.array(train[1][0])
a2 = cp_ar1.dot(cp_ar2.T)

s3 = time.time()
cp2_ar1 = chainer.cuda.to_gpu(cp.array(train[0][0]))
cp2_ar2 = chainer.cuda.to_gpu(cp.array(train[1][0]))
a3 = cp2_ar1.dot(cp2_ar2.T)

s4 = time.time()
print 'np:',s2-s1
print 'cp:',s3-s2
print 'cp2:',s4-s3
np: 5.57899475098e-05
cp: 0.182370185852
cp2: 0.000236988067627

やはりNumPyが一番速かったです. CuPyが負けてしまったのはGPUへのメモリ転送がネックになっているのだと思います.

あと,numpyをcupyにただ置き換えるだけではなく, to_gpu()を書いてあげたほうがいいみたいです.

ちなみに大きめの行列だとCuPyに軍配が上がります.

s1 = time.time()
a = np.ones((1000, 1000),dtype=np.float32)
a.dot(a.T)

s2 = time.time()
b = cp.ones((1000, 1000),dtype=cp.float32)
b.dot(b.T)

s3 = time.time()
c = chainer.cuda.to_gpu(cp.ones((1000, 1000),dtype=cp.float32))
c.dot(c.T)

s4 = time.time()

print 'np:',s2-s1
print 'cp:',s3-s2
print 'cp2:',s4-s3
np: 0.0469000339508
cp: 0.281046152115
cp2: 0.000430822372437

※とある事情でコードを手打ちで書いたのでミスがあるかもしれません,悪しからず.