我的问题与如何为Tensorflow Dataset
选择最佳(甚至合理)参数以优化GPU性能有关。
我去年建立了一个培训渠道,现在正在重新审查,以查看是否可以改进。这是我目前已编码的数据集:
dataset = tf.data.TFRecordDataset(self.filenames, "ZLIB", 384 * 1024 * 1024, num_parallel_reads=12)
dataset = dataset.map(parse_func, 20)
dataset = dataset.batch(8192) ## TODO
dataset = dataset.prefetch(2)
dataset = dataset.apply(tf.data.experimental.prefetch_to_device("/gpu:0", 1))
作为背景,我正在读取一个protobuf文件,它们看起来像这样:
features {
feature {
key: "DAT"
value {
float_list {
value: 1.0
value: -7.0
value: 0.0
value: -7.0
value: 0.0
value: -7.0
value: 0.0
value: -7.0
value: 0.0
value: -7.0
value: 0.0
value: -7.0
value: 0.0
value: -7.0
value: -1.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: -1.0
value: -5.0
value: 0.0
value: -5.0
value: 0.0
value: -5.0
value: 0.0
value: -5.0
value: 0.0
value: -5.0
value: 0.5
value: -5.5
value: 0.5
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: -1.0
value: -5.0
value: 0.0
value: -5.0
value: 1.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: -1.0
value: -5.0
value: 0.0
value: -5.0
value: 0.0
value: -5.0
value: 0.0
value: -5.0
value: 0.0
value: -5.0
value: 0.0
value: -5.0
value: -1.0
value: -4.0
value: 1.0
value: -5.0
value: 0.0
value: -5.0
value: 0.0
value: -5.0
value: 0.0
value: -5.0
value: 0.0
value: -5.0
value: 1.0
value: -6.0
value: 0.0
value: -6.0
value: 0.0
value: -6.0
value: -1.0
value: -5.0
value: -1.0
value: -4.0
value: 0.0
value: -4.0
value: 0.0
value: -4.0
value: 0.0
value: -4.0
value: -1.0
value: -3.0
value: 1.0
value: -4.0
value: 0.0
value: -4.0
value: 0.0
value: -4.0
value: 0.0
value: -4.0
value: 0.0
value: -4.0
value: 0.0
value: -4.0
value: 0.0
value: -4.0
value: 0.0
value: -4.0
value: 0.0
value: -4.0
value: 1.0
value: -5.0
value: 0.0
value: -5.0
value: -1.0
value: -4.0
value: 0.0
value: -4.0
value: -1.0
value: -3.0
value: -2.0
value: -1.0
value: 0.0
value: -1.0
value: 1.0
value: -2.0
value: 0.0
value: -2.0
value: -2.0
value: 0.0
value: 0.0
value: 0.0
value: 0.0
value: 0.0
value: 0.0
value: -2.5
value: -0.5
value: 0.0
value: 0.0
value: 0.000187634868780151
}
}
}
此外,我像这样从protobuf解析example
:
def get_parse_func(self):
def _parse_function(example_proto):
keys_to_features = {
"DAT": tf.FixedLenFeature(self._shapeX, tf.float32)
}
ex = ex = tf.parse_single_example(example_proto, keys_to_features)
X = tf.reshape(ex["DAT"][1:257], (128, 2))
##X = ex["DAT"][1:257]
Y_bd = ex["DAT"][259]
retBd = 5
Y_bd = tf.clip_by_value(Y_bd, -retBd, retBd)
Y_bd = tf.math.scalar_mul(1e4/retBd, Y_bd)
Y_full = ex["DAT"][257:260]
W = ex["DAT"][0]
return X, Y_full, Y_bd, W
return _parse_function
因此,这些文件一次仅包含一个示例/数据点,而在过去,我甚至在保存的文件中预先添加了批处理,以避免进行批处理的开销。但是,这样做有很多弊端,因此,我试图避免这种情况。附带说明一下,当我进行批量培训时,我的GPU利用率在训练时约为95%(尽管由于CPU / GPU io问题我经常将其利用率降至0%,但我也想解决这个问题,但这不是这个问题的重点) 。
我一直在尝试使用各种dataset
预处理功能的参数,例如map
,batch
,prefetch
和prefetch_to_device
,但这感觉就像ving牛刮胡子。看起来,无论我尝试使用哪种参数组合,即使我将参数改变了整个数量级,最终GPU利用率仍在30%到40%之间。令人惊讶的是,考虑到我正在改变输入参数的程度,性能几乎没有变化。通常,我尝试从除batch
的参数以外的每个小参数(例如等于1)开始,我将其设为8192或8192 * 2。的8192)。
但是,我意识到我什至没有知道保留这些参数的数量级的原则基础。 以下每个问题的具体问题:
tf.data.TFRecordDataset
的最佳num_parallel_reads
参数是什么?我注意到如果我将它设置得太高(例如100),一切都会崩溃。但是太低会导致性能下降。这应该等于我计算机上的num核心吗?其他一些与操作系统相关的线程数?dataset.map
,num_parallel_calls
同样与我设备上的cpus数有关吗?有什么好的经验法则?上面的项目符号点还应该与我的num_parallel_reads
参数有关系吗?dataset.prefetch
和dataset.apply
,我不认为它们与num个线程有关(但也许我错了?),但我认为这与可用的RAM或可用的GPU有关记忆?我如何获得一个合理的数字开始实验?谢谢您的帮助和建议。