GPUを使ってみようと思うのだが、メモリがうんたらかんたら言われて、巨大なデータを入力すると動かないので、Python でやったら実はいい感じに動くのではないかと思ってやってみる。
Python ならpycuda, gnumpy があるようだが、gnumpy のほうがnumpy ベースでやれるからgnumpy を使ってみる。
GPU は入ってるけど、いざやってみると
gnumpy: failed to import cudamat. Using npmat instead. No GPU will be used.
と言われるので、cudamatを入れて再チャレンジする。
40倍くらい早くなるが、こちらも巨大なデータを入れるとメモリうんたらかんたらで死ぬ。
# Pythonで import time import gnumpy as g import numpy as np i, j = 2000, 2000 x = g.randn(i, j) g.dot(x, x) start = time.time() print "GPU: Matrix product, total sum is %f, computed in %f secs" %\ (g.sum(g.dot(x , x)), time.time()-start) x0 = x.asarray() start = time.time() print "CPU: Matrix product, total sum is %f, computed in %f secs" %\ (np.sum(np.dot(x0 , x0)), time.time()-start)
前にRでやったときはたかだか5倍くらいしか速くならなかったので、rPythonを使ってPython に仕事を投げて、結果だけもってくる。
これも巨大なデータを入れるとメモリうんたらかんたらで死ぬし、gnumpy のgarray 形式だとRでデータを持てないからリスト構造にする必要がある。しかし、リスト構造に変換していたらそれのほうが時間かかるし、結局R内で愚直に計算する方がよさそう。
library(rPython) i <- 1000 j <- 1000 x <- matrix(runif(i*3), nc=3) y <- matrix(runif(j*3), nr=3) python.exec(" import time\ import gnumpy as g\ import numpy as np") python.exec(" def gpu_py(x, y):\ z = g.dot(x, y)\ return [[zzz for zzz in zz] for zz in z]") z <- python.call("gpu_py", x, y)
pycuda を使いたかったら、パスを通さないといけないみたいで、インストールしたCUDA のバージョンをいじって
CUDA_ROOT=/usr/local/cuda-7.5 PATH=$PATH:/usr/local/cuda-7.5/bin LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda-7.5/lib64:/usr/local/cuda-7.5/lib CPATH=$CPATH:/usr/local/cuda-7.5/include CUDA_INC_DIR=/usr/local/cuda-7.5/bin:$CUDA_INC_DIR
pip するよりかはソースからインストールするとよさそう。
git clone --recursive http://git.tiker.net/trees/pycuda.git cd pycuda python configure.py sudo python setup.py install sudo make install
本当は行列演算がしたいのに、pycuda のdot 関数がなぜか行列積じゃないっぽいのでやめた。
import pycuda.gpuarray import pycuda.driver as cuda import pycuda.autoinit import numpy j = 2 a = pycuda.gpuarray.to_gpu(numpy.random.randn(j, j).astype(numpy.float32)) b = pycuda.gpuarray.to_gpu(numpy.random.randn(j, j).astype(numpy.float32)) print a w = pycuda.gpuarray.dot(a, a) w.get