我尝试使用cupy而不是numpy来加快python代码的速度。这里的问题是,使用cupy,我的代码大大变慢了。也许我对这个问题有些天真。
也许任何人都可以在我的代码中找到瓶颈:
import cupy as np
import time as ti
def f(y, t):
y_ = np.zeros(2 * N_1*N_2) # n: e-6, c: e-5
for i in range(0, N_1*N_2):
y_[i] = y[i + N_1*N_2] # n: e-7, c: e-5 or e-6
for i in range(N_1*N_2):
sum = -4*y[i] # n: e-7, c: e-7 after some statements e-5
if (i + 1 in indexes) and (not (i in indi)):
sum += y[i+1] # n: e-7, c: e-7 after some statements e-5
if (i - 1) in indexes and (i % N_1 != 0):
sum += y[i-1] # n: e-7, c: e-7 after some statements e-5
if i + N_1 in indexes:
sum += y[i+N_1] # n: e-7, c: e-7 after some statements e-5
if i - N_1 in indexes:
sum += y[i-N_1] # n: e-7, c: e-7 after some statements e-5
y_[i + N_1*N_2] = sum
return y_
def k_1(y, t, h):
return np.asarray(f(y, t)) * h
def k_2(y, t, h):
return np.asarray(f(np.add(np.asarray(y) , np.multiply(1/2 , k_1(y, t, h))), t + 1/2 * h)) * h
# k_2, k_4 look just like k_2, may be with an 1/2 here or there
# some init stuff is happening here
while t < T_end:
# also some magic happening here which is just data saving
y = np.asarray(y) + 1/6*(k_1(y, t, m) + 2*k_2(y, t, m) + 2*k_3(y, t, m) + k_4(y, t, m))
t += m
编辑 我试图对我的代码进行基准测试,以下是一些结果,可以将它们视为代码中的注释。每个数字停留一行。单位是秒。 n:脾气暴躁,c:CuPy,我主要是对该顺序进行粗略估计。 我另外测试过
np.multiply # n: e-6, c: e-5
和
np.add # n: e-5 or e-6, c: 0.005 or e-5
答案 0 :(得分:0)
您的代码示例不起作用,因为您尚未在任何地方定义N_1
,N_2
,indexes
和indi
。同样,您在代码中的注释似乎也无法帮助其他人了解正在发生的事情。
您的代码可能不会从numba / cupy中受益,因为您尚未对代码中的操作进行矢量化处理。目前,列表的工作方式可能与numpy数组一样快。
如果您摆脱了for循环并进行更改
y_ = np.zeros(2 * N_1*N_2)
for i in range(0, N_1*N_2):
y_[i] = y[i + N_1*N_2]
到
n = N1*N2
y_ = np.zeros(2*n)
y_[:n] = y[n:2*n]
以此类推,您将大大加快代码的速度。
答案 1 :(得分:0)
您的代码并不慢,因为numpy慢,但是因为您调用了许多(python)函数,而在python中,调用函数(以及迭代和访问对象以及python中的所有内容)却很慢。因此cupy并不能帮助您(但可能会损害性能,因为它必须进行更多设置,例如将数据复制到gpu)。如果您可以制定算法来使用较少的python函数(在另一个答案中进行向量化),则可以极大地加快代码的速度(您可能不需要cupy)。
您还可以查看numba,它会使用llvm在本机代码中编译您的代码。如果这样做,请务必阅读一些文档并使用nopython=True
,否则,您将只用慢的numba代码切换慢的cupy代码。