我想知道在为可变大小的输入(相对于固定大小的输入)创建TensorFlow占位符时是否存在任何实质性缺点(例如,关于计算效率,内存......)?
比如说,我正在进行小批量学习,并使用占位符初始化图形,我假设一个固定的batch_size:
tf.placeholder(..., shape=[batch_size, ...])
或者,我可以初始化占位符变量,以便它接受可变大小的输入:
tf.placeholder(..., shape=[None, ...])
我并不熟悉底层的低级张量流实现,但后者不会在每次迭代时检查维度,分配内存和创建新数组,以解释我的小批量大小在培训期间发生变化的情况吗?那么,根据实施情况,如果我使用固定的批量维度,那么计算上的浪费是不是很大?
1 回答
提供完全定义的形状(可以产生更好的性能)和允许尺寸变化(这使得数据流图更容易重复使用)之间存在明确的张力 . 正如您所怀疑的那样,使用变形tf.placeholder() ops来表示TensorFlow模型中的输入有一些缺点:
TensorFlow通常能够在完全了解形状时简化数据流图 . 例如,对tf.shape(x)的调用返回
tf.Tensor
,其中包含张量x
的真实动态形状 . 如果在图形构造时完全定义了该形状,TensorFlow将使用tf.constant()替换形状计算,这将用于常量折叠优化,以减少运行时完成的工作量 .作为极端情况,XLA compiler要求在生成代码之前完全定义所有输入张量形状,以便它可以生成更高效的内核代码,其中数组边界(等)是编译时常量 . XLA为每种输入形状组合重新编译内核代码,因此使用固定大小的张量将避免重新编译开销 .
TensorFlow的内存分配器当前为每个调用
tf.Session.run()
的每个中间和输出张量分配新数组 . 但是,如果它们具有静态分配的分配请求(因为可以从最近释放的缓冲区满足请求),底层内存分配器(GPU内存的BFC分配器和CPU内存的tcmalloc
或jemalloc
)往往表现更好 .