python - 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
. 如果我使切片更小,循环会花费太多时间
解决方案
注意:我假设您要迭代每个数组的第一个维度并计算其他维度之间的绝对差。如果它不是您打算计算的,请改写它。
发电机
如果您不需要一次访问所有结果,您可以使用生成器来减少内存消耗并按需执行计算:
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 中的结果但不是一次全部,请使用生成器链接您的计算流并按需将距离发送到另一个进程。
推荐阅读
- appium - WebDriverAgent 文件夹缺少 appium 1.15.1
- amazon-web-services - AWS Lambda 函数:它不显示现有角色的列表
- mysql - 查看 Libreoffice Base 对 mysql 的查询
- python - 如何使用 Django Filters 过滤同一字段的多个值?
- python - 从 Python 中的父文件夹导入模块
- c# - 无法使用 SharePoint 客户端 API 列出文件/文件夹
- sql - 如何使用 LINQ 使用一个表获取另一个表的值
- python - 使用 selenium 捕获网络请求
- authentication - 在 cakephp 3 中对多个模型使用身份验证
- git - 通过 LibGit2Sharp 将 Blazor GitHub 存储库文件放入索引数据库