我试图用一个简单的例子来说明为我自己和一些同事使用numba.prange的好处,但我无法获得适当的加速.我编写了一个简单的一维扩散解算器,它基本上在一个长数组上循环,组合元素i+1ii-1,并将结果写入第二个数组的元素i.这应该是一个非常完美的并行for循环用例,类似于Fortran或C中的OpenMP.

下面是我的完整示例:

import numpy as np
from numba import jit, prange

@jit(nopython=True, parallel=True)
def diffusion(Nt):
    alpha = 0.49
    x = np.linspace(0, 1, 10000000)
    # Initial condition
    C = 1/(0.25*np.sqrt(2*np.pi)) * np.exp(-0.5*((x-0.5)/0.25)**2)
    # Temporary work array
    C_ = np.zeros_like(C)
    # Loop over time (normal for-loop)
    for j in range(Nt):
        # Loop over array elements (space, parallel for-loop)
        for i in prange(1, len(C)-1):
            C_[i] = C[i] + alpha*(C[i+1] - 2*C[i] + C[i-1])
        C[:] = C_
    return C

# Run once to just-in-time compile
C = diffusion(1)

# Check timing
%timeit C = diffusion(100)

当使用parallel=False时,这大约需要2秒,使用parallel=True时大约需要1.5秒.我在一台有4个物理内核的MacBook Pro上运行,Activity Monitor报告在有无并行化的情况下CPU使用率分别为parallel=False%和700%左右.

我本以为会有更接近因子4的加速.我做错什么了吗?

推荐答案

较差的可扩展性当然来自于桌面计算机上所有内核共享的RAM饱和.事实上,与CPU(或GPU)的计算能力相比,your code is memory-bound和内存吞吐量在现代机器上相当有限.因此,在大多数台式机上,1或2个内核通常足以使RAM饱和(计算服务器上需要更多的内核).

在具有40~43 GiB/s RAM的10核Intel Xeon处理器上,并行代码需要1.32秒,顺序代码需要2.56秒.这意味着使用10核时速度仅提高2倍.也就是说,并行循环每个时间步读取一次完整的C数组,并且每个时间步读取+写入一次完整的C_数组(默认情况下,x86处理器需要读取写入的内存,因为是write allocate cache policy).C[:] = C_也有同样的功能.这意味着仅在1.32秒内并行读取/写入(2*3)*(8*10e6)*100/1024**3 = 44.7 GiB或RAM,导致33.9 GiB/s内存吞吐量达到RAM带宽的80%(非常适合此用例).

为了加快这段代码的速度,您需要从RAM中读写更少的数据,并在缓存中尽可能多地计算数据.要做的第一件事是使用double-buffering方法和两个视图,以避免非常昂贵的拷贝.另一个优化是try 同时并行执行多个时间步.从理论上讲,使用复杂的trapezoidal tiling strategy是可能的,但在实践中很难实现,尤其是在Numba中.高性能模具库应该为您做到这一点.这样的优化不应该只产生improve the sequential execution but also the scalability个并行代码.

Python相关问答推荐

sys.modulesgo 哪儿了?

避免循环的最佳方法

Python主进程和分支进程如何共享gc信息?

如何在Python中使用ijson解析SON期间检索文件位置?

Python -Polars库中的滚动索引?

使用Keras的线性回归参数估计

当多个值具有相同模式时返回空

如何使用Python将工作表从一个Excel工作簿复制粘贴到另一个工作簿?

为什么符号没有按顺序添加?

用Python解密Java加密文件

如何在虚拟Python环境中运行Python程序?

如何使用根据其他值相似的列从列表中获取的中间值填充空NaN数据

django禁止直接分配到多对多集合的前端.使用user.set()

如何使用pytest来查看Python中是否存在class attribution属性?

pyscript中的压痕问题

DataFrames与NaN的条件乘法

删除marplotlib条形图上的底边

UNIQUE约束失败:customuser. username

如何在Python中使用Pandas将R s Tukey s HSD表转换为相关矩阵''

交替字符串位置的正则表达式