You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何启用Numba parallel=True后,可并行循环反而变慢?

Numba并行化后代码运行变慢的原因分析

你遇到的问题是启用Numba并行化后,代码执行时间反而显著增加,结合你的代码和测试场景,原因主要有以下几点:

  • 单线程版本已被Numba极致优化
    你的基础代码逻辑非常简单,仅对每个i执行少量算术运算和内存写入。Numba的njit模式会自动完成循环展开、寄存器分配、SIMD指令生成等深度优化,单线程就能把CPU的计算资源利用到接近极限,并行化很难再提升计算效率。

  • 并行化的额外开销远大于收益
    使用prange开启并行时,需要完成线程创建、任务拆分与调度、线程同步等操作,这些都有固定的额外开销。而你的每个循环迭代计算量极小,这点开销完全抵消甚至超过了并行带来的计算收益,最终导致整体运行时间增加。

  • 内存访问模式的缓存效率下降
    单线程版本中,代码按顺序访问数组元素,CPU缓存的命中率极高。并行化后,多个线程同时访问不同的内存区域,可能引发缓存竞争,或破坏原有的连续访问模式,导致缓存命中率降低,进一步拖慢运行速度。

  • 测试的数据集规模过小
    你测试的n范围是2^0到2^14(即1到16384),这个量级下,并行化的固定开销占总运行时间的比例极高。只有当n达到百万级以上的大规模时,并行化的计算收益才可能超过开销,体现出优势。


基础单线程代码

@njit('f8[:,::1](f8[:,::1], f8[:,::1], f8[:,::1])', fastmath=True)
def fun(A, B, C):

    n = A.shape[1]

    b00 = B[0,0]
    b02 = B[0,2]

    out = np.empty((n, 12))

    for i in range(n):

        ui = A[0,i]

        c1 = C[0,i]
        c2 = C[1,i]
        c3 = C[2,i]
        c4 = C[3,i]

        out[i, 0] = c1 * b00
        out[i, 1] = 0.
        out[i, 2] = c1 * (b02-ui)
        out[i, 3] = c2 * b00
        out[i, 4] = 0.
        out[i, 5] = c2 * (b02-ui)
        out[i, 6] = c3 * b00
        out[i, 7] = 0.
        out[i, 8] = c3 * (b02-ui)
        out[i, 9] = c4 * b00
        out[i, 10] = 0.
        out[i, 11] = c4 * (b02-ui)

    return out

并行化版本代码

@njit('f8[:,::1](f8[:,::1], f8[:,::1], f8[:,::1])', fastmath=True, parallel=True)
def fun_parallel(A, B, C):

    n = A.shape[1]

    b00 = B[0,0]
    b02 = B[0,2]

    out = np.empty((n, 12))

    for i in prange(n):

        ui = A[0,i]

        c1 = C[0,i]
        c2 = C[1,i]
        c3 = C[2,i]
        c4 = C[3,i]

        out[i, 0] = c1 * b00
        out[i, 1] = 0.
        out[i, 2] = c1 * (b02-ui)
        out[i, 3] = c2 * b00
        out[i, 4] = 0.
        out[i, 5] = c2 * (b02-ui)
        out[i, 6] = c3 * b00
        out[i, 7] = 0.
        out[i, 8] = c3 * (b02-ui)
        out[i, 9] = c4 * b00
        out[i, 10] = 0.
        out[i, 11] = c4 * (b02-ui)

    return out

测试代码

B = np.random.rand(3,3)

perfplot.show(
    setup=lambda n: (np.random.rand(2, n), np.random.rand(4, n)),
    kernels=[
        lambda A, C: fun(A, B, C),
        lambda A, C: fun_parallel(A, B, C),
    ],
    labels=["fun", "fun_parallel"],
    n_range=[2**k for k in range(15)],
    xlabel="n",
    show_progress=False,
)

内容的提问来源于stack exchange,提问作者abc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 05:18:33