pycudaで構築したdot productコードとscikit-cudaに実装されているモジュールで2つのアレイのdot product(ドット積)をテストしてみる。
スポンサーリンク
dot productテスト(skcuda編)¶
>>> import pycuda.autoinit
>>> import pycuda.gpuarray as gpuarray
>>> import numpy as np
>>> import skcuda.linalg as linalg
>>> import skcuda.misc as misc
>>> linalg.init()
>>> a = np.asarray(np.random.rand(4, 2), np.float32)
>>> b = np.asarray(np.random.rand(2, 2), np.float32)
>>> a_gpu = gpuarray.to_gpu(a)
>>> b_gpu = gpuarray.to_gpu(b)
>>> c_gpu = linalg.dot(a_gpu, b_gpu)
>>> np.allclose(np.dot(a, b), c_gpu.get())
>>> d = np.asarray(np.random.rand(5), np.float32)
>>> e = np.asarray(np.random.rand(5), np.float32)
>>> d_gpu = gpuarray.to_gpu(d)
>>> e_gpu = gpuarray.to_gpu(e)
>>> f = linalg.dot(d_gpu, e_gpu)
>>> np.allclose(np.dot(d, e), f)
skcuda.linalg.dotとnumpy.dotの速度を比較する。
%timeit -n10000 -r10 linalg.dot(a_gpu, b_gpu)
%timeit -n10000 -r10 np.dot(a, b)
from time import time
st = time()
linalg.dot(a_gpu, b_gpu)
gpu_time = (time() - st)
print ("GPU: ", gpu_time)
st = time()
np.dot(a, b)
cpu_time = (time() - st)
print ("CPU: ", cpu_time)
print ("speedup: ", gpu_time/cpu_time)
スポンサーリンク
dot productテスト(PyCUDA編)¶
import pycuda.driver as cuda
import pycuda.autoinit
from pycuda.compiler import SourceModule
import numpy
MATRIX_SIZE = 10
a = numpy.random.randint(2, size=(MATRIX_SIZE, MATRIX_SIZE)).astype(np.float32)
b = numpy.random.randint(2, size=(MATRIX_SIZE, MATRIX_SIZE)).astype(np.float32)
a_gpu = gpuarray.to_gpu(a)
b_gpu = gpuarray.to_gpu(b)
c_gpu = gpuarray.empty((MATRIX_SIZE, MATRIX_SIZE), numpy.float32)
mod = SourceModule("""
__global__ void dot(float *a, float *b, float *c)
{
// 2D Thread ID (assuming that only *one* block will be executed)
int tx = threadIdx.x;
int ty = threadIdx.y;
// Pvalue is used to store the element of the matrix
// that is computed by the thread
float Pvalue = 0;
// Each thread loads one row of M and one column of N,
// to produce one element of P.
for (int k = 0; k < %(MATRIX_SIZE)s; ++k) {
float Aelement = a[ty * %(MATRIX_SIZE)s + k];
float Belement = b[k * %(MATRIX_SIZE)s + tx];
Pvalue += Aelement * Belement;
}
// Write the matrix to device memory;
// each thread writes one element
c[ty * %(MATRIX_SIZE)s + tx] = Pvalue;
}
""" % {
'MATRIX_SIZE': MATRIX_SIZE
})
func = mod.get_function("dot")
func(a_gpu, b_gpu, c_gpu, \
block=(MATRIX_SIZE, MATRIX_SIZE, 1))
print(a)
print(b)
print(c_gpu.get())
numpy.dotとの整合性を確認する。
np.dot(a, b)
%timeit func(a_gpu, b_gpu, c_gpu, block=(MATRIX_SIZE, MATRIX_SIZE, 1))
%timeit np.dot(a, b)
array sizeが小さいとCPUの方が実行速度が速い。
参考サイトhttps://wiki.tiker.net/
スポンサーリンク
スポンサーリンク