Python numpy在大型计算后未释放交换

Python numpy在大型计算后未释放交换,python,numpy,memory,multidimensional-array,Python,Numpy,Memory,Multidimensional Array,我有两大组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] 在带有16

我有两大组
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中,这不仅会产生
内存错误
;由于错误而崩溃后,从
htop
,我可以看到交换空间仍然被填满

对于MemoryError,我重写了代码以使用
数据的片段,而不是一次使用整个数组。(EDIT:现在没有
MemoryError
,但进程在经过一段时间后被
SIGKILL
终止,它说)但仍然非常缓慢,交换不释放仍然存在我执行此操作时是否存在内存泄漏?


奖金问题:有没有一种有效的方法来计算差额?创建数组似乎比计算花费的时间要多,即使我使用
数据片
。如果我将切片变小,循环将花费太多时间。注意:我假设您要迭代每个数组的第一个维度,并计算其他维度之间的绝对差。如果它不是你想要计算的,请重新措辞

发电机 如果您不需要一次访问所有结果,则可以使用generator减少所消耗的内存量,并按需执行计算:

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,:,:])
然后,您可以通过发出以下命令一次获得所有结果(这将消耗大量内存,因为它存储所有结果):

或者直接使用它(这将大大减少所需的内存量,因为它只在需要时计算距离):

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

import sys
sys.getsizeof(data)/1024**2 # 384.5216064453125 Mb
如果要存储所有结果,还可以估计所需的内存量,基本上它会比维度与
dtype
大小的乘积大一点。在您的情况下,它将是关于:

64*60000*40*42*4 bytes ~ 24.609,375 Mb
这肯定超过了RAM和交换容量的总和

变通办法 因此,您几乎没有选择:

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

这给我的结果与用大块的
数据
来计算差异几乎相同。这和我的两个代码都使用较小的数组,没有问题(是的
数据
是384Mb)@Teshanhanukaj,你能更好地解释一下你想要执行的操作吗,预期结果的形状是什么?你能告诉我们你是否需要所有的结果都是一次性的吗。因为如果你按需使用生成器而不是存储所有结果,它将大大降低所需的内存量。实际上,我不想一次存储所有结果。我只是专注于使代码更快,我没有想到这一点。谢谢你的见解,不客气,出于好奇,我是否正确地实现了你的计算?干杯。你的生成器代码必须工作,但我想计算它们,我想一次计算所有中心的一个数据点之间的差异。以前,我一次对所有中心进行所有数据点,然后进行下一次计算。因此,我将代码更改为类似于c的循环:get diff->do calculations->store result
import sys
sys.getsizeof(data)/1024**2 # 384.5216064453125 Mb
64*60000*40*42*4 bytes ~ 24.609,375 Mb