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]

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

对于MemoryError,我重写了代码,使其同时使用data的切片,而不是整个数组。(编辑:现在没有MemoryError,但进程在使用SIGKILL一段时间后会被终止,它说(但它仍然很慢,交换不释放仍然存在我这样做是不是有内存泄漏

奖金问题:有没有一种有效的方法来计算差异?创建数组似乎比进行计算花费了太多时间,即使我使用data的切片进行计算也是如此。如果我缩小切片,循环会花费太多时间

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

发电机

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

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中的结果,但不是一次全部结果,请使用生成器来链接您的计算流,并根据需要将距离发送到另一个进程

最新更新