Python numba没有';t并行化范围
我的代码中有我想要并行化的循环Python numba没有';t并行化范围,python,jit,numba,Python,Jit,Numba,我的代码中有我想要并行化的循环 from numba import njit, prange from time import time @njit def f1(n): s = 0 for i in range(n): for j in range(n): for k in range(n): s += (i * k < j * j) - (i * k > j * j) return
from numba import njit, prange
from time import time
@njit
def f1(n):
s = 0
for i in range(n):
for j in range(n):
for k in range(n):
s += (i * k < j * j) - (i * k > j * j)
return s
@njit
def f2(n):
s = 0
for i in prange(n):
for j in prange(n):
for k in prange(n):
s += (i * k < j * j) - (i * k > j * j)
return s
@njit(parallel=True)
def f3(n):
s = 0
for i in range(n):
for j in range(n):
for k in range(n):
s += (i * k < j * j) - (i * k > j * j)
return s
@njit(parallel=True)
def f4(n):
s = 0
for i in prange(n):
for j in prange(n):
for k in prange(n):
s += (i * k < j * j) - (i * k > j * j)
return s
for f in [f1, f2, f3, f4]:
d = time()
f(2500)
print('%.02f' % (time() - d))
我检查了我的处理器的活动,前三个函数是100%,第四个是300%
我不明白为什么指定parallel没有改变任何事情,需要使用prange。在中,有一个例子是Numba文档中的range.: @jit的experimental parallel=True选项将尝试优化阵列操作并并行运行它们。它还添加了对prange()的支持,以显式地并行化循环 现在,由于在函数中不做任何数组操作,所以如果不显式地用prange标记循环,Numba就无法并行化 所以,只是为了确保没有混淆。 当您在装饰中设置parallel=True时,Numba只会将您的循环拆分为线程,并通过更改来明确标记循环;范围->胡说八道 在您的f4()中,您已经将prange放在了所有for循环上,我建议只将prange放在最外层的循环上,因为您不想冒险从线程中派生线程。 即:
@njit(parallel=True)
def f5(n):
s=0
对于prange中的i(n):
对于范围(n)内的j:
对于范围(n)内的k:
s+=(i*kj*j)
返回s
我在Github上创建了一个问题,一个贡献者的回答非常准确()
如果他想在这里转载他的答案,我会接受的。很有趣。这对我来说似乎是一个错误。我尝试了所有的
jit
和njit
组合,有和没有nogil
,我总是在f1
到f3
上获得11秒,在f4
上获得2.5秒。但是afaikparallel=True
仍然是一个实验性的特性。也许你应该在numba
github上提交一份bug报告。@Scotty1-谢谢你的帮助,我会等一天再报告。nogil通常会影响性能吗?根据我的经验,它不会影响性能,但我没有使用任何并发线程。我只是想让它能够检查它是否可以并行运行而不发生任何冲突。不要在所有循环上使用prange(OpenMP也不会这样做)。通常,SIMD的目标是将内部循环矢量化,并在外部循环上并行化,以获得最佳性能。fastmath关键字也与此类型的操作相关。这将提供更多代数上正确的优化,这可能会对数值预测产生影响(使用部分和求和)不被视为0维数组吗?如果我将它初始化为numpy ndarray,它会改变吗?你确定是嵌套式的胡闹吗?我认为它的工作原理与OMP不同(例如)。你是说进程而不是线程?
27.44
27.34
26.83
13.05
@njit(parallel=True)
def f5(n):
s = 0
for i in prange(n):
for j in range(n):
for k in range(n):
s += (i * k < j * j) - (i * k > j * j)
return s