保存到hdf5非常慢(Python冻结)
我正在尝试将瓶颈值保存到新创建的hdf5文件中。 瓶颈值以批的形式出现保存到hdf5非常慢(Python冻结),python,numpy,keras,hdf5,Python,Numpy,Keras,Hdf5,我正在尝试将瓶颈值保存到新创建的hdf5文件中。 瓶颈值以批的形式出现(120,10,102048)。 保存一个单独的批处理占用了超过16个Gig,python在这一批处理上似乎已经冻结了。根据最近的发现(见更新),hdf5占用大内存似乎没有问题,但冻结部分似乎是一个小故障 我只想保存第一批2批用于测试目的,并且只保存 训练数据集(再一次,这是一个测试运行),但我甚至无法通过第一批。它只是在第一批暂停,不会循环到下一个迭代。如果我尝试检查hdf5,资源管理器将变慢,Python将冻结。如果我尝试
(120,10,102048)
。
保存一个单独的批处理占用了超过16个Gig,python在这一批处理上似乎已经冻结了。根据最近的发现(见更新),hdf5占用大内存似乎没有问题,但冻结部分似乎是一个小故障
我只想保存第一批2批用于测试目的,并且只保存
训练数据集(再一次,这是一个测试运行),但我甚至无法通过第一批。它只是在第一批暂停,不会循环到下一个迭代。如果我尝试检查hdf5,资源管理器将变慢,Python将冻结。如果我尝试杀死Python(即使不检查hdf5文件),Python无法正常关闭,并强制重新启动
以下是相关代码和数据:
总数据点约为90000 ish,分120批发布
Bottleneck shape is (120,10,10,2048)
所以我要保存的第一批是(120,10,102048)
以下是我如何尝试保存数据集:
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 Gig,在我强制杀戮之前)。实际上我甚至不能用task manager强制杀戮,我必须重新启动操作系统,在这种情况下要真正杀掉Python
更新
在使用我的代码一段时间后,似乎出现了一个奇怪的bug/行为
有关部分如下:
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_-balk')
,我的内存将占用大约69-72 Gig,即使只是几个批次。如果我尝试更多批次,内存是相同的。因此我假设train_-balk
根据我分配数据集的大小参数决定存储,而不是在数据集填满时。
因此,尽管有72场演出,它运行得相当快(一分钟)
如果我运行第二行,train\u labels
,我的内存会占用几兆字节。
迭代没有问题,执行break语句
但是,如果我尝试运行这两条线路,问题就出现了(在我的情况下,这是必要的,因为我需要保存“train\u瓶子”和“train\u标签”),我在第一次迭代时遇到了冻结,即使在20分钟后,它也不会继续到第二次迭代。Hdf5文件正在缓慢增长,但如果我尝试访问它,Windows资源管理器会慢到一个蜗牛,我无法关闭Python--我必须重新启动操作系统
因此,我不确定尝试运行这两行时会出现什么问题——就像我运行内存不足的
train\u data
行一样,if工作正常并在一分钟内结束。将数据写入HDF5
如果在未指定chunkshape的情况下写入分块数据集,h5py将自动为您执行此操作。由于h5py不知道如何从数据集中写入或读取数据,因此这通常会导致性能下降
您还使用默认的区块缓存大小1 MB。如果您只写入区块的一部分,而区块不适合缓存(很可能是1MP区块缓存大小),整个数据块将在内存中读取、修改并写回磁盘。如果这种情况发生多次,您将看到远远超过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的吞吐量(CPU有限)。使用真实数据和较低的压缩比,您应该可以轻松达到硬盘的顺序IO速度
如果多次调用此块出错,则使用with语句打开HDF5文件也可能导致性能下降。这将关闭并重新打开文件,删除区块缓存
为了确定正确的块大小,我还建议:
将数据写入HDF5 如果在未指定chunkshape的情况下写入分块数据集,h5py将自动为您执行此操作。由于h5py不知道如何从数据集中写入或读取数据,因此这通常会导致性能下降 您还使用默认的区块缓存大小1 MB。如果您只写入区块的一部分,而区块不适合缓存(很可能是1MP区块缓存大小),整个数据块将在内存中读取、修改并写回磁盘。如果这种情况发生多次,您将看到远远超过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的吞吐量(CPU有限)。使用真实数据和较低的压缩比,您应该可以轻松达到硬盘的顺序IO速度
如果多次调用此块出错,则使用with语句打开HDF5文件也可能导致性能下降。这将关闭并重新打开文件,删除区块缓存
为了确定正确的块大小,我还建议:
如果您有足够的DDR内存,并且想要极快的数据加载和保存性能,请直接使用np.load()和np.save()。 np.load()和np.save()可以提供最快的数据加载和保存性能,