当对数组的列作为向量进行"for loop"时,cupy 比 numpy 慢

  • 本文关键字:loop for cupy numpy 数组 向量 cupy
  • 更新时间 :
  • 英文 :


我正在尝试将以下操作与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 知道如何处理逻辑操作,但会给你一个非常小的额外加速。

最新更新