【发布时间】:2018-10-19 16:12:30
【问题描述】:
我的代码中有要并行化的循环
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))
我知道时间:
27.44
27.34
26.83
13.05
我检查了处理器的活动,前三个功能处于 100%,而第四个功能大约为 300%。
我不明白为什么指定并行并没有改变任何东西并且需要使用 prange。在the doc 中有一个带范围的例子。
【问题讨论】:
-
有趣。这对我来说似乎是一个错误。我尝试了
jit和njit的所有组合,无论有没有nogil,我总是在f1到f3上得到11 秒,在f4上得到大约2.5 秒。但是 afaikparallel=True仍然是一个实验性功能。也许你应该在numbagithub 上提交错误报告。 -
@Scotty1- 感谢您的帮助,我会等一天再报告。 nogil 一般会影响性能吗?
-
根据我的经验,它没有,但我没有使用任何并发线程。我只是想让它检查它是否可以并行运行而没有任何冲突。
-
不要在所有循环上使用 prange(你也不会使用 OpenMP 这样做)。通常,目标是对内部循环进行 SIMD 向量化并在外部循环上并行化以获得最佳性能。 fastmath 关键字也与此类操作相关。这将提供更多代数正确的优化,可能会对数值精度产生影响(通过使用部分和进行求和)