You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

开启vm.overcommit_memory=1后Numpy仍报MemoryError的问题求助

树莓派32位系统下Numpy内存分配异常问题

我在树莓派armv7l(4GB内存,32位系统)上运行代码时遇到numpy报错:numpy.core._exceptions.MemoryError,但机器仍有大量可用内存,按道理不应出现此问题。

系统状态与配置

内存状态

$ free
              total        used        free      shared  buff/cache   available
Mem:        3748172       87636     3384520        8620      276016     3528836
Swap:       1048572           0     1048572

内核内存超配设置

$ cat /proc/sys/vm/overcommit_memory
1

测试代码与报错

触发报错的测试代码

import numpy as np
arrays = [np.empty((18, 602, 640), dtype=np.float32) for i in range(200)]

报错信息

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <listcomp>
numpy.core._exceptions.MemoryError: Unable to allocate 26.5 MiB for an array with shape (18, 602, 640) and data type float32

进一步测试结果

def allocate_arr(i):
     print(i, i * 26.5)
     return np.empty((18, 602, 640), dtype=np.float32)

arrays = [allocate_arr(i) for i in range(0, 200)]

报错时输出:

1 26.5
2 53.0
3 79.5
...
111 2941.5
112 2968.0
113 2994.5
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <listcomp>
  File "<stdin>", line 3, in allocate_arr
numpy.core._exceptions.MemoryError: Unable to allocate 26.5 MiB for an array with shape (18, 602, 640) and data type float32

疑问:为何Python/Numpy会出现此行为?如何解决?3GB是否为限制?能否提升?内存超配的作用为何未生效?


原因分析

1. 32位进程的虚拟地址空间限制

32位Linux进程的虚拟地址空间总上限为4GB,默认配置下内核会预留1GB自用,留给用户态进程的仅3GB。测试中分配接近3GB时触发错误,完全对应这个硬限制——哪怕物理内存有4GB,32位进程也无法突破虚拟地址空间的上限。

2. 内存超配不适用此场景

vm.overcommit_memory=1的作用是允许内核分配超过物理内存总量的地址空间,但它无法突破32位进程的虚拟地址空间上限。这个配置解决的是物理内存不足时的分配问题,而你遇到的是进程地址空间耗尽的问题,所以超配设置完全无效。

3. Numpy的连续内存要求

Numpy数组需要占用连续的虚拟地址空间,即使进程总可用虚拟内存足够,若地址空间碎片化,也可能找不到一块连续的26.5MiB空间触发错误。不过你的测试中是接近3GB阈值时报错,核心原因还是虚拟地址空间上限。


解决方法

1. 切换到64位系统

这是彻底解决问题的最优方案。树莓派4B及以上型号支持64位Raspberry Pi OS,切换后进程虚拟地址空间可扩展至TB级,能充分利用4GB物理内存,也不存在3GB用户态限制。

2. 优化内存使用策略(不换系统的临时方案)

  • 按需创建和释放数组:避免一次性批量分配大量数组,用完即手动释放(del array + gc.collect())。
  • 使用内存映射文件:用np.memmap将部分数组存储到磁盘,减少对物理内存和虚拟地址空间的占用。
  • 降低数据精度:如果业务允许,将float32换成float16,单个数组内存占用直接减半。

3. 调整内核地址空间分割(不推荐)

部分32位Linux内核支持将用户态/内核态地址空间比例从3GB/1GB改为3.5GB/0.5GB,但需要重新编译内核,且会减少内核可用空间,可能导致系统稳定性问题,仅作为极端场景的临时手段。


内容的提问来源于stack exchange,提问作者Almog-at-Nailo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 10:57:52