假设我有一个非常大的numpy内存映射数组:
fp = np.memmap("bigarray.mat",dtype='float32',mode='w+',shape=(5000000,5000))
现在经过一些操作等,我想删除第10列:
fp = np.delete(fp,10,1)
一个重要的问题是删除不连续的数据块是一件非常重要的事情.例如,考虑一个小例子:
fp = np.memmap("bigarray.mat",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使用基于列而不是行的内存布局,因此将修复列删除示例.但是,在该数据结构中,删除行将是中断操作.
这个订单参数在numpy documentation的几个地方解释:
[parameter:
order
,either'C'
or'F'
] Specify the order of the ndarray memory layout: row-major,C-style or column-major,Fortran-style. This only has an effect if the shape is greater than 1-D. The default order is ‘C’.
但是要考虑到,如果你执行“删除”,你将移动很多GB.而且因为你不能在内存中做到这一点(它不适合),你需要有效地修改文件.这将是一个巨大的操作,这将是非常缓慢的.我会说你可能想要某种额外的逻辑来执行“掩码”或类似的东西.但是在更高级别,而不是在numpy级别(虽然它可能有一些视图类封装了它,但我并不完全确定).你没有告诉你的用例,所以我只能猜测.但是……你正在处理大量数据,移动它是Bad Idea(TM).