首页 > 解决方案 > Python numpy 在大计算后不释放交换

问题描述

我有两组大数组float32

centers = np.random.uniform(-1, 1, (64, 40, 42)).astype(dtype=np.float32)
data = np.random.uniform(-1, 1, (60000, 40, 42)).astype(dtype=np.float32)

我想从这个数组中的每个中心点减去每个数据点并得到 abs 值。这是我尝试执行此操作的一种方法

diff = [np.abs(data - c) for c in centers]

在我的具有 16GB RAM 和 2GB 交换空间的 linux PC 中,这不仅提供了MemoryError; 在因错误而崩溃后htop,我可以看到交换空间仍然被填满。

对于 MemoryError,我重写了代码以data一次使用切片而不是整个数组。(编辑MemoryError现在不,但进程会在一段时间后被杀死SIGKILL)但它仍然很慢,交换未释放仍然存在。我这样做的方式是否存在内存泄漏?

额外的问题:有计算差异的有效方法吗?即使我使用data. 如果我使切片更小,循环会花费太多时间

标签: pythonnumpymemorymultidimensional-array

解决方案


注意:我假设您要迭代每个数组的第一个维度并计算其他维度之间的绝对差。如果它不是您打算计算的,请改写它。

发电机

如果您不需要一次访问所有结果,您可以使用生成器来减少内存消耗并按需执行计算:

import itertools
import numpy as np

def generate_distance(a, b):
    for i, j in itertools.product(range(a.shape[0]), range(b.shape[0])):
        yield np.abs(a[i,:,:] - b[j,:,:])

然后您可以通过发出一次获得所有结果(这将消耗大量内存,因为它存储所有结果):

x = np.array(list(generate_distance(data, centers)))

或者只是动态消耗它(这将大大减少所需的内存量,因为它只会在需要时计算距离):

for d in generate_distance(data, centers):
    # perform some computation on distance

记忆

您可以使用以下方法检查对象的大小:

import sys
sys.getsizeof(data)/1024**2 # 384.5216064453125 Mb

如果您的目标是存储所有结果,您还可以估计所需的内存量,基本上它会比尺寸乘以dtype. 在您的情况下,这将是:

64*60000*40*42*4 bytes ~ 24.609,375 Mb

这绝对超过了您的 RAM 和交换容量的总和。

解决方法

所以,你有几个选择:

  • 如果您需要将结果保存在 RAM 中,则必须对其进行批处理,因为完整的结果不适合给定的设置;
  • 如果你只是需要将所有结果存储在磁盘上,那么使用生成器来降低内存消耗并将距离一一写入文件;
  • 如果您需要 RAM 中的结果但​​不是一次全部,请使用生成器链接您的计算流并按需将距离发送到另一个进程。

推荐阅读