Python 3.8在Spyder中运行大数组运算时出现内存错误求助
处理大尺寸NumPy数组时的内存错误解决方案
我在Windows 11(16GB内存)上用Spyder运行Python程序,需要处理一个形状为(69496, 511)的二进制NumPy数组。代码如下:
import numpy as np import math import re def ip(A): B=A.transpose() C = np.dot(A, B) [a, b] = C.shape D=[] for i in range (a): print(i) for j in range (i+1, a): c= C[i, j] D.append(c) return(D)
执行D = ip(o)时触发内存错误:
MemoryError: Unable to allocate 36.0 GiB for an array with shape (69496, 69496) and data type float64
核心问题分析
代码中C = np.dot(A, B)会生成一个(69496, 69496)的矩阵,按float64类型计算需要约36GB内存,远超16GB的可用内存,这是内存错误的直接原因。根本不需要生成整个矩阵C,直接计算所需的上三角元素即可大幅降低内存占用。
优化方案
直接计算行向量点积,跳过巨大中间矩阵
修改代码,逐行计算当前行与后续所有行的点积,无需存储完整的C矩阵:import numpy as np def ip(A): D = [] n_rows = A.shape[0] for i in range(n_rows): print(i) # 取第i行,计算与i+1到末尾所有行的点积 row_i = A[i] dot_products = np.dot(A[i+1:], row_i) D.extend(dot_products.tolist()) return D这种方式仅需存储当前行和临时的点积结果,内存占用会骤降。
优化数据类型减少内存开销
输入是二进制数组(元素为0/1),点积结果为整数(对应位同为1的数量),可以转换为更小的整数类型(如int32)来进一步压缩内存:def ip(A): D = [] n_rows = A.shape[0] A_int = A.astype(np.int32) # 转换为int32类型,降低计算和存储开销 for i in range(n_rows): print(i) row_i = A_int[i] dot_products = np.dot(A_int[i+1:], row_i) D.extend(dot_products.tolist()) return D分块处理降低内存峰值(可选)
如果仍有内存压力,可将数组分块处理,每次计算一小块行向量与后续行的点积:def ip(A): D = [] n_rows = A.shape[0] block_size = 1000 # 可根据内存情况调整块大小 A_int = A.astype(np.int32) for i in range(0, n_rows, block_size): block = A_int[i:i+block_size] for row_idx in range(block.shape[0]): global_i = i + row_idx print(global_i) current_row = block[row_idx] dot_products = np.dot(A_int[global_i+1:], current_row) D.extend(dot_products.tolist()) return D使用生成器完全避免结果列表内存占用
若无需一次性存储所有结果,可改用生成器返回点积值,彻底省去列表D的内存开销:def ip(A): n_rows = A.shape[0] A_int = A.astype(np.int32) for i in range(n_rows): print(i) row_i = A_int[i] dot_products = np.dot(A_int[i+1:], row_i) yield from dot_products使用时可遍历生成器:
for val in ip(o): ...,或按需转换为列表。
内容的提问来源于stack exchange,提问作者Robin Kurtz
相关产品推荐
相关产品推荐

