不复制情况下将NumPy数组调整为较小的大小

6

当我使用resize方法收缩一个numpy数组(即由于resize而使数组变小),是否保证不会进行复制?

示例:

a = np.arange(10)            # array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
a.resize(5, refcheck=False)  # array([0, 1, 2, 3, 4])

据我理解,这应该总是可以在不进行复制的情况下实现。我的问题是:实现确实保证了这一点吗?不幸的是,resize 的文档没有提到这一点。


1
如果您的新大小始终会更小,为什么不切片数组并将其重新分配给自己呢? - EdChum
@EdChum:你是指 a = a[:5] 吗?老实说,我没有想过这个选项。虽然我不知道切片的内部工作原理,但这样做是否需要在其他地方制作数据副本呢? - luator
1个回答

4

numpy数组是一个固定大小的数组,任何类型的重新调整大小都会复制该数组。

也就是说,您可以创建该数组的切片,有效地仅使用该数组的子集,而无需调整大小/复制。

>>> import numpy
>>> a = numpy.arange(10)
>>> b = a[:5]
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> b
array([0, 1, 2, 3, 4])
>>>
>>> a += 10
>>> a
array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
>>> b
array([10, 11, 12, 13, 14])
>>>
>>> b += 10
>>> a
array([20, 21, 22, 23, 24, 15, 16, 17, 18, 19])
>>> b
array([20, 21, 22, 23, 24])

谢谢,我之前并不知道可以用切片来做这个。但是这种方法有一个缺点:未使用的a部分的内存不会被释放(在某些情况下可能会成为问题)。如果我执行del a会发生什么?它会保留全部数据还是只保留通过b可访问的部分? - luator
1
当执行 del a 时,它会保留 a,因为它仍然存在。b 只显示了 a 的一小部分,但它仍然存在。实际释放内存的唯一方法是将其复制到一个新数组中并删除旧数组。在后台,numpy 在创建/删除数组时只是执行标准的 malloc/free 操作,而在 C 中不可能释放数组的一部分。 - Wolph
还有一个问题:为什么在缩小数组时resize必须进行复制?我不是内存分配的专家,但是难道不应该只释放已分配内存的后面部分,而保留前面部分而无需复制任何内容吗? - luator
我明白了。如果不了解更多使用情况,很难给出有意义的建议,但也许稀疏矩阵(scipy.sparse)或多个数组的组合在这种情况下会更有益。此外,不要忘记选择正确的数据类型。float32 的大小是 float64 的一半,在许多情况下已经足够了。 - Wolph
1
@Mr.F: 没错,但据我所知,这仅适用于简单地改变数组的形状(而不是大小)。例如,从(4,1)调整大小到(2,2)(1,4)。不过,我应该注意一下,我没有仔细查看过源代码。有关更多信息,请在此处查找源代码:https://github.com/numpy/numpy/search?l=c&q=resize&utf8=%E2%9C%93 - Wolph
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接