我正在尝试将以下操作与cupy并行化: 我有一个数组。对于该数组的每一列,我正在生成 2 个随机向量。我采用该数组列,添加一个向量,减去另一个向量,然后将该新向量作为数组的下一列。我继续,直到我完成阵列。
我已经问了以下问题 - 在遍历数组时,Cupy 比 numpy 慢。但这是不同的,因为我相信我遵循了并行化操作的建议,并有一个"for 循环"而不是两个,并且只遍历数组列而不是行和列。
import cupy as cp
import time
#import numpy as cp
def row_size(array):
return(array.shape[1])
def number_of_rows(array):
return(array.shape[0])
x = (cp.zeros((200,200), 'f'))
#x = cp.zeros((200,200))
x[:,1] = 500000
vector_one = x * 0
vector_two = x * 0
start = time.time()
for i in range(number_of_rows(x) - 1):
if sum(x[ :, i])!=0:
vector_one[ :, i + 1], vector_two[ :, i+ 1] = cp.random.poisson(.01*x[:,i],len(x[:,i])), cp.random.poisson(.01 * x[:,i],len(x[:,i]))
x[ :, i+ 1] = x[ :, i] + vector_one[ :, i+ 1] - vector_two[ :, i+ 1]
time = time.time() - start
print(x)
print(time)
当我在cupy中运行它时,时间约为0.62秒。
当我切换到 numpy 时,所以我 1( 取消注释 #import numpy 作为 cp 和 #x = cp.zeros((200,200(( 和 2( 改为将导入 cupy 注释为 cp 和 x = (cp.zeros((200,200(, 'f'((:
时间大约是0.11秒。
我想也许如果我增加数组大小,例如从 (200,200( 到 (2000,2000(,那么我会看到 cupy 更快,但它仍然更慢。
从某种意义上说,我知道这是正常工作的,因为如果我将 cp.random.poisson 中的系数从 .01 更改为 .5,我只能在 cupy 中这样做,因为 lambda 对于 numpy 来说太大了。
但是,我如何用cupy让它变得更快?
通常,在主机 (CPU( 上循环并迭代处理小型设备 (GPU( 数组并不理想,因为与面向列的方法相比,您必须启动更多数量的独立内核。但是,有时面向列的方法并不可行。
你可以通过使用CuPy的sum
来加速你的CuPy代码,而不是使用Python的内置sum
操作,后者在每次调用设备时都会强制设备托管传输。话虽如此,您还可以通过切换到 NumPy 的总和来加速您的 NumPy 代码。
import cupy as cp
import time
#import numpy as cp
def row_size(array):
return(array.shape[1])
def number_of_rows(array):
return(array.shape[0])
x = (cp.zeros((200,200), 'f'))
#x = cp.zeros((200,200))
x[:,1] = 500000
vector_one = x * 0
vector_two = x * 0
start = time.time()
for i in range(number_of_rows(x) - 1):
# if sum(x[ :, i]) !=0:
if x[ :, i].sum() !=0: # or you could do: if x[ :, i].sum().get() !=0:
vector_one[ :, i + 1], vector_two[ :, i+ 1] = cp.random.poisson(.01*x[:,i],len(x[:,i])), cp.random.poisson(.01 * x[:,i],len(x[:,i]))
x[ :, i+ 1] = x[ :, i] + vector_one[ :, i+ 1] - vector_two[ :, i+ 1]
cp.cuda.Device().synchronize() # CuPy is asynchronous, but this doesn't really affect the timing here.
t = time.time() - start
print(x)
print(t)
[[ 0. 500000. 500101. ... 498121. 497922. 497740.]
[ 0. 500000. 499894. ... 502050. 502174. 502112.]
[ 0. 500000. 499989. ... 501703. 501836. 502081.]
...
[ 0. 500000. 499804. ... 499600. 499526. 499371.]
[ 0. 500000. 499923. ... 500371. 500184. 500247.]
[ 0. 500000. 500007. ... 501172. 501113. 501254.]]
0.06389498710632324
这个小变化应该会让你的工作流程更快(0.06 与最初在我的 T4 GPU 上为 0.6 秒(。请注意,注释中的.get()
方法用于在不相等比较之前将sum
操作的结果从 GPU 显式传输到 CPU。这不是必需的,因为 CuPy 知道如何处理逻辑操作,但会给你一个非常小的额外加速。