GPU もrPython を使ってやってみる

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