我正在尝试将瓶颈值保存到新创建的hdf5文件中。
瓶颈值分批形成(120,10,10, 2048)
。
保存一个单独的批次占用超过16个演出,python似乎在那一批冻结。根据最近的调查结果(见更新,似乎hdf5占用大内存是可以的,但冻结部分似乎是一个小问题。
我只是试图保存第一个 2 批次用于测试目的而且只是 训练数据集(再次,这是一个测试运行),但我甚至无法通过第一批。它只是在第一批停止并且不循环到下一次迭代。如果我尝试检查hdf5,资源管理器将变得缓慢,Python将冻结。如果我试图杀死Python(即使没有检查hdf5文件),Python也无法正常关闭并强制重启。
以下是相关代码和数据:
总数据点约为90,000 ish,分批发布120个。
Bottleneck shape is (120,10,10,2048)
所以我试图保存的第一批是(120,10,10,2048)
以下是我尝试保存数据集的方法:
with h5py.File(hdf5_path, mode='w') as hdf5:
hdf5.create_dataset("train_bottle", train_shape, np.float32)
hdf5.create_dataset("train_labels", (len(train.filenames), params['bottle_labels']),np.uint8)
hdf5.create_dataset("validation_bottle", validation_shape, np.float32)
hdf5.create_dataset("validation_labels",
(len(valid.filenames),params['bottle_labels']),np.uint8)
#this first part above works fine
current_iteration = 0
print('created_datasets')
for x, y in train:
number_of_examples = len(train.filenames) # number of images
prediction = model.predict(x)
labels = y
print(prediction.shape) # (120,10,10,2048)
print(y.shape) # (120, 12)
print('start',current_iteration*params['batch_size']) # 0
print('end',(current_iteration+1) * params['batch_size']) # 120
hdf5["train_bottle"][current_iteration*params['batch_size']: (current_iteration+1) * params['batch_size'],...] = prediction
hdf5["train_labels"][current_iteration*params['batch_size']: (current_iteration+1) * params['batch_size'],...] = labels
current_iteration += 1
print(current_iteration)
if current_iteration == 3:
break
这是打印语句的输出:
(90827, 10, 10, 2048) # print(train_shape)
(6831, 10, 10, 2048) # print(validation_shape)
created_datasets
(120, 10, 10, 2048) # print(prediction.shape)
(120, 12) #label.shape
start 0 #start of batch
end 120 #end of batch
# Just stalls here instead of printing `print(current_iteration)`
它只是在这里暂停(20分钟+),并且hdf5文件的大小逐渐增大(现在大约20演出,在我强行杀死之前)。实际上我甚至不能用任务管理器强制杀死,我必须重新启动操作系统,在这种情况下实际杀死Python。
在玩了我的代码之后,似乎有一个奇怪的错误/行为。
相关部分在这里:
hdf5["train_bottle"][current_iteration*params['batch_size']: (current_iteration+1) * params['batch_size'],...] = prediction
hdf5["train_labels"][current_iteration*params['batch_size']: (current_iteration+1) * params['batch_size'],...] = labels
如果我运行其中任何一行,我的脚本将完成迭代,并按预期自动中断。因此,如果我运行 - 或者没有冻结。它发生得相当快 - 不到一分钟。
如果我跑第一行('train_bottle')
,我的记忆大约需要69-72个演出,即使它只有几个批次。如果我尝试更多批次,内存是相同的。所以我假设基于我正在分配数据集的大小参数确定train_bottle
存储,而不是实际填充时。
所以尽管有72场演出,它的运行速度相当快(一分钟)。
如果我运行第二行train_labels
,我的内存占用几兆字节。
迭代没有问题,并且执行了break语句。
然而,现在问题是,如果我尝试运行这两行(在我的情况下是必要的,因为我需要保存'train_bottle'和'train_labels'),我在第一次迭代时遇到冻结,即使在20分钟后,也不会继续第二次迭代。 Hdf5文件正在慢慢增长,但如果我尝试访问它,Windows资源管理器会慢慢变成蜗牛而我无法关闭Python - 我必须重新启动操作系统。
所以我不确定尝试运行这两行时的问题是什么 - 好像我运行内存饥饿train_data
行,如果工作完美并在一分钟内结束。
答案 0 :(得分:3)
将数据写入HDF5
如果您在没有指定chunkshape的情况下写入分块数据集,h5py将自动为您执行此操作。由于h5py不知道你如何编写或读取数据集中的数据,这往往会导致性能不佳。
您还使用1 MB的默认chunk-cache-size。如果您只写入块的一部分并且块不适合缓存(很可能是1MP chunk-cache-size),则整个块将在内存中读取,修改并写回磁盘。如果多次发生这种情况,您将看到远远超出HDD / SSD的连续IO速度的性能。
在下面的示例中,我假设您只读取或写入第一个维度。如果不是这个必须根据您的需要进行修改。
import numpy as np
import tables #register blosc
import h5py as h5
import h5py_cache as h5c
import time
batch_size=120
train_shape=(90827, 10, 10, 2048)
hdf5_path='Test.h5'
# 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*200) #200 MB cache size
dset_train_bottle = f.create_dataset("train_bottle", shape=train_shape,dtype=np.float32,chunks=(10, 10, 10, 2048),compression=32001,compression_opts=(0, 0, 0, 0, 9, 1, 1), shuffle=False)
prediction=np.array(np.arange(120*10*10*2048),np.float32).reshape(120,10,10,2048)
t1=time.time()
#Testing with 2GB of data
for i in range(20):
#prediction=np.array(np.arange(120*10*10*2048),np.float32).reshape(120,10,10,2048)
dset_train_bottle[i*batch_size:(i+1)*batch_size,:,:,:]=prediction
f.close()
print(time.time()-t1)
print("MB/s: " + str(2000/(time.time()-t1)))
修改强> 循环中的数据创建花费了大量时间,因此我在时间测量之前创建了数据。
这应该至少提供900 MB / s throuput(CPU限制)。使用实际数据和较低的压缩比,您应该可以轻松达到硬盘的顺序IO速度。
使用with语句打开HDF5文件如果多次错误地调用此块,也会导致性能下降。这将关闭并重新打开文件,删除块缓存。
为了确定正确的块大小,我还建议: https://stackoverflow.com/a/48405220/4045774 https://stackoverflow.com/a/44961222/4045774
答案 1 :(得分:2)
如果你有足够的DDR内存并且想要极快的数据加载和节省性能,请直接使用np.load()& np.save()。 https://stackoverflow.com/a/49046312/2018567 np.load()& np.save()可以为您提供最快的数据加载和保存性能,到目前为止,我无法找到任何其他工具或框架可以竞争它,即使HDF5的性能只是它的1/5~1 / 7。
答案 2 :(得分:0)
此答案更像是对@ max9111和@Clock ZHONG之间的参数的注释。我写这篇文章是为了帮助其他人想知道哪种更快的HDF5或np.save()。
我使用了@ max9111提供的代码,并按照@Clock ZHONG的建议进行了修改。准确的Jupyter笔记本可以在https://github.com/wornbb/save_speed_test上找到。
简而言之,根据我的规范:
HDF5达到1339.5 MB / s,而np.save仅924.9 MB / s(不压缩)。
此外,如@Clock ZHONG所述,他/她对lzf -Filter有问题。如果您还遇到此问题,可以在win 10上使用pip安装的软件包使用python3的conda分发运行发布的jupyter笔记本。