【问题标题】:Numpy: delete column from very big memory mapped Numpy ArrayNumpy:从非常大的内存映射的 Numpy 数组中删除列
【发布时间】:2016-06-30 14:05:03
【问题描述】:

假设我有一个非常大的 numpy 内存映射数组:

fp = np.memmap("bigarray.mat", dtype='float32', mode='w+', shape=(5000000,5000))

现在经过一些操作等,我想删除第 10 列:

fp = np.delete(fp,10,1)

这会导致内存不足错误,因为 (??) 返回的数组是内存数组。我想要的是一个纯内存映射删除操作。

在全内存映射模式下删除列最有效的方法是什么?

【问题讨论】:

  • 必须是列吗?你能转置你的数据模型吗?您是否检查过更改内存布局的order 参数?如果我没记错 numpy 的默认值,删除一列对内存非常不利
  • 如果要删除的列数很少,最好忽略它。只需在单独的数组中列出相关/不相关的列。如果列的数量很大,为什么不将剩余的列复制到一个新数组中呢?然后对齐就ok了。

标签: python arrays numpy memory out-of-memory


【解决方案1】:

免责声明:我总是把行和列弄得一团糟,所以我可能会在这个答案中失言......

一个重要的问题是删除不连续的数据块是一件非常重要的事情。例如,考虑一个更小的例子:

fp = np.memmap("bigarray.mat", dtype='float32', mode='w+', shape=(1000000,10000))

这个memmap 将有10**10 元素,每个元素4 个字节。这意味着这个结构将接近 40GB。它不适合我的笔记本电脑内存,所以可以使用它。

以下将移动所有行,有效地删除第 10 行:

for i in range(10, 999999):
    fp[i, :] = fp[i+1, :]

这有效(几乎杀死了我的操作系统,但有效)。然而,以下将打破一切:

for i in range(10, 9999):
    fp[:, i] = fp[:, i+1]

这是因为要更改第 11 列,您需要更改所有行。默认情况下,文件(和内存)中的布局是基于行的。这意味着您必须访问许多不同的地方才能获得所有必需的数字才能进行更新。

我的经验是,当事情开始不适合内存时,一切都会停止,我不知道它是在交换还是在做一些缓存。但是,有效的行为是:它突然停止并且不做任何事情。

当然,您可以为内存访问制定一些更好的算法,不需要在内存中保存完整的行等,但这是我通常不会期望的优化级别,因为它非常麻烦实施,将会非常慢(大量随机访问磁盘,如果你没有 SSD,你就死定了)并且不是很常见的情况。

如果您必须使用列,您可能需要在构建memmap 时更改order 参数。 Fortran 使用基于列而不是行的内存布局,因此将修复列删除示例。但是,在该数据结构中,删除一行将是中断操作。

这个order参数在numpy documentation的几个地方都有解释:

[参数:order'C''F'] 指定 ndarray 内存布局的顺序:row-major,C-style 或 column-major,Fortran-style。这仅在形状大于 1-D 时才有效。默认顺序为“C”。


但是请考虑到,如果您执行“删除”,您将移动大量 GB。而且因为你不能在内存中这样做(它不适合),你需要有效地修改文件。这将是一个巨大的操作,而且会非常缓慢。我会说你可能需要某种额外的逻辑来执行“掩码”或类似的东西。但是在更高的级别上,而不是在 numpy 级别上(尽管它可能有一些封装了它的视图类,但我并不完全确定)。你还没有告诉你的用例,所以我只能猜测。但是...您正在处理大量数据,移动它是个坏主意 (TM)。

【讨论】:

    猜你喜欢
    • 2020-01-25
    • 2014-11-29
    • 1970-01-01
    • 2020-08-28
    • 1970-01-01
    • 2013-10-05
    • 1970-01-01
    • 2011-03-10
    • 2020-04-19
    相关资源
    最近更新 更多