SSDとは何なのか?ここで言うところのSSDはSolid State Drive(ソリッドステートドライブ)のことではないのであしからず。ここで言うSSDとはSum of Squared Differences(ssd)のことで、 SSD between 2 Numpy arraysと言えば、2つのナンピー(ナンパイが正解だが日本人ならナンピーだろ)配列間の差分二乗和を意味する。今回はこのSSDのnumpyでの表記法とパイキューダ(pycudaはパイクーダと言うらしいが日本人なら当然パイキューダだろ)との速度比較をやる。
スポンサーリンク
SSD Numpyバージョン¶
import numpy as np
a = np.random.randn(5)
b = np.random.randn(5)
print(a)
print(b)
np.sum((a-b)**2)
np.sum((b-a)**2)
a = np.asarray([[1,2,4],
[3,1,2]])
b = np.asarray([[2,1,1],
[3,2,3],
[4,1,2],
[2,2,1],])
np.sum((b-a)**2)
a = np.asarray([[1,2,4],
[3,1,2]])
b = np.asarray([[2,1,1],
[3,2,3],
[4,1,2],
[2,2,1],])
np.sum((b[:,None] - a)**2)
a = np.asarray([[1,2,4],
[3,1,2]])
b = np.asarray([[2,1,1],
[3,2,3],
[4,1,2],
[2,2,1],])
np.square(b[:,None] - a).sum(axis=2).T
np.square(b[:,None] - a).sum(axis=1).T
np.square(b[:,None] - a).sum(axis=0).T
c = np.square(b[:,None] - a).sum(axis=0).T
np.sum(c)
スポンサーリンク
PyCUDA vs. Numpy¶
このサイトからコードを拝借して速度比較をする。
import pycuda.gpuarray as gpuarray
import pycuda.reduction as reduction
import pycuda.driver as cuda
import pycuda.autoinit
from pycuda.compiler import SourceModule
import numpy
import time
krnl = reduction.ReductionKernel(numpy.float32, neutral="0",
reduce_expr="a+b", map_expr="x[i]*y[i]",
arguments="float *x, float *y")
ssd = reduction.ReductionKernel(numpy.float32, neutral="0",
reduce_expr="a+b", map_expr="(x[i] - y[i])*(x[i] - y[i])",
arguments="float *x, float *y")
for i in range(5):
a = numpy.random.randn(140**i)
b = numpy.random.randn(140**i)
a_gpu = gpuarray.to_gpu(a.astype(numpy.float32))
b_gpu = gpuarray.to_gpu(b.astype(numpy.float32))
start = time.time()
numpy_dot = numpy.dot(a,b)
numpy_ssd = numpy.sum((a - b) ** 2)
end = time.time()
dt = end - start
print ("CPU time", dt)
print ("numpy_dot", numpy_dot)
print ("numpy_euclid", numpy_ssd)
start = time.time()
my_dot_prod = krnl(a_gpu, b_gpu).get()
my_euclid = ssd(a_gpu, b_gpu).get()
end = time.time()
dt1 = end - start
print (("GPU time", dt1))
print (("my dot product", my_dot_prod))
print (("my euclid", my_euclid))
print('Speed difference: {:0.1f}x'.format(dt / dt1))
print (("\n"))
配列が小さいとCPUが圧倒的に速いが、配列がでかくなるに従ってGPUの独壇場になる。しかし、巨大なアレイになると途端にメモリ不足を起こすので、やはりメインメモリは64G、GPUメモリは16Gは欲しいところだ。
スポンサーリンク
スポンサーリンク