在 numba.jit 装饰器中使用并行选项会使函数给出错误的结果

2024-05-02

给定一个矩形的两个对角(x1, y1) and (x2, y2)和两个半径r1 and r2,找到位于由半径定义的圆之间的点的比率r1 and r2到矩形中的点数。

简单的 NumPy 方法:

def func_1(x1,y1,x2,y2,r1,r2,n):
     x11,y11 = np.meshgrid(np.linspace(x1,x2,n),np.linspace(y1,y2,n))
     z1 = np.sqrt(x11**2+y11**2)
     a = np.where((z1>(r1)) & (z1<(r2)))
     fill_factor = len(a[0])/(n*n)
     return fill_factor

接下来我尝试用以下方法优化这个函数jit来自 numba 的装饰器。当我使用时:

nopython = True

该函数速度更快并给出正确的输出。但是当我还添加:

parallel = True

该函数速度更快,但给出了错误的结果。 我知道这与我的z矩阵,因为它没有被正确更新。

@jit(nopython=True,parallel=True)
def func_2(x1,y1,x2,y2,r1,r2,n):
    x_ = np.linspace(x1,x2,n)
    y_ = np.linspace(y1,y2,n)
    z1 = np.zeros((n,n))
    for i in range(n):
        for j in range(n):
            z1[i][j] = np.sqrt((x_[i]*x_[i]+y_[j]*y_[j]))
    a = np.where((z1>(r1)) & (z1<(r2)))
    fill_factor = len(a[0])/(n*n)
    return fill_factor

测试值:

x1 = 1.0
x2 = -1.0
y1 = 1.0
y2 = -1.0
r1 = 0.5
r2 = 0.75
n = 25000

附加信息:Python版本:3.6.1,Numba版本:0.34.0+5.g1762237,NumPy版本:1.13.1


问题在于parallel=True是它是一个黑匣子。 Numba 甚至不保证它实际上会并行化任何东西。它使用启发式方法来确定它是否可并行以及什么could并行进行。这些可能会失败,在您的示例中它们确实会失败,就像我的实验parallel和努巴 https://stackoverflow.com/q/35459065/5393381。这使得parallel不值得信任,我会建议against使用它!

在较新的版本中 (0.34)prange已添加,您可能会更幸运。它不能应用于这种情况,因为prange作品就像range这不同于np.linspace...

请注意:您可以避免构建z并做np.where完全在你的函数中,你可以明确地进行检查:

import numpy as np
import numba as nb

@nb.njit   # equivalent to "jit(nopython=True)".
def func_2(x1,y1,x2,y2,r1,r2,n):
    x_ = np.linspace(x1,x2,n)
    y_ = np.linspace(y1,y2,n)
    cnts = 0
    for i in range(n):
        for j in range(n):
            z = np.sqrt(x_[i] * x_[i] + y_[j] * y_[j])
            if r1 < z < r2:
                cnts += 1
    fill_factor = cnts/(n*n)
    return fill_factor

与您的函数相比,这还应该提供一些加速,甚至可能比使用parallel=True(如果它能正常工作)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 numba.jit 装饰器中使用并行选项会使函数给出错误的结果 的相关文章

随机推荐