有没有一种方法可以在对numpy数组进行切片时不进行复制?

2024-04-29 09:42:08 发布

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

我需要在我的项目中处理一些大的numpy数组。从磁盘加载这样一个数组之后,我的计算机的内存将消耗掉一半以上。你知道吗

在数组加载之后,我对它做了几个切片(几乎一半的数组都会被选中),然后我收到错误消息,告诉我内存不足。你知道吗

通过做一个我理解的小实验,我收到了错误,因为当numpy数组被切片时,将创建一个副本

import numpy as np

tmp = np.linspace(1, 100, 100)
inds = list(range(100))
tmp_slice = tmp[inds]

assert id(tmp) == id(tmp_slice)

返回AssertionError

有没有办法使numpy数组的片只引用原始数组的内存地址,这样就不会复制数据项?你知道吗


Tags: 项目内存numpyid消息计算机错误np
2条回答

在Python中,slice是一个定义良好的类,具有startstopstep值。当我们用alist[1: 10: 2]索引列表时使用它。这将生成一个新列表,其中包含原始指针的副本。在numpy中,它们用于basic indexing,例如arr[:3, -3:]。这将创建原始的viewview共享数据缓冲区,但有自己的shapestrides。你知道吗

但是当我们用列表、数组或布尔数组(mask)索引数组时,它必须创建一个副本,一个有自己数据缓冲区的数组。元素的选择太复杂或不规则,无法用shapestrides属性来表示。你知道吗

在某些情况下,索引数组很小(与原始数组相比),副本也很小。但是如果我们排列整个数组,那么索引数组和副本都将和原始数组一样大。你知道吗

通过阅读thisthisthis我认为你的问题在于使用高级切片,重申其中一个答案numpy docs清楚地表明

Advanced indexing always returns a copy of the data (contrast with basic slicing that returns a view).

因此,与其这样做:

inds = list(range(100))
tmp_slice = tmp[inds]

您应该使用:

tmp_slice = tmp[:100]

这将导致view rather than a copy。您可以通过尝试以下方法来发现差异:

tmp[0] = 5

在第一种情况下tmp_slice[0]将返回1.0,但在第二种情况下它将返回5。你知道吗

相关问题 更多 >