如何合并非常大的numpy阵列?

如何合并非常大的numpy阵列?,numpy,memory-management,Numpy,Memory Management,我将有许多存储在文件中,这些文件是使用函数保存的 我将信息分成许多数组,因为如果不是这样,我使用的函数会因为内存问题而崩溃。数据不是稀疏的 我需要将所有这些信息合并到一个唯一的数组中(能够用一些例程处理),并将其存储到磁盘中(用不同的参数多次处理) 阵列无法装入RAM+交换内存 如何将它们合并到一个唯一的阵列中并保存到磁盘? 我怀疑我应该使用,但我不知道具体如何使用。另外,如果我一开始不保留连续的磁盘空间,可能会出现一些性能问题 我读过这篇文章,但我仍然不知道怎么做 编辑 澄清:我制作了许多函

我将有许多存储在文件中,这些文件是使用函数保存的

我将信息分成许多数组,因为如果不是这样,我使用的函数会因为内存问题而崩溃。数据不是稀疏的

我需要将所有这些信息合并到一个唯一的数组中(能够用一些例程处理),并将其存储到磁盘中(用不同的参数多次处理)

阵列无法装入RAM+交换内存

如何将它们合并到一个唯一的阵列中并保存到磁盘?

我怀疑我应该使用,但我不知道具体如何使用。另外,如果我一开始不保留连续的磁盘空间,可能会出现一些性能问题

我读过这篇文章,但我仍然不知道怎么做


编辑

澄清:我制作了许多函数来处理类似的数据,其中一些函数需要数组作为参数。在某些情况下,通过使用切片,我只能传递这个大型阵列的一部分。但掌握所有信息仍然很重要。在这样的阵列中

这是因为:阵列包含按时间顺序排列的信息(来自物理模拟)。在函数的参数中,用户可以设置要处理的初始时间和最后时间。此外,他/她还可以设置处理区块的大小(这很重要,因为这会影响性能,但允许的区块大小取决于计算资源)。因此,我无法将数据存储为单独的数据块


这个特定阵列(我正在尝试创建的阵列)的构建方式在其工作时并不重要。

这是一个如何将90GB易于压缩的数据写入磁盘的示例。这里提到了最重要的几点

在普通硬盘上,写入/读取速度应在(300 MB/s、500 MB/s)范围内

示例

import numpy as np
import tables #register blosc
import h5py as h5
import h5py_cache as h5c
import time

def read_the_arrays():
  #Easily compressable data
  #A lot smaller than your actual array, I do not have that much RAM
  return np.arange(10*int(15E3)).reshape(10,int(15E3))

def writing(hdf5_path):
  # As we are writing whole chunks here this isn't realy needed,
  # if you forget to set a large enough chunk-cache-size when not writing or reading 
  # whole chunks, the performance will be extremely bad. (chunks can only be read or written as a whole)
  f = h5c.File(hdf5_path, 'w',chunk_cache_mem_size=1024**2*1000) #1000 MB cache size
  dset = f.create_dataset("your_data", shape=(int(15E5),int(15E3)),dtype=np.float32,chunks=(10000,100),compression=32001,compression_opts=(0, 0, 0, 0, 9, 1, 1), shuffle=False)

  #Lets write to the dataset
  for i in range(0,int(15E5),10):
    dset[i:i+10,:]=read_the_arrays()

  f.close()

def reading(hdf5_path):
  f = h5c.File(hdf5_path, 'r',chunk_cache_mem_size=1024**2*1000) #1000 MB cache size
  dset = f["your_data"]

  #Read chunks
  for i in range(0,int(15E3),10):
    data=np.copy(dset[:,i:i+10])
  f.close()

hdf5_path='Test.h5'
t1=time.time()
writing(hdf5_path)
print(time.time()-t1)
t1=time.time()
reading(hdf5_path)
print(time.time()-t1)

您应该能够在
np.memap
数组中逐块加载:

import numpy as np

data_files = ['file1.npz', 'file2.npz2', ...]

# If you do not know the final size beforehand you need to
# go through the chunks once first to check their sizes
rows = 0
cols = None
dtype = None
for data_file in data_files:
    with np.load(data_file) as data:
        chunk = data['array']
        rows += chunk.shape[0]
        cols = chunk.shape[1]
        dtype = chunk.dtype

# Once the size is know create memmap and write chunks
merged = np.memmap('merged.buffer', dtype=dtype, mode='w+', shape=(rows, cols))
idx = 0
for data_file in data_files:
    with np.load(data_file) as data:
        chunk = data['array']
        merged[idx:idx + len(chunk)] = chunk
        idx += len(chunk)

但是,正如注释中所指出的,跨一个不是最快的维度工作会非常慢。

您无法映射压缩数组。我认为当前的
np.load
实现忽略了
mmap_模式
,如果您尝试的话。谢谢您提供的信息。您必须将它们合并到一个数组中,还是可以一块一块地加载它们,一块一块地处理它们,然后一块一块地写出它们?@user1420303:我明白了。您仍然可以通过查看时间范围、找到相应的块并加载这些块,以及在必要时切片第一个和最后一个块来使用分块数据。这更符合逻辑,但它可以防止内存不足。您甚至可以将其抽象为某种流式集合类,允许透明数组索引和隐藏该逻辑。@user1420303:我不知道该功能。这似乎是合理的,是的。不过,我不完全确定怎么做。谢谢你的回答。我给了我一些想法。我不知道代码是如何加载多个预先存在的npz文件的。@user1420303 With
data.iteritems
可以遍历文件中的数组,而
sorted(data.keys())
可以遍历数组中的名称(我假设它们应该按字母顺序排序,但可能是其他名称)。对。据我所知,代码读取插入多个数组的“一”npz文件,并合并它们。我需要读取“多个”npz文件,每个文件包含一个数组,然后合并它们。@user1420303啊,我明白了,好吧,我没有正确理解。我现在改了,谢谢。写速度还可以。我需要考虑一下代码。我不熟悉hdf5。问:您可以这样做:“dset=f.create_dataset”,然后多次“dset[i:i+10,:]=读取_数组()。整个数组永远不在RAM中,对吗?是的,read_The_arrays()函数应该简单地模拟从npz文件中读取的过程。所以最大RAM使用量应该是一个输入阵列的大小+块大小,我已经设置为1000MB。这也可以降低,但是如果缓存太少,性能会急剧下降。很好,这使我很容易解决另一个问题(一些时间值在数组中重复,也就是说,有一点重叠)。您认为最终的.h5文件可以简单地转换为.npz吗?如果在一个块中出现重复值,压缩算法会很好地处理它。从一个HDF5文件到一个压缩的numpy文件的转换是可能的,但不是那么直接。(将某些内容分块写入zip文件)。