为什么 TensorFlow 2 比 TensorFlow 1 慢很多?
许多用户将其作为切换到 Pytorch 的原因,但我还没有找到一个理由/解释来牺牲最重要的实用质量和速度,以实现急切的执行。
下面是代码基准测试性能,TF1 与 TF2 - TF1 的运行 速度提高了 47% 到 276% 。
我的问题是: 在图形或硬件级别上,是什么导致了如此显着的减速?
寻找详细的答案 - 我已经熟悉广泛的概念。相关的
Git
规格 :CUDA 10.0.130、cuDNN 7.4.2、Python 3.7.4、Windows 10、GTX 1070
基准测试结果 :
更新 :根据以下代码禁用 Eager Execution 无济于事 。然而,这种行为是不一致的:有时在图形模式下运行有很大帮助,有时它相对于
Eager运行 速度较慢。
基准代码 :
# use tensorflow.keras... to benchmark tf.keras; used GPU for all above benchmarks
from keras.layers import Input, Dense, LSTM, Bidirectional, Conv1D
from keras.layers import Flatten, Dropout
from keras.models import Model
from keras.optimizers import Adam
import keras.backend as K
import numpy as np
from time import time
batch_shape = (32, 400, 16)
X, y = make_data(batch_shape)
model_small = make_small_model(batch_shape)
model_small.train_on_batch(X, y) # skip first iteration which builds graph
timeit(model_small.train_on_batch, 200, X, y)
K.clear_session() # in my testing, kernel was restarted instead
model_medium = make_medium_model(batch_shape)
model_medium.train_on_batch(X, y) # skip first iteration which builds graph
timeit(model_medium.train_on_batch, 10, X, y)
使用的功能 :
def timeit(func, iterations, *args):
t0 = time()
for _ in range(iterations):
func(*args)
print("Time/iter: %.4f sec" % ((time() - t0) / iterations))
def make_small_model(batch_shape):
ipt = Input(batch_shape=batch_shape)
x = Conv1D(128, 400, strides=4, padding='same')(ipt)
x = Flatten()(x)
x = Dropout(0.5)(x)
x = Dense(64, activation='relu')(x)
out = Dense(1, activation='sigmoid')(x)
model = Model(ipt, out)
model.compile(Adam(lr=1e-4), 'binary_crossentropy')
return model
def make_medium_model(batch_shape):
ipt = Input(batch_shape=batch_shape)
x = Bidirectional(LSTM(512, activation='relu', return_sequences=True))(ipt)
x = LSTM(512, activation='relu', return_sequences=True)(x)
x = Conv1D(128, 400, strides=4, padding='same')(x)
x = Flatten()(x)
x = Dense(256, activation='relu')(x)
x = Dropout(0.5)(x)
x = Dense(128, activation='relu')(x)
x = Dense(64, activation='relu')(x)
out = Dense(1, activation='sigmoid')(x)
model = Model(ipt, out)
model.compile(Adam(lr=1e-4), 'binary_crossentropy')
return model
def make_data(batch_shape):
return np.random.randn(*batch_shape), np.random.randint(0, 2, (batch_shape[0], 1))
-
2020年 8
月 17 日30 日更新:TF 2.3 终于做到了:所有案例的运行速度都比任何以前的版本都快,或者明显快。此外,我之前的更新对 TF 不公平;我的 GPU
是罪魁祸首,最近一直过热。如果您看到迭代时间的上升茎图,这是一个可靠的症状。最后,请参阅开发人员关于Eager vs
Graph的说明。这可能是我对这个答案的最后一次更新。 您的 模型速度的真实统计数据只能由您在您的设备上找到。
2020 年 5 月 19 日更新 :TF 2.2,使用相同的测试:Eager 速度仅略有改进。下面绘制 Large-Large
Numpytrain_on_batch
情况,x 轴是连续拟合迭代;我的 GPU
没有接近其全部容量,所以怀疑它是否在节流,但随着时间的推移迭代确实会变慢。如上所述,Graph 和 Eager 分别比 TF1 慢 1.56 倍 和 1.97倍。 不确定我是否会进一步调试,因为我正在考虑切换到
Pytorch,因为 TensorFlow
对自定义/低级功能的支持不佳。但是,我确实打开了一个问题以获取开发人员的反馈。
2020 年 2 月 18 日更新 :我每晚都替补 2.1 和 2.1;结果好坏参半。除了一个配置(模型和数据大小)之外的所有配置都与 TF2 和
TF1 的最佳配置一样快或快得多。较慢且显着减慢的是Large-Large - 尤其是。在图形执行中( 慢 1.6 倍到 2.5 倍 )。此外,对于我测试的一个大型模型,Graph 和 Eager 之间存在 极大
的可重复性差异——无法通过随机性/计算并行性来解释。我目前无法根据时间限制为这些声明提供可重现的代码,因此我强烈建议您对自己的模型进行测试。尚未就这些问题打开 Git
问题,但我确实对原始问题发表了评论-
还没有回复。一旦取得进展,我会更新答案。
VERDICT :它 不是 ,如果你知道你在做什么。但是,如果您 不这样做 ,则可能会花费您很多钱-平均要花费一些 GPU
升级,而最坏的情况是要花费多个 GPU。
此答案 :旨在提供问题的高级描述,以及如何根据您的需求决定培训配置的指南。有关详细的低级描述,包括所有基准测试结果 +
使用的代码,请参阅我的其他答案。如果我学到任何信息,我将更新我的答案和更多信息 - 可以收藏/“星标”这个问题以供参考。
问题摘要 :正如TensorFlow 开发人员 Q. Scott Zhu
所证实的那样,TF2
的开发重点是 Eager 执行和与 Keras 的紧密集成,这涉及到 TF
源代码的彻底变化——包括图形级别的变化。好处:大大扩展了处理、分发、调试和部署能力。然而,其中一些成本是速度。然而,这件事要复杂得多。不仅仅是 TF1 与 TF2 - 导致列车速度显着差异的因素包括:
- TF2 与 TF1
- Eager vs. Graph 模式
keras
对比tf.keras
numpy
对比tf.data.Dataset
对比……train_on_batch()
对比fit()
- GPU 与 CPU
model(x)
对比model.predict(x)
对比……
不幸的是,上面几乎没有一个是相互独立的,并且每个都至少可以使执行时间相对于另一个增加一倍。幸运的是,您可以通过一些捷径来系统地确定最有效的方法 -
正如我将展示的那样。
我应该怎么办? 目前,唯一的方法是 - 试验您的特定模型、数据和硬件。没有单一的配置总是最有效 - 但是有 一些可以
做和不应该做的事情来简化您的搜索:> > 做:
train_on_batch()
+numpy
+tf.keras
+ TF1 + 渴望/图表train_on_batch()
+numpy
+tf.keras
+ TF2 + 图表fit()
+numpy
+tf.keras
+ TF1/TF2 + 图表 + 大模型和数据
> > 不要:
-
fit()
+numpy
+keras
适用于中小型模型和数据 -
fit()
+numpy
+tf.keras
+ TF1/TF2 + 渴望 -
train_on_batch()
+numpy
+keras
+ TF1 + 渴望 -
[专业]
tf.python.keras
; 它的运行速度可以慢 10-100 倍,并且有很多错误;- 这包括
layers
,models
,optimizers
, & 相关的“开箱即用”使用导入;ops、utils 和相关的“私有”导入很好 - 但可以肯定的是,检查 alt 以及它们是否用于tf.keras
- 这包括
有关示例基准测试设置,请参阅我的其他答案底部的代码。上面的列表主要基于另一个答案中的“基准”表。
*上述做与不做的 *限制:
- 这个问题的标题是“为什么 TF2 比 TF1 慢很多?”,虽然它的主体明确涉及训练,但问题不仅限于此; 即使 在相同的 TF 版本、导入、数据格式等内, 推理 也受到主要速度差异的影响 -
- RNN 可能会显着改变另一个答案中的数据网格,因为它们在 TF2 中得到了改进
- 主要使用
Conv1D
的模型Dense
- 没有 RNN、稀疏数据/目标、4/5D 输入和其他配置 - 输入数据仅限于
numpy
andtf.data.Dataset
,而存在许多其他格式;看其他答案 - 使用了 GPU;结果在 CPU 上 会 有所不同。事实上,当我问这个问题时,我的 CUDA 没有正确配置,并且一些结果是基于 CPU 的。
为什么 TF2 牺牲了最实用的质量和速度,换取了急切的执行力? 它没有,很明显 - 图表仍然可用。但如果问题是“为什么急于求成”:
- 出色的调试 :您可能会遇到很多问题,询问“我如何获得中间层输出”或“我如何检查权重”;急切,它(几乎)像
.__dict__
. 相比之下,Graph 需要熟悉特殊的后端功能 - 使调试和自省的整个过程大大复杂化。 - 更快的原型设计 :根据与上述类似的想法;更快的理解 = 更多的时间留给实际的 DL。
如何启用/禁用 EAGER?
tf.enable_eager_execution() # TF1; must be done before any model/tensor creation tf.compat.v1.disable_eager_execution() # TF2; above holds
TF2中的误导
;看这里。
附加信息 :
- 小心
_on_batch()
TF2 中的方法;根据 TF 开发人员的说法,他们仍然使用较慢的实现,但 不是故意 的 - 即它需要修复。有关详细信息,请参阅其他答案。
对 TensorFlow 开发人员的要求 :
请修复, 以及 迭代train_on_batch()
调用的性能方面;fit()
自定义火车循环对许多人来说很重要,尤其是对我而言。添加文档/文档字符串提及这些性能差异以供用户了解。提高一般执行速度,以防止窥视者跳到 Pytorch。
致谢 :感谢
更新 :
-
19 年 11 月 14 日- 找到了一个模型(在我的实际应用程序中),它在 TF2 上运行速度较慢, _适用于所有配置_ w/Numpy 输入数据。差异范围为 13-19%,平均为 17%。然而,
keras
和之间的差异更为显着: 18-40% ,平均。32%(TF1 和 2)。( - 除了 Eager,TF2 OOM’d 除外)tf.keras
**** -
2019 年 11 月 17 日- 开发人员在最近的一次提交
on_batch()
中更新了方法,声称提高了速度 - 将在 TF 2.1 中发布,或者现在以. 由于我无法让后者运行,因此将把 benching 延迟到 2.1。tf-nightly
-
2/20/20 - 预测性能也值得一试;例如,在 TF2 中,CPU 预测时间可能涉及周期性尖峰
-
为什么TensorFlow 2比TensorFlow 1慢得多?
2021-01-29 关注 0 浏览223 1答案
-
为什么Python 3比Python 2慢很多?[重复]
2021-01-29 关注 0 浏览78 1答案
-
GPU上的Tensorflow Matmul计算比CPU慢
2021-01-29 关注 0 浏览72 1答案
-
TensorFlow,为什么选择python语言?
2021-01-29 关注 0 浏览65 1答案
-
TensorFlow:如何以及为什么使用SavedModel
2021-01-29 关注 0 浏览135 1答案
-
为什么我们在Tensorflow中命名变量?
2021-01-29 关注 0 浏览99 1答案
-
为什么增加批次大小时TensorFlow示例失败?
2021-01-29 关注 0 浏览110 1答案
-
为什么True比1慢?
2021-01-29 关注 0 浏览107 1答案
-
为什么`tf.constant()`的值在TensorFlow的内存中多次存储?
2021-01-29 关注 0 浏览89 1答案
-
Tensorflow 2.0 - AttributeError:模块'tensorflow'没有属性'Session'
2022-07-28 关注 0 浏览25 1答案