Python 使用Tensorflow数据集API读取TFRecords文件时,预处理输入数据会减慢输入管道的速度
我使用Tensorflow数据集API读取TFRecords文件,但GPU的使用率仍然很低(10%)。我认为原因是我在将数据送入Python 使用Tensorflow数据集API读取TFRecords文件时,预处理输入数据会减慢输入管道的速度,python,performance,tensorflow,tensorflow-gpu,tfrecord,Python,Performance,Tensorflow,Tensorflow Gpu,Tfrecord,我使用Tensorflow数据集API读取TFRecords文件,但GPU的使用率仍然很低(10%)。我认为原因是我在将数据送入sess.run()之前对其进行了预处理。下面是我的代码。 1.从3个单独的文件创建数据集 tf.reset_default_graph() # The content of TFRecords files is that each row is an array. Calculate total rows. n_total_row = sum(1 for _ in
sess.run()
之前对其进行了预处理。下面是我的代码。1.从3个单独的文件创建数据集
tf.reset_default_graph()
# The content of TFRecords files is that each row is an array. Calculate total rows.
n_total_row = sum(1 for _ in tf.python_io.tf_record_iterator(epd))
def get_epd_dataset(filename):
dataset = tf.data.TFRecordDataset(filename)
def _parse_function(example_proto):
keys_to_features = {'data':tf.VarLenFeature(tf.int64)}
parsed_features = tf.parse_single_example(example_proto, keys_to_features)
return tf.sparse_tensor_to_dense(parsed_features['data'])
# Parse the record into tensors.
dataset = dataset.map(_parse_function)
return dataset
# There are 3 essential files comprising input data. It reads 3 seperate
# files "epd", "y_id", "x_feat" into 3 separate dataset respectively, and
# uses `Dataset.zip()` to combine these 3 separate files into 1 dataset.
epd_ds = get_epd_dataset(epd)
n_lexicon, id_ds = get_id_dataset(y_id)
feat_ds = get_feat_dataset(x_feat)
data_ds = tf.data.Dataset.zip((feat_ds, epd_ds, id_ds))
# Shuffle the dataset
data_ds = data_ds.shuffle(buffer_size=n_total_row, reshuffle_each_iteration=True)
# Repeat the input indefinitly
data_ds = data_ds.repeat(epoch)
# Generate batches
data_ds = data_ds.batch(1)
# Create a one-shot iterator
iterator = data_ds.make_one_shot_iterator()
data_iter = iterator.get_next()
二,。建立一个Tensorflow图
n_input = DIM*(LEFT+1+RIGHT)
n_classes = n_lexicon
mlp = MultiLayerPerceptron.MultiLayerPerceptron(DIM*(LEFT+1+RIGHT), n_lexicon)
# tf Graph input
X = tf.placeholder("float", [None, n_input])
Y = tf.placeholder("float", [None, n_classes])
logits = mlp.multilayer_perceptron(X, dropout_mode)
loss_op = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=Y), name='loss_op')
optimizer = tf.train.AdamOptimizer(learning_rate=lr)
train_op = optimizer.minimize(loss_op, name='train_op')
三,。从data\u iter
生成数据并运行TF会话
sess = tf.Session()
# Initialization
sess.run(tf.global_variables_initializer())
for e in range(1, epoch+1):
while True:
try:
# Get data from dataset iterator
tmp = sess.run([data_iter])[0]
# a,b,c are a row from 3 serapate files.
a = tmp[0].flatten()
b = tmp[1].flatten()
c = tmp[2].flatten()
# I believe this step slows down my input pipeline.
x_train, y_train = _data_generate(mlp, b, d, c)
_, c = sess.run([train_op, loss_op], feed_dict={X: x_train,
Y: y_train})
except tf.errors.OutOfRangeError:
break
sess.close()
我的代码达到了GPU使用量的10~15%。我认为原因是\u data\u generate()
在处理numpy数组上花费了太多时间。
但我不知道如何改进我的管道。以下是我的问题
sess.run()
。我没有选择后一种解决方案,因为我提到了这一点\u data\u generate()
放入\u parse\u function()
可以解决这个问题,bucause Tensorflow处理的是数据部分的预处理,而不是python。但是我不知道怎么做,因为\u data\u generate()
需要从3个单独的文件中提取3行。有人知道怎么做吗谢谢。您能分享
\u data\u generate
功能的代码吗?
我看不出它有什么作用
正如您所指出的,性能可能会因为RAM GPU而损失
内存交换和tensorflow操作与Python操作的混合
与其通过sess.run()
自己运行迭代器data\u iter
,执行numpy操作,然后执行训练步骤,不如将data\u iter
作为输入传递到神经网络图中-它应该替换占位符。
(只需制作一个函数,使用data\u iter
作为参数来构造图形)
我认为将_data _generate()放入_parse _function()可以解决这个问题
他的问题是,bucause Tensorflow处理预处理数据部分,但不处理>python。但是我不知道怎么做,因为_data_generate()需要3个不同文件中的3>行。有人知道怎么做吗
正确的方法是从文件中创建3个数据集,对它们进行解码、压缩,然后将迭代器作为处理图的输入传递给压缩后的数据集。你几乎要这么做了
还有,;
只要可能/需要,就尝试执行多线程。
在这里:
你应使用:
dataset.map(_parse_function, num_threads=<MORE THAN ONE>)
dataset.map(\u parse\u函数,num\u threads=)
其中,
是大于1的整数。
在您的情况下,我将从8个线程开始(看看GPU是否为100%)
检查dis并告诉我它是否正常我假设您的示例使用了您模型的简化版本,否则GPU几乎总是在下一批准备就绪之前终止其工作 每个数据集和transofrmation管道都有自己的特殊性,很难提供明确的答案,但这里可能有一些值得研究的问题:
- 您不应该明确地计算数据的值,也不应该再使用占位符和提要。.make_one_shot_iterator().get_next()返回的值已经是模型的输入节点,而不是占位符变量。这将把输入管道与模型粘在一起,避免在tensorflow CPU、python和tensorflow GPU内存区域之间来回发送数据。在您的session.run()调用中,您不需要指定任何输入值,模型将根据需要自动在数据集上输入自己
- 我不认为TFRecord文件在随机访问时应该很快,因为元素大小未知。在您的案例中,您似乎还使用了三次随机访问:epd、feats和元数据
- 你有没有指示tensorflow在什么地方使用?否则,tensorflow可能会在加载和处理下一批之前等待处理当前批次
- 您可能需要检查map函数的多个工作进程是否正在等待某些资源(磁盘IO、CPU时间、锁定对象?)
- data API很难调试,而且不太实用(说真的,它怎么可能不知道关于张量的任何信息?),您可能想看看tensorpack库或旧的tensorflow队列数据加载API
dataset.map(_parse_function, num_threads=<MORE THAN ONE>)