Numba parallel 在 for 循环中导致不正确的结果,我无法查明问题所在

Numba parallel causing incorrect results in a for loop, I can't pinpoint the issue

所以我有一个看起来完全可以接受的并行循环。但是当我将它传递给 Numba parallel 时,它总是给出不正确的结果。循环中发生的所有事情是一个输入矩阵将一个元素设置为 0,发生矩阵乘法并填充一个新矩阵,然后将设置为 0 的元素设置回其原始值。看起来数组 a 在 Numba 的每次分派中都被修改了,所以我尝试将 a 复制到循环内的另一个变量,仅修改副本,但获得相同的错误结果(未显示) .这是一个最小的例子。我只是不明白问题是什么,或者如何解决它:

import numpy as np
from scipy.stats import random_correlation
import numba as nb

def myfunc(a, corr):
    b = np.zeros(a.shape[0])

    for i in range(b.shape[0]):
        temp = a[i]
        a[i] = 0
        b[i] = a@corr@a.T
        a[i] = temp

    return b

@nb.njit(parallel=True)
def numbafunc(a, corr):
    b = np.zeros(a.shape[0])

    for i in nb.prange(b.shape[0]):
        temp = a[i]
        a[i] = 0
        b[i] = a@corr@a.T
        a[i] = temp

    return b

if __name__ == '__main__':
    a = np.random.rand(10)
    corr = random_correlation.rvs(eigs=[2,2,1,1,1,1,0.5,0.5,0.5,0.5])

    b_1 = myfunc(a, corr)
    b_2 = numbafunc(a, corr)

    # check if serial and Numba results match off the same inputs
    print(np.isclose(b_1,b_2))

    # double check the original function returns the same results again..
    b_1_check = myfunc(a, corr)
    print(np.isclose(b_1, b_1_check))

Returns 所有错误值,或者至少 9/10 是错误的...任何人都可以查明代码的哪一部分对于并行化有问题吗?我觉得不错。非常感谢!

numbafunc 中存在 竞争条件 。事实上,a[i] = 0 修改数组 a 在多个线程之间共享 reading/writing a 以获得不同的 i 值。将值存储在 temp 中以便稍后恢复它只能按顺序进行,但不能并行进行,因为线程可以随时读取 a

要解决这个问题,每个线程都应该在自己的 a:

副本上操作
@nb.njit(parallel=True)
def numbafunc(a, corr):
    b = np.zeros(a.shape[0])

    for i in nb.prange(b.shape[0]):
        c = a.copy()
        c[i] = 0.0
        b[i] = c @ corr @ c.T

    return b