电脑 CPU 为 `AMD Ryzen 7 6800H` ,8 核 16 进程

系统为 `Windows 11`

任务为对一组数据做分段 FFT ,因为每段 FFT 相互无关,所以将整段数据分为 `n_jobs` 块后每块并行计算,试图加速(具体代码不能公开,正在整理一份能复现的代码)。但是发现了奇怪的情况,保持其他参数不变,使用 `parallel = Parallel(n_jobs=int(n_jobs))` ,当 `n_jobs` 大于 4 后,总体用时不会下降。

![代码性能测试]( https://i.piantu.cn/i/0/2024/10/67161a5318fea.png)

深入进程测试后发现每个进程内部的 `for` 循环内的代码拖慢了速度,代码如下(正常来说怎么测试每行代码的性能呢……望大佬指路!):

```python
tCost = []

for i in batchTask:
    tCost.append([time.time()])

    startTime = sampleDot[0] + i * step
    endTime = startTime + step

    splitSampleDot = sampleDot[
        np.where((sampleDot >= startTime) & (sampleDot < endTime))
    ]

    tCost[-1].append(time.time() - tCost[-1][0]) # ckpt t0

    splitData = np.array(list(zip(splitSampleDot, linearData(splitSampleDot))))

    tCost[-1].append(time.time() - tCost[-1][0]) # ckpt t1
   
    signal, powerDensity = getFftResult(
        splitData,
        splitSampleDot,
        float(sampleRate),
        0.0,
        0.8,
        float(minFreq),
    )

    tCost[-1].append(time.time() - tCost[-1][0]) # ckpt t2

    powerDensity[powerDensity < displayThreshold] = np.nan

    tCost[-1].append(time.time() - tCost[-1][0]) # ckpt t3

    fftDataList.append(powerDensity)
    fftFreqList.append(signal)

    fftStartTimeList.append(datetime.fromtimestamp(startTime))

    tCost[-1].append(time.time() - tCost[-1][0]) # ckpt t4

    realTimeDateObjList.append(
        mdates.date2num(np.vectorize(datetime.fromtimestamp)(splitSampleDot))
    )

    tCost[-1].append(time.time() - tCost[-1][0]) # ckpt t5
```

请问为什么会出现这种情况呢?有哪些办法能进一步提升性能呢?
举报· 172 次点击
登录 注册 站外分享
7 条回复  
BingoXuan 小成 2024-10-21 17:27:58
因为你只有 8 核
vicalloy 小成 2024-10-21 17:31:12
看一下每个核的 CPU 占用率,如果负载满了就是到性能瓶颈了。
Donaldo 小成 2024-10-21 17:47:09
@Leon6868 #2 上下文切换,缓存同步,核间通信也有开销的,实际上很难(甚至可以说不可能)做到 N 个核的效率是 1 个核的 N 倍。
NoOneNoBody 小成 2024-10-21 18:09:13
windows
python 多进程还有很多消耗,基本上达不到 total/n 这么完美的效果
然后,你需要一些特殊的包,控制 CPU 亲和度,把闲置的 CPU 核分给进程
另外,我的经验是外部跑一些消耗的软件,如播放器、浏览器,python 多进程的效率会大幅降低,只有保留 CPU 专用,才能保持一个相对较高效率
还有内存,当内存用满,也是会大幅效率降低

如果数据不是十份庞大,多进程提升不大,数据庞大且内存足够,建议想办法跑 numba ,如果实在难以跑 numba ,也要尽量用 np/pd 的向量函数

你这里用了大量 append ,考虑一下换成一次生成的思路
或者改写方式,就是预置长度,所有元素为默认值,然后定位再赋值计算结果
yzongyue 初学 2024-10-21 18:22:10
瓶颈不一定在 cpu , 跑代码的时候,把任务管理器打开, 看看是不是内存/磁盘 io 满了
Riyue 小成 2024-10-21 18:31:58
numpy 底层的 mkl openblas 自动利用多核,不知道会不会是原因之一
Clouder1 小成 2024-10-21 18:46:56
一个原因是你只有 8cores ,另一部分原因是:多进程本身就有开销,比如启动进程的开销、进程通信拷贝数据的开销,以及如果你使用的某些库本身就会使用多线程、向量化之类的手段优化性能,开太多进程其实对并行计算也没有多少帮助。提名 numpy/polars 等。
如果想要逐行 profile ,可以参考 https://stackoverflow.com/questions/3927628/how-can-i-profile-python-code-line-by-line
返回顶部