Python 在numba.jit decorior中使用parallel选项会使函数给出错误的结果

Python 在numba.jit decorior中使用parallel选项会使函数给出错误的结果,python,python-3.x,numpy,jit,numba,Python,Python 3.x,Numpy,Jit,Numba,给定矩形(x1,y1)和(x2,y2)的两个相对角以及两个半径r1和r2,求出半径r1和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)) & (

给定矩形
(x1,y1)
(x2,y2)
的两个相对角以及两个半径
r1
r2
,求出半径
r1
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
该函数速度更快,输出正确。但当我补充说:

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

附加信息:Python版本:3.6.1,Nuba版本:0.34.0+5.g1762237,NumPy版本:1.13.1。Numba甚至不能保证它将实际并行任何东西。它使用启发式来确定它是否可并行化,以及可以并行完成什么。这些可能会失败,在您的示例中,它们确实会失败,就像在中一样。这使得
并行
不可信,我建议不要使用它

在较新的版本(0.34)中,添加了
prange
,您可能会更幸运。它不能应用于这种情况,因为
prange
的工作方式类似于
range
,这与
np.linspace
不同

请注意:您可以避免构建
z
和执行
np。如果函数中的
是完整的,您可以直接执行检查:

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
将numpy导入为np
进口麻木为nb
@注意:njit相当于“jit(nopython=True)”。
def func_2(x1、y1、x2、y2、r1、r2、n):
x_uux=np.linspace(x1,x2,n)
y=np.linspace(y1,y2,n)
碳纳米管=0
对于范围(n)中的i:
对于范围(n)内的j:
z=np.sqrt(x_[i]*x_[i]+y_[j]*y_j])
如果r1

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

谢谢!我想补充的另一件事是,不必求z的平方根,可以直接比较平方(正如我的导师所指出的)。除此之外,我试图看看代码可能出了什么问题,我认为可能是开发了一个竞态条件,人们不应该像你之前指出的那样盲目地使用并行选项。是的,我也认为这是某种竞态条件,但我检查了生成的LLVM代码,我不知道怎么做。竞态条件需要发生在
np.where
(因为在
z
中没有后续写入到相同的数组位置),但这可能会导致竞态条件,这有点不祥。但我对平方根很好奇:计算平方根是否比计算两次乘法和一次加法更快?
x1 = 1.0
x2 = -1.0
y1 = 1.0
y2 = -1.0
r1 = 0.5
r2 = 0.75
n = 25000
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