Python多进程因内存分配问题停滞的技术咨询
问题分析与解决方案
核心原因
Linux与Windows的内存管理机制差异导致了该现象:
- 场景1:单进程分配内存接近总内存1/4:四个进程同时申请时,总需求接近系统可用内存上限。Linux内核会优先通过**页交换(Swap)**调度内存,导致进程被内核阻塞(等待内存页从swap加载/写入),无法执行到异常捕获逻辑,因此卡在
threading.py的wait方法处。 - 场景2:单进程分配内存超过总内存:此时内核直接触发OOM Killer终止进程。multiprocessing的Pool会检测到子进程异常退出,进而触发
func中的except块,打印"error"并返回None。 - Windows系统的内存管理不会依赖swap阻塞进程,而是直接拒绝内存分配请求,因此能正常触发异常捕获。
解决方案
1. 禁用Swap(临时生效)
禁用swap后,内核无法通过交换页满足内存需求,会直接拒绝超量的内存分配,触发MemoryError,进程即可进入异常处理流程:
swapoff -a
注意:该操作会影响系统其他进程的内存可用空间,仅适合测试场景。
2. 手动预检查可用内存
使用psutil库提前获取系统可用内存,避免分配接近临界值的内存:
import time import numpy as np import psutil def func(arg): try: # 获取系统可用内存(字节) available_mem = psutil.virtual_memory().available # 计算本次分配需要的内存:float64类型,每个元素8字节 required_mem = 40 * 1024 * 1024 * 128 * 8 # 预留10%内存,避免触发内核swap调度 if required_mem > available_mem * 0.9: raise MemoryError("Insufficient memory for allocation") print(f"Start allocating: {arg}") a = np.full((40, 1024, 1024, 128), 1.) print(f"Done allocating: {arg}") time.sleep(1) return arg except: print("error") return None if __name__=='__main__': import multiprocessing with multiprocessing.get_context('spawn').Pool(4) as pool: results = pool.map(func, range(4)) print(results)
3. 调整内存超配参数
修改Linux内核的内存超配策略,让系统直接拒绝超出可用内存的分配请求:
- 临时生效:
echo 2 > /proc/sys/vm/overcommit_memory - 永久生效:编辑
/etc/sysctl.conf,添加:
然后执行vm.overcommit_memory=2sysctl -p加载配置。
该参数设置为2时,内核会严格检查内存分配请求,仅允许分配不超过可用内存 + 交换分区*swap_ratio的空间,超出时直接返回分配失败,触发MemoryError。
内容的提问来源于stack exchange,提问作者Mads M Pedersen
相关产品推荐
相关产品推荐

