如何优化Python处理十亿级条目数组时的内存占用?
问题原因
你当前的代码触发OOM(内存不足)被系统杀死,核心原因有两个:
- 初始数组内存占用过大:你创建的数组范围是
150000000:3000000000,对应28.5亿个int64类型元素,仅数组本身就占用约22.8GB内存,已经超过M1 MacBook Air的常规内存上限(8/16GB)。 - 笛卡尔积冗余加载:你将
itertools.product(array, array)强制转为list,会尝试把约8×10^18个元素全部加载到内存,这是完全不可能完成的操作,直接触发系统杀进程。
优化方案
根据你的实际需求,按优先级推荐以下方案:
方案1:连续整数场景极致优化(无需创建数组,毫秒级出结果)
你当前使用的是连续整数数组,要找两个数之和等于目标值3756499519,完全不需要创建数组或者遍历,直接通过不等式计算就能得到所有解:
设数组取值范围为L=150000000 ≤x ≤R=2999999999,需要满足x + y = 3756499519,推导可得x的有效范围:
x ≥ 3756499519 - R = 756499520x ≤ 3756499519 - L = 3606499519
结合x本身的取值范围,所有满足756499520 ≤x ≤2999999999的整数都是有效解,对应y值为3756499519 -x,比如取x=756499520,y=2999999999就是符合要求的结果。
方案2:非连续数组通用优化(O(n)时间复杂度,无冗余内存)
如果你的数组是离散非连续的,这是经典的两数之和问题,用哈希集合即可解决,完全不需要生成笛卡尔积:
import numpy as np from datetime import datetime target = 3756499519 startTime = datetime.now() # 离散数组请替换为你的加载逻辑,内存不足可分批加载 array = np.ogrid[150000000:3000000000] num_set = set() found = False for x in array: complement = target - x if complement in num_set: print("Found: ", complement) print("Found: ", x) found = True break num_set.add(x) if not found: print("No matching pair found") print("Running took: ", datetime.now() - startTime)
该方案仅需存储大小和原数组一致的哈希集合,不会产生额外冗余数据。
方案3:必须使用笛卡尔积的优化(不推荐,仅做参考)
如果业务要求必须遍历所有两两组合,绝对不要把itertools.product转为list,直接迭代其原生生成器即可,生成器会边迭代边生成元素,不会全量加载到内存:
# 仅修改原for循环行,去掉外层list() for element in itertools.product(array, array):
注意该方案时间复杂度为O(n²),对于28亿规模的数组完全无法在可接受时间内跑完,仅做原理参考。
额外提醒
如果你确实需要生成所有两两求和的结果,28亿规模数组的两两组合有8×10^18个元素,全球所有存储设备加起来都无法容纳,建议先确认需求是否合理,是否可以对结果做分片、过滤等预处理。
内容的提问来源于stack exchange,提问作者Lais Bento
相关产品推荐
相关产品推荐

