我正在尝试将大量numpy nd_arrays写入磁盘。
列表的长度约为500000个元素
每个元素都是一个int_size(〜2048,2)的nd_array。阵列具有不同的形状。
我(当前)使用的方法是
@staticmethod
def _write_with_yaml(path, obj):
with io.open(path, 'w+', encoding='utf8') as outfile:
yaml.dump(obj, outfile, default_flow_style=False, allow_unicode=True)
我也尝试了泡菜,它也给出了相同的问题:
在较小的列表(约3400长)上,这可以很好地完成,并且速度足够快(<30秒)。
在约6000个长列表中,此过程在约2分钟后结束。
列表变大时,该过程似乎什么也没做。 RAM或磁盘活动没有变化。
30分钟后,我不再等待。
在强制停止该过程后,文件突然变得很大(〜600MB)。 我不知道它是否写完了。
写这么大列表的正确方法是什么,知道他写是否成功,并且如果可能的话,知道写/读何时完成?
该进程似乎挂起时,如何调试正在发生的事情?
我不想在我的代码中手动破坏和组装列表,我希望序列化库能够为我做到这一点。
答案 0 :(得分:1)
我不能说这就是答案,但是也许是。
当我在需要快速循环的应用程序上工作时,我发现代码中的某些内容非常慢。它正在打开/关闭yaml文件。
它通过使用JSON解决。
除了作为您不经常打开的某种配置之外,请勿将YAML用于其他任何事情。
保存阵列的解决方案:
np.save(path,array) # path = path+name+'.npy'
如果您确实需要保存数组列表,建议您保存带有数组路径的列表(数组本身,将使用np.save保存在磁盘上)。将python对象保存在磁盘上并不是您真正想要的。您要使用np.save
保存numpy数组完整解决方案(保存示例):
for array_index in range(len(list_of_arrays)):
np.save(array_index+'.npy',list_of_arrays[array_index])
# path = array_index+'.npy'
完整的解决方案(加载示例):
list_of_array_paths = ['1.npy','2.npy']
list_of_arrays = []
for array_path in list_of_array_paths:
list_of_arrays.append(np.load(array_path))
更多建议:
Python不能真正处理大型数组。此外,如果您已在列表中加载了其中的几个。从速度和内存的角度出发,始终一次处理一个,两个阵列。其余的必须在磁盘上等待。因此,将对象作为路径而不是对象引用,并在需要时从磁盘加载它。
您还说过,您不想手动组装列表。
可能的解决方案,我不建议,但可能正是您要寻找的解决方案
>>> a = np.zeros(shape = [10,5,3])
>>> b = np.zeros(shape = [7,7,9])
>>> c = [a,b]
>>> np.save('data.npy',c)
>>> d = np.load('data.npy')
>>> d.shape
(2,)
>>> type(d)
<type 'numpy.ndarray'>
>>> d.shape
(2,)
>>> d[0].shape
(10, 5, 3)
>>>
我相信我不需要注释上述代码。但是,重新加载后,您将丢失列表,因为该列表将转换为numpy数组。
答案 1 :(得分:1)
对于代码
import numpy as np
import yaml
x = []
for i in range(0,50000):
x.append(np.random.rand(2048,2))
print("Arrays generated")
with open("t.yaml", 'w+', encoding='utf8') as outfile:
yaml.dump(x, outfile, default_flow_style=False, allow_unicode=True)
在使用Python 3.7和PyYAML 3.13的系统(MacOSX,i7、16 GiB RAM,SSD)上,完成时间为61分钟。在保存过程中,python进程占用了大约5 GB的内存,最终文件大小为2 GB。这也显示了文件格式的开销:由于数据大小为50k * 2048 * 2 * 8(在python中,float的大小通常为64位)= 1562 MB,意味着yaml差了1.3倍(并且序列化/反序列化也需要时间。
要回答您的问题:
编辑:如果您想要快速的东西,请使用泡菜。代码:
import numpy as np
import yaml
import pickle
x = []
for i in range(0,50000):
x.append(np.random.rand(2048,2))
print("Arrays generated")
pickle.dump( x, open( "t.yaml", "wb" ) )
在9秒内完成,并生成1.5GBytes的文件(无开销)。当然,在与yaml不同的情况下应该使用pickle格式...