【发布时间】:2021-08-21 14:45:38
【问题描述】:
我正在学习使用 numba 来加速 Python 中的代码。使用此代码:
from numba import cuda, vectorize
import numpy as np
@cuda.jit(device = True)
def pixel_count(img1,img2):
count1 = 0
count2 = 0
for i in range(img1.shape[0]):
for j in range(img1.shape[1]):
if img1[i][j] > 200:
count1 = count1 + 1
i = 0; j = 0;
for i in range(img2.shape[0]):
for j in range(img2.shape[1]):
if img2[i][j] > 200:
count2 = count2 + 1
return count1, count2
@vectorize(['float32(float32,float32)'], target = 'cuda')
def cint(img1, img2):
c1, c2 = pixel_count(img1, img2)
res = c1-c2
return res
A = np.random.rand(480, 640).astype(np.float32)*255
B = np.random.rand(480, 640).astype(np.float32)*255
res = cint(A,B)
我收到以下错误:
TypingError: 没有实现函数 函数(
) 找到签名:pixel_count (float32, float32) 有 2 个候选实现: - 其中 2 个不匹配,原因是: 函数“pixel_count”中的重载:文件:.......\OneDrive\Desktop :行 4. 带参数:'(float32,float32)': 由于实现引发了特定错误而被拒绝: TypingError:在 nopython 模式管道中失败(步骤:nopython 前端) float32 类型的未知属性“形状” File "<ipython-input-33-9169f440975d>", line 8: def pixel_count(img1,img2): <source elided> count2 = 0 for i in range(img1.shape[0]): ^ During: typing of get attribute at <ipython-input-33-9169f440975d> (8) File "<ipython-input-33-9169f440975d>", line 8: def pixel_count(img1,img2): <source elided> count2 = 0 for i in range(img1.shape[0]): ^从 C:\Users\giuli\anaconda3\envs\GPUcomp\lib\site-packages\numba\core\typeinfer.py:1071
期间:解析被调用者类型: 函数(
) 期间:在 (3)
编辑
我使用 guvectorize 更改了这样的代码:
@guvectorize(['(float32[:],float32[:], float32)'], '(), () -> ()',target = 'cuda')
def cint(img1, img2, res):
c1, c2 = pixel_count(img1, img2)
res = c1-c2
A = np.random.rand(480, 640).astype(np.float32)*255
B = np.random.rand(480, 640).astype(np.float32)*255
res = cint(A, B)
出现此错误:
TypingError: 没有实现函数 函数(
) 找到签名:pixel_count (array(float32, 1d, A), array(float32, 1d, A)) 有2个 候选实现:
- 其中 1 个不匹配的原因是:函数“pixel_count”中的重载:文件: ..........\OneDrive\Desktop
:行
- 使用参数:'(array(float32, 1d, A), array(float32, 1d, A))':由于实现引发特定错误而被拒绝: TypingError:在 nopython 模式管道中失败(步骤:nopython 前端)内部错误在
。元组索引超出范围期间:键入 静态获取项目 (9) 启用 在调试级别记录以获取详细信息。 文件“”,第 9 行:def pixel_count(img1,img2): 对于我在范围内(img1.shape[0]): 对于范围内的 j(img1.shape[1]): ^ 从 C:\Users\giuli\anaconda3\envs\GPUcomp\lib\site-packages\numba\core\typeinfer.py:1071
- 其中 1 个不匹配的原因是:函数“pixel_count”中的重载:文件: ..........\OneDrive\Desktop
:行
- 使用参数:'(array(float32, 1d, A), array(float32, 1d, A))':由于实现引发特定错误而被拒绝: TypingError:在 nopython 模式管道中失败(步骤:nopython 前端)内部错误在
。元组索引超出范围期间:键入 静态获取项目 (9) 启用 在调试级别记录以获取详细信息。 文件“”,第 9 行:def pixel_count(img1,img2): 对于我在范围内(img1.shape[0]): 对于范围内的 j(img1.shape[1]): ^ 从 C:\Users\giuli\anaconda3\envs\GPUcomp\lib\site-packages\numba\core\typeinfer.py:1071
期间:解析被调用者类型: 函数(
) 期间:在 (23)
如何使用 cuda.jit 和 vectorize/guvectorize 函数?
编辑 2
感谢大家的回复。目标是弄清楚如何使用 numba 使用 GPU 解决此任务。 CPU 中的代码可能更快,因为矩阵较小;感谢您对并行计算的提示非常有帮助。您对如何将此代码移植到 GPU 有任何其他建议吗?非常感谢。
我以这种方式修改了代码,但它总是返回值 0:
from numba import cuda, vectorize, guvectorize
import numpy as np
@cuda.jit(device = True)
def pixel_count(img1,img2):
count1 = 0
count2 = 0
for i in range(img1.shape[0]):
for j in range(img1.shape[1]):
if img1[i][j] > 200:
count1 = count1 + 1
i = 0; j = 0;
for i in range(img2.shape[0]):
for j in range(img2.shape[1]):
if img2[i][j] > 200:
count2 = count2 + 1
return count1, count2
@guvectorize(['(float32[:,:],float32[:,:], int16)'],
'(n,m), (n,m)-> ()', target = 'cuda')
def cint(img1, img2, res):
count1, count2 = pixel_count(img1, img2)
res = count1 - count2
A = np.random.rand(480, 640).astype(np.float32)*255
B = np.random.rand(480, 640).astype(np.float32)*255
res1 = cint(A, B)
【问题讨论】:
-
显然调用一个期望数组作为输入的函数不适用于向量化,因为函数在标量上工作。
-
同样,您的新版本在设备函数中有二维索引,但
guvectorize指定一维数组。在这两种情况下,如果您花时间研究错误消息,编译器就会直接告诉您问题所在 -
记住,这里没有鸭子打字。一切都必须明确输入、标注尺寸并匹配。编译器正在静态键入所有内容。
-
您是否真的想通过
(A > 200).sum() - (B > 200).sum()解决的问题来解决这个问题。该表达式已被矢量化。如果您希望依赖 CUDA,您可能希望使用 Numba 来装饰该表达式或探索 CuPy。