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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 07:05:29