我想使用Numba 的guvectorize
方法在我的 CUDA 卡上运行代码。我首先定义了一个CPU方法
from numba import guvectorize
import numpy as np
@guvectorize(['float32[:,:], float32[:,:]',
'float64[:,:], float64[:,:]'],
'(n,m)->(n,m)', nopython=True, target='cpu')
def update_a_cpu(A, Anew):
n, m = A.shape
for j in range(1, n-1):
for i in range(1, m-1):
Anew[j, i] = 0.25 * (A[j, i+1] + A[j, i-1] + A[j-1, i] + A[j+1, i])
它给出了测试矩阵的预期输出
>>> A = np.arange(16, dtype=np.float32).reshape(4,4) # single precision for GTX card
>>> Anew = np.zeros((4,4), dtype=np.float32)
>>> res_cpu = update_a_cpu(A, Anew)
>>> print(res_cpu)
[[ 0. 0. 0. 0.]
[ 0. 5. 6. 0.]
[ 0. 9. 10. 0.]
[ 0. 0. 0. 0.]]
实际上,当以 CPU 为目标时,Anew
它已就地突变,因此无需将输出分配给res_cpu
>>> res_cpu is Anew
True
将目标更改为以未针对 Generalized CUDA ufuncs'cuda'
记录的方式彻底改变guvectorize
行为。这是修改后的 ufunc 定义
@guvectorize(['float32[:,:], float32[:,:]',
'float64[:,:], float64[:,:]'],
'(n,m)->(n,m)', nopython=True, target='cuda')
def update_a_cuda(A, Anew):
n, m = A.shape
for j in range(1, n-1):
for i in range(1, m-1):
Anew[j, i] = 0.25 * (A[j, i+1] + A[j, i-1] + A[j-1, i] + A[j+1, i])
现在该函数不接受第二个输入矩阵
>>> res_cuda = update_a_cuda(A, Anew)
...
TypeError: invalid number of input argument
而是创建一个空矩阵将值放入
>>> res_cuda = update_a_cuda(A)
>>> print(res_cuda)
array([[ 1.55011636e-41, 1.55011636e-41, 1.55011636e-41, 1.55011636e-41],
[ 1.55011636e-41, 5.00000000e+00, 6.00000000e+00, 1.55011636e-41],
[ 1.55011636e-41, 9.00000000e+00, 1.00000000e+01, 1.55011636e-41],
[ 1.55011636e-41, 1.55011636e-41, 1.55011636e-41, 1.55011636e-41]], dtype=float32)
我希望通用 ufunc 更新输入矩阵的适当值,而不是填充空矩阵。以 CUDA 设备为目标时,有没有办法将变量指定为输入和输出?