我正在处理大型数据集(起始为75GB->最终结果为两个100GB文件),并将数据分块为大约5000个单独的Numpy .npy文件。我试图遍历每个文件,进行一些处理和填充,然后存储到两个容器之一中。还有其他一些元数据数组,但是可以单独运行它们。但是,它们应该/需要能够与大数据处理保持一致。
我在脚本开头创建了两个内存映射文件
f1 = np.memmap('f1.dat', dtype='float32', mode='w+', shape=(2600, 5000, 2000))
f2 = np.memmap('f2.dat', dtype='float32', mode='w+', shape=(2500, 5000, 2000))
# f1 and f2 store different sets, depending on a flag
我在processData()中启用了数据处理功能,以返回元数据和大型数据数组。然后,将其添加或设置给定数组。这些都是在枚举的for循环中完成的。
for i, object in enumerate(object_list)
meta1, meta2, data = processData(i, object)
list_meta1.append(meta1)
array_meta2[i] = meta2
if flag_1:
f1[j] = data; j+=1
elif flag_2:
f2[k] = data; k+=1
我已经尝试过将数据处理作为一种功能(我使用生成器进行了阅读,但可能会有点错了,哈哈),并使用了for循环。
我遇到的问题是,当我使用bash shell中的top监视python进程时,python进程正常加载。它将VIRT内存下的两个大数据文件“加载”到0.199t,并且在开始加载数据文件之前,在RES / SHR下大约需要一两个GB的空间。
但是,一旦开始如下所述实际开始处理数据:
data = np.load(object + ".npy")
meta1 = fetchMeta(1, object)
meta2 = fetchMeta(2, object)
if len(data) != whatItShouldBe[i]:
sys.exit("You goof'd somewhere")
else:
if len(data) < padding_limit:
data = np.concatenate([np.array(data), np.zeros((padding_limit - len(data), 2000))], axis=0)
return meta1, meta2, data
RES内存量快速增长,在文件400左右时达到10GB左右,并且在某个时候将达到系统64GB的48GB。在整个处理过程中,直到达到48GB为止,Python处理过程中都有很多要点D(我知道这是不可中断的睡眠)。我以为这是让memmap将自身写入磁盘。
但是,手动刷新阵列不会释放任何内存或根本无法加快运行速度(如果有的话,它会在刷新刷新间隔约1分钟的时间内减慢速度)。
从本质上讲,我知道整个批处理过程很可能会及时完成,因为它会跳过前一百或两百个文件,将它们保存起来并继续进行运输。但是,存在一个“潜在”内存问题,似乎使事情陷入了困境。在我看来,没有理由让内存使用率在高使用率时保持保持状态(显然,两次写入磁盘之间的时间间隔会很高),但是在我看来,单个数据块由于某种原因(在将它们复制到正确的内存映射之后)被保留在内存中。
结尾说明:使用标准数组时,此代码的常规结构可以正常工作,但这是在非常小的数据集上进行的。为了清楚起见,我对代码进行了更多的匿名处理,但是可以在此处找到完整的实现:https://pastebin.com/nNZDxL0k