通过并行化加速numpy标准正态分布随机数生成的问题咨询
问题原因分析
你的多进程方案速度更慢主要来自两个核心开销:
- 进程间通信(IPC)开销:你用
multiprocessing.Pool的方案里,每个子进程生成的250000×100的float数组(单份约200MB)需要完整拷贝回主进程,4份合计800MB的数据拷贝开销,已经超过了随机数生成本身的计算开销。同时进程启动、参数传递也有额外耗时。 - numpy随机数生成本身的优化程度高:
default_rng的standard_normal是经过SIMD指令优化的实现,单进程运行时已经吃满了单核的算力,本身计算耗时很低,并行带来的计算收益完全覆盖不了额外开销。
可行优化方案
方案1:改用多线程避免IPC开销
numpy的随机数生成函数运行时会释放GIL,用多线程替代多进程可以完全避免跨进程数据拷贝的开销,代码修改量极小:
from numpy.random import default_rng from concurrent.futures import ThreadPoolExecutor from time import time def rng_mp(seed): return default_rng(seed).standard_normal((250000, 100)) if __name__ == '__main__': n_proc = 4 seeds = range(n_proc) rng_all = default_rng(1) start = time() result = rng_all.standard_normal((int(1e6), 100)) print(f'Single process: {time() - start:.3f} seconds') start = time() with ThreadPoolExecutor(max_workers=n_proc) as p: result = list(p.map(rng_mp, seeds)) print(f'MT: {time() - start:.3f} seconds')
该方案在4核机器上通常可以拿到3倍左右的性能提升。
方案2:用共享内存进一步优化
如果需要生成的数组更大,可以预分配共享内存,子进程/子线程直接往共享内存写数据,连最后拼接数组的开销都可以省掉。
方案3:按需生成分段数组
如果后续是分段处理数据,完全不需要一次性生成全量数组,用生成器按需生成对应分段即可,既省内存又省初始化时间。
内容的提问来源于stack exchange,提问作者Wouter
相关产品推荐
相关产品推荐

