许多用户将其作为切换到 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 没有接近其全部容量,所以怀疑它是否在节流,但随着时间的推移迭代确实会变慢。
train_on_batch
如上所述,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 - 导致列车速度显着差异的因素包括:
keras
tf.keras
numpy
tf.data.Dataset
train_on_batch()
fit()
model(x)
model.predict(x)
不幸的是,上面几乎没有一个是相互独立的,并且每个都至少可以使执行时间相对于另一个增加一倍。幸运的是,您可以通过一些捷径来系统地确定最有效的方法 - 正如我将展示的那样。
我应该怎么办? 目前,唯一的方法是 - 试验您的特定模型、数据和硬件。没有单一的配置总是最有效 - 但是有 一些可以 做和不应该做的事情来简化您的搜索:
> > 做:
> > 不要:
fit()+ numpy+keras适用于中小型模型和数据
fit()+ numpy+ tf.keras+ TF1/TF2 + 渴望
train_on_batch()+ numpy+ keras+ TF1 + 渴望
[专业] tf.python.keras ; 它的运行速度可以慢 10-100 倍,并且有很多错误;
tf.python.keras
layers
models
optimizers
有关示例基准测试设置,请参阅我的其他答案底部的代码。上面的列表主要基于另一个答案中的“基准”表。
*上述做与不做的 *限制:
Conv1D
Dense
为什么 TF2 牺牲了最实用的质量和速度,换取了急切的执行力? 它没有,很明显 - 图表仍然可用。但如果问题是“为什么急于求成”:
.__dict__
如何启用/禁用 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()
对 TensorFlow 开发人员的要求 :
致谢 :感谢
更新 :
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
on_batch()
tf-nightly
2/20/20 - 预测性能也值得一试;例如,在 TF2 中,CPU 预测时间可能涉及周期性尖峰