目次

5. Cupy

5.1 CuPyとは

CuPyはNumPyとSciPyで記述されたCPU用のプログラムをGPUで動かすためのツールです。
簡単な移植作業により、GPUの高い計算性能を生かして高速に計算することができます。

5.2 CuPyによるベクトル和とベクトル内積の計算

リスト5-1にCuPyを用いてベクトル和とベクトル内積を計算するプログラムを示します。
計算時間を正確に測定するためにEventクラスを使用しています。

リスト5-1 CuPyによるベクトル和のベクトル内積のソースコード (vector_cupy.py)


"""
vector_cupy.py
test program of vector operations
CuPy
"""

import numpy as np
import cupy as cp

# (vadd) add two vectors : CuPy + NumPy version
def vadd(a, b):
    return a + b

# (sdot-1) scalar product of two vectors : CuPy version
def sdot_cupy(a, b):
    return cp.dot(a, b)

# (sdot-2) scalar product of two vectors : NumPy version
def sdot_numpy(a, b):
    return np.dot(a, b)

# parameters
N = 100000000
L = 100
dtype = 'f4'   # 'f4' or 'f8'
fn = 'vadd-1'
#fn = 'sdot-1'

# timer
start = cp.cuda.Event()
end   = cp.cuda.Event()
start.record()

# setup
a = np.arange(N).astype(dtype)
b = np.arange(N).astype(dtype)
if fn.startswith('vadd'):
    c = np.zeros(N, dtype)

# copy to device
d_a = cp.array(a)
d_b = cp.array(b)
if fn.startswith('vadd'):
    d_c = cp.array(c)

# timer
end.record()
end.synchronize()
t1 = cp.cuda.get_elapsed_time(start, end)
start.record()

# calculation
for _ in range(L):
    if   fn == 'vadd-1':
        d_c = vadd(d_a, d_b)
    elif fn == 'vadd-2':
        c = vadd(a, b)
    elif fn == 'sdot-1':
        s = sdot_cupy(d_a, d_b)
    elif fn == 'sdot-2':
        s = sdot_numpy(a, b)

# timer
end.record()
end.synchronize()
t2 = cp.cuda.get_elapsed_time(start, end)

# check
if   fn == 'vadd-1':
    c = cp.asnumpy(d_c)
    r1 = np.sum(c)
    r2 = N * (N - 1)
elif fn == 'vadd-2':
    r1 = np.sum(c)
    r2 = N * (N - 1)
else:
    r1 = s
    r2 = N * (N - 1) * (2 * N - 1) / 6

# output
print('(%s) N=%d, L=%d' % (fn, N, L))
print('%.2f+%.2f[sec], %e, %e' % (t1 * 1e-3, t2 * 1e-3, r1, r2))

# free
a = None
b = None
d_a = None
d_b = None
if fn.startswith('vadd'):
    c = None
    d_c = None

CuPyのNumPyとの主な違いは以下の通りです。

5.3 CuPyの計算時間

表5-1にCuPyのベクトル和とベクトル内積の計算時間を示します。
配列の大きさ(=N)と繰り返し回数(=L)の積は一定(=1010)です。 従って全体の演算量は同じです。

表5-1 CuPyのベクトル和とベクトル内積の計算時間
No.配列の大きさN繰り返し回数Lベクトル和ベクトル内積
単精度倍精度単精度倍精度
1100,000,000100 0.49秒 1.00秒 0.65秒 1.30秒
210,000,0001,000 0.50秒 0.99秒 0.66秒 1.33秒
31,000,00010,000 0.52秒 1.03秒 0.94秒 1.44秒
4100,000100,000 2.34秒 2.49秒 9.78秒 9.90秒
510,0001,000,00028.48秒27.34秒99.60秒98.78秒

表5-1から以下のことがわかります。