【问题标题】:TypingError: Failed in nopython mode pipeline (step: nopython frontend) Unknown attribute 'shape' of type float32TypingError:在 nopython 模式管道中失败(步骤:nopython 前端) float32 类型的未知属性“形状”
【发布时间】: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:行
  1. 使用参数:'(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:行
  1. 使用参数:'(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 &gt; 200).sum() - (B &gt; 200).sum() 解决的问题来解决这个问题。该表达式已被矢量化。如果您希望依赖 CUDA,您可能希望使用 Numba 来装饰该表达式或探索 CuPy

标签: python cuda jit numba


【解决方案1】:

不使用 CUDA,但这可能会给你一些想法:

Pure Numpy(已经矢量化):

A = np.random.rand(480, 640).astype(np.float32) * 255
B = np.random.rand(480, 640).astype(np.float32) * 255

%timeit (A > 200).sum() - (B > 200).sum()
478 µs ± 4.06 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

只需将 numpy 操作包装在 JITted 函数中:

@nb.njit
def pixel_count_jit(img):
    return (img > 200).sum()

%timeit pixel_count_jit(A) - pixel_count_jit(B)
165 µs ± 13.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

使用 Numba 按行并行化:

@nb.njit(parallel=True)
def pixel_count_parallel(img):
    counts = np.empty(img.shape[1], dtype=nb.uint32)
    for i in nb.prange(img.shape[0]):
        counts[i] = (img[i] > 200).sum()
    return counts.sum()

%timeit pixel_count_parallel(A) - pixel_count_parallel(B)
28.5 µs ± 571 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

【讨论】:

    猜你喜欢
    • 2019-07-30
    • 2020-07-15
    • 2023-02-01
    • 2020-07-21
    • 2020-08-08
    • 2021-06-15
    • 2021-11-08
    • 2017-05-24
    • 2019-08-21
    相关资源
    最近更新 更多