使用大型Numpy阵列的技术?

2024-05-15 13:09:23 发布

您现在位置:Python中文网/ 问答频道 /正文

有时必须对一个或多个大型Numpy数组执行许多中间操作。这会很快导致MemoryErrors。到目前为止,在我的研究中,你已经发现腌制(Pickle、CPickle、Pytables等)和gc.collect()是缓解这种情况的方法。我想知道有经验的程序员在处理大量数据时是否使用了其他技术(当然,除了消除策略/代码中的冗余之外)。

还有,如果有一件事我可以肯定的话,那就是没有什么是免费的。对于其中的一些技术,有哪些折衷(即速度、健壮性等)?


Tags: 数据方法numpy情况数组经验pytables策略
3条回答

dask.array库提供了一个numpy接口,该接口使用阻塞的算法处理具有多个内核的大于内存的数组。

您还可以查看SpartanDistarrayBiggus

第一个最重要的技巧是:分配几个大数组,并使用和回收其中的一部分,而不是使用和丢弃/垃圾收集大量临时数组。听起来有点老套,但如果精心编程,速度会令人印象深刻。(您可以更好地控制对齐和数据位置,因此可以使数字代码更加高效。)

第二:使用^{}并希望操作系统缓存对磁盘的访问足够有效。

第三:正如@Jaime所指出的,如果整个矩阵是大的,则使用非块子矩阵。

编辑:

避免不必要的列表理解,正如SE中的answer所指出的。

我感觉到你的痛苦。。。有时,您最终会在以后丢弃的值中存储数倍于数组大小的值。当一次处理数组中的一个项时,这是不相关的,但在矢量化时可能会杀死您。

我将用一个工作中的例子来说明。我最近用numpy编写了here描述的算法。这是一种颜色映射算法,它将一个RGB图像转换成一个CMYK图像。对每个像素重复的处理如下:

  1. 使用每个RGB值中最重要的4位作为三维查找表的索引。这将确定LUT中立方体8个顶点的CMYK值。
  2. 基于上一步的顶点值,使用每个RGB值的最低有效4位在该立方体内插值。要做到这一点,最有效的方法是计算16个uint8数组,其大小与正在处理的图像大小相同。对于一个24位的RGB图像,它相当于需要x6倍的存储空间来处理它。

你可以做一些事情来处理这个问题:

一。分而治之

可能无法在一次过程中处理1000x1000数组。但是,如果您可以使用python for循环遍历10个100x1000数组,那么它仍然会远远超过python迭代器遍历1000000个项目!会比较慢,是的,但不会太慢。

2。缓存昂贵的计算

这与我上面的插值示例直接相关,而且更难理解,尽管值得关注。因为我在三维立方体上插值,每个维度有4位,所以只有16x16x16个可能的结果,可以存储在16个16x16x16字节的数组中。因此,我可以使用64KB的内存对它们进行预计算和存储,并逐个查找整个图像的值,而不是以巨大的内存开销对每个像素重复相同的操作。这已经为小到64x64像素的图像带来了回报,并且基本上允许在不需要细分数组的情况下处理像素数为x6倍的图像。

三。明智地使用你的dtypes

如果中间值可以放在单个uint8中,请不要使用int32s数组!这可能会因为无声的溢出而变成一个神秘错误的噩梦,但是如果你小心,它可以提供很大的资源节约。

相关问题 更多 >