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
所以我有一个看起来完全可以接受的并行循环。但是当我将它传递给 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