分配大共享内存触发Bus error (core dumped)问题求助
大尺寸共享内存分配触发"Bus error (core dumped)"的问题分析与解决
问题现象
分配占128GiB总内存60%的共享内存时,程序运行数秒后抛出Bus error (core dumped)错误,内存占用持续上升;但使用普通内存分配的b()函数运行完全正常。
复现代码
from multiprocessing.managers import SharedMemoryManager import numpy as np SIZE = 70462337280 # Exact size is not quite important def spin(): import time while True: time.sleep(60) def a(): with SharedMemoryManager() as smm: shm = smm.SharedMemory(size=SIZE) buf = np.ndarray((SIZE,), dtype=np.uint8, buffer=shm.buf) buf.fill(0) print("Done") spin() def b(): buf = np.empty((SIZE,), dtype=np.uint8) buf.fill(0) print("Done") spin() # Bus error (core dumped) a() # Works fine # b()
已排查信息
已确认shmmax参数无限制:
cat /proc/sys/kernel/shmmax 18446744073692774399
问题原因
Bus error本质是进程尝试访问无效的物理内存地址,这里的核心差异在于共享内存与普通内存的物理映射机制不同:
- 普通内存(
np.empty分配)属于进程私有地址空间,内核采用按需分页策略,只有当实际访问内存页时才分配物理内存,且可借助swap空间缓解压力; - 共享内存创建后,执行
buf.fill(0)会强制将所有虚拟内存页映射到物理内存,此时如果系统物理内存+swap不足以承载,或者存在shmall这类总共享内存页数限制,就会触发Bus error。
很多人容易忽略shmall参数——它限制的是系统可分配的共享内存总页数,而非单块共享内存的大小(shmmax管的是单块最大值)。
解决方案
1. 检查并调整shmall参数
执行以下命令查看当前shmall值:
cat /proc/sys/kernel/shmall
对于128GiB的系统,shmall至少需要设置为34359738368(计算方式:128*1024*1024*1024 / 4,默认页大小4KiB)。
- 临时生效:
echo 34359738368 > /proc/sys/kernel/shmall
- 永久生效:
编辑/etc/sysctl.conf,添加或修改:
kernel.shmall = 34359738368
然后执行sysctl -p让配置生效。
2. 验证swap空间可用性
执行free -h查看swap是否开启且有足够空间。如果物理内存不足,确保swap空间能补充缺口(虽然共享内存对swap的依赖较低,但部分系统会允许共享内存页交换到swap)。
3. 分块填充共享内存
如果无法调整系统参数,可以尝试分块填充共享内存,避免一次性触发全量物理内存映射:
def a(): with SharedMemoryManager() as smm: shm = smm.SharedMemory(size=SIZE) buf = np.ndarray((SIZE,), dtype=np.uint8, buffer=shm.buf) # 分块填充,每块1GiB block_size = 1024*1024*1024 for i in range(0, SIZE, block_size): end = min(i + block_size, SIZE) buf[i:end].fill(0) print("Done") spin()
验证
调整参数或修改代码后,重新运行a()函数,确认是否还会出现Bus error。
内容的提问来源于stack exchange,提问作者obfish
相关产品推荐
相关产品推荐

