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秒。但是afaik
parallel=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