为什么Python3复杂矩阵计算使用多进程反而比单进程运行慢?
问题分析与修正方案
多进程使用的核心错误
- 未回收子进程计算结果:
multiprocessing.Process默认不会将函数返回值传回主进程,你当前的多进程代码仅启动了计算任务,结果完全没有被回收,不过该问题不影响现有耗时统计的有效性。 - 进程开销覆盖了计算收益:尺寸小于1024阶的矩阵计算耗时仅为微秒/毫秒级,但macOS系统下
multiprocessing默认采用spawn模式启动子进程,每个子进程需要重新加载Python解释器,且传入的矩阵需要完整拷贝到子进程内存空间,这部分开销远大于并行计算带来的收益,所以小尺寸矩阵下多进程反而更慢。 - 和numpy原生多线程冲突:你用到的
np.dot在M1芯片上会调用Apple官方的Accelerate框架,本身已经实现了多核并行优化,手动再开多进程会导致CPU资源竞争,反而拉低计算效率。 - 大矩阵内存占用超标:8192阶的单张float64矩阵占用内存约为512MB,3张矩阵合计1.5GB,开3个子进程需要额外拷贝3份矩阵,瞬时内存占用超过6GB;2^14即16384阶的单张矩阵就占2GB内存,多进程拷贝后内存直接超出普通M1设备的物理内存上限,系统触发虚拟内存交换,所以耗时极长无法输出结果。
和M1设备的关联
- M1采用统一内存架构,多进程间的数据拷贝开销比x86架构的独立内存更高,spawn模式创建进程的额外开销也更明显。
- macOS默认对进程资源限制更严格,大内存负载下虚拟内存交换的性能衰减比Linux系统更显著。
- M1配套的Accelerate框架BLAS运算并行效率已经很高,手动多进程很难超过原生优化的性能。
修正方案
- 对于numpy已经原生优化的矩阵运算场景,优先依赖numpy本身的多线程能力,不要盲目使用多进程,仅当单任务计算耗时超过1秒时再考虑并行改造。
- 如果要验证并行收益,优先使用多线程而非多进程:numpy运算会自动释放GIL,多线程不需要拷贝地址空间,开销远低于多进程,可使用
concurrent.futures.ThreadPoolExecutor实现。 - 必须使用多进程时,要采用共享内存存储矩阵,避免每个子进程都拷贝全量数据,可通过
multiprocessing.Array实现共享内存,降低数据传输开销。 - 测试前提前计算矩阵内存占用,不要超过设备物理内存上限,8GB内存的M1设备建议最大测试尺寸不要超过8192阶。
优化后的测试代码示例
#!/usr/bin/env python3 import numpy as np import time from concurrent.futures import ThreadPoolExecutor def mat_mul(mat1, mat2): return np.dot(mat1, mat2) if __name__ == '__main__': # 仅测试计算耗时大于10ms的矩阵尺寸 for n in (2**p for p in range(8, 14)): # 直接用numpy生成随机矩阵,替代原来的低效循环生成 x = np.random.randint(0, 256, size=(n,n)).astype(np.float64) y = np.random.randint(0, 256, size=(n,n)).astype(np.float64) # 串行计算耗时统计 start = time.time() res1 = mat_mul(x, x) res2 = mat_mul(x, x.T) res3 = 4 * mat_mul(y, y) total = res1 + res2 + res3 serial_time = time.time() - start # 多线程并行计算耗时统计 start = time.time() with ThreadPoolExecutor(max_workers=3) as executor: future1 = executor.submit(mat_mul, x, x) future2 = executor.submit(mat_mul, x, x.T) future3 = executor.submit(mat_mul, y, y) res1 = future1.result() res2 = future2.result() res3 = 4 * future3.result() total = res1 + res2 + res3 parallel_time = time.time() - start print(f"矩阵尺寸{n}: 串行耗时{serial_time:.4f}s, 并行耗时{parallel_time:.4f}s")
内容的提问来源于stack exchange,提问作者Prashanthv
相关产品推荐
相关产品推荐

