CuDNNLSTM和LSTM在Keras中有什么区别?

53
在高级深度学习库Keras中,有多种类型的循环层,包括LSTM(长短期记忆)和CuDNNLSTM。根据Keras文档,CuDNNLSTM是一种:
快速的LSTM实现,支持CuDNN。只能在使用TensorFlow后端的GPU上运行。
我认为Keras会自动尽可能地使用GPU。根据TensorFlow构建说明,要使用工作正常的TensorFlow GPU后端,需要安装CuDNN:
必须在您的系统上安装以下NVIDIA软件:
- NVIDIA的Cuda Toolkit(>= 7.0)。我们推荐使用版本9.0。有关详细信息,请参见NVIDIA的文档。请确保按照NVIDIA文档中的说明将相关的Cuda路径名附加到LD_LIBRARY_PATH环境变量中。 - 与NVIDIA的Cuda Toolkit相关联的NVIDIA驱动程序。 - cuDNN(>= v3)。我们推荐使用版本6.0。有关详细信息,请参见NVIDIA的文档,特别是关于将适当的路径名附加到LD_LIBRARY_PATH环境变量中的描述。
因此,使用TensorFlow GPU后端的常规LSTM与CuDNNLSTM有何不同?当发现可用的TensorFlow GPU后端时,CuDNNLSTM是否会自动选择并替换常规LSTM?

我猜它们是一样的?只有在没有GPU运行时才会有所不同。 - TYZ
3
如果您要将模型部署到生产环境中,选择LSTM <-> CuDNNLSTM很重要。例如��Google Cloud平台到目前为止仅允许您在其“AI平台”上使用CPU机器。因此,如果您使用CuDNNLSTM训练模型,就无法将其部署。 - Vlad-HC
5个回答

32

为什么不亲自试一下呢? 在我的情况下,使用 LSTM 训练一个模型需要10分30秒。 只需将调用从 LSTM() 切换到 CuDNNLSTM() 就不到一分钟。

我还注意到切换到 CuDNNLSTM() 也显著加快了 model.evaluate()model.predict() 的速度。


6
我刚刚发现这件事,太惊奇了!以前我在大型数据集上评估一个模型需要3个小时,现在只需要大约20分钟。 - aL_eX
10
CuDNNLSTM比普通的LSTM更快(因为它使用GPU支持),但是它的选项较少,例如没有dropout。 - lbcommer
请查看此帖子以获取更多信息:https://www.reddit.com/r/learnmachinelearning/comments/9jv0gx/what_is_the_difference_between_cudnnlstm_lstm/ - Arayan Singh
1
只是再强调一下之前说过的。使用10个LSTM层、3个密集层和每层200个神经元以硬Sigmoid激活函数运行模型,强制使用通用GPU - 每个时期超过40分钟。将其改回普通Sigmoid允许cuDNN - 每个时期54秒。这会产生巨大的差异。 - Jeremy Slater
我刚在Python 3.9.9和Tensorflow 2.7.0上尝试了一下。我用tf.compat.v1.keras.layers.CuDNNLSTM(128, return_sequences=True)替换了tf.keras.layers.LSTM(128, return_sequences=True),结果我得到了超过3倍的速度提升,从每步110毫秒降至38毫秒。在RTX 3080Ti上运行,低端显卡可能会看到更大的性能提升。因此,官方文档关于tensorflow 2.x已经使用CuDNN内核的说法是不正确的,至少对我来说不起作用。 - Billy Cao

16
在TensorFlow 2.0中,内置的LSTM和GRU层已经默认使用CuDNN内核来利用GPU。由于这个改变,之前的keras.layers.CuDNNLSTM/CuDNNGRU层已经被弃用,您可以构建模型而不必担心它将在什么硬件上运行。
由于CuDNN内核是基于某些假设构建的,这意味着如果更改内置的LSTM或GRU层的默认值,则该层将无法使用CuDNN内核。
请查阅tensorflow RNN文档:https://www.tensorflow.org/guide/keras/rnn

1
这是不正确的。我刚在Python 3.9.9和Tensorflow 2.7.0上尝试了一下。我用tf.compat.v1.keras.layers.CuDNNLSTM(128, return_sequences=True)替换了tf.keras.layers.LSTM(128, return_sequences=True),结果我得到了超过3倍的速度提升,从每步110毫秒到38毫秒。在RTX 3080Ti上运行,低端显卡可能会看到更大的性能提升。因此,你所说的关于tensorflow 2.x已经使用CuDNN内核的说法是不正确的,至少对我来说不起作用。 - Billy Cao
1
经过测试,使用Keras 2.4/TF 2.3和RTX 2060 Super,通过tf.compat.v1.keras.layers调用CuDNNLSTM与LSTM相比没有提升速度。在我的情况下,两种方法每步都需要24ms。 - James_SO

13

TL;DR:使用GPU训练模型速度提高了15倍!

设置步骤

依赖项

性能基准:标准测试机的比较。
对612235个样本进行1次迭代训练。

keras.layers.LSTM Intel i5-4690 CPU only: 612235/612235 [==============================] - 3755秒6毫秒/步 - 损失: 2.7339 - 准确率: 0.5067 - val_loss: 2.1149 - val_acc: 0.6175

GTX:950 & Intel i5-4690: 612235/612235 [==============================] - 1417秒2毫秒/步 - 损失: 2.7007 - 准确率: 0.5137 - val_loss: 2.0983 - val_acc: 0.6199

使用GPU可获得2.5倍的增益。

GTX:970 & Intel i5-4690: 612235/612235 [==============================] - 1322秒2毫秒/步 - 损失: 1.9214 - 准确率: 0.6442 - val_loss: 1.8808 - val_acc: 0.6461

强大的GPU带来的收益可以忽略不计。

RTX 2070 & Intel i7-9700K: 612235/612235 [==============================] - 1012s 2ms/step - 损失: 2.7268 - 准确率: 0.5111 - 验证损失: 2.1162 - 验证准确率: 0.6234

即使使用了强大的硬件升级,也只有极少的收益!

keras.layers.CuDNNLSTM RTX 2070 & Intel i7-9700K: 612235/612235 [==============================] - 69秒 112us/step - 损失: 1.9139 - 准确率: 0.6437 - 验证损失: 1.8668 - 验证准确率: 0.6469

CPU 的性能只有它的54倍!
传统(非Cuda)LSTM实现的性能只有它的15倍!


3
似乎只需要展示最后2个案例,因为它们是公平测试——相同的组件,仅CuDNNLSTM与LSTM不同。前几个示例只会让你的帖子变得混乱。 - cryanbhu

3

GPU适用于大规模并行计算,大多数线性代数运算可以进行并行化以提高性能。向量操作例如矩阵乘法和梯度下降可应用于大型矩阵,借助GPU支持并行执行。 CUDA - 统一计算架构为向量操作提供了接口以利用GPU的并行性。CuDNN使用CUDA实现了在GPU上进行大型矩阵运算的内核。

在此,CuDNNLSTM专门设计用于CUDA并行处理,如果没有GPU则无法运行。但是,LSTM是专为普通CPU设计的。由于并行化,执行速度更快。


0

lbcommer评论说得非常到位。从LSTM层切换到cuDNNLSTM层速度快了很多,大约是10-20倍,但你会失去一些选项,使其更不灵活。你会失去的重要选项包括:掩码、自定义激活和dropout。

然而,可以通过进一步的层次结构或在其他层次结构中引入一些这些属性,来争论一些这些属性可以被引入模型中。

因此,如果这很重要,或者你没有GPU,或者部署是一个问题,那就使用LSTM。否则,cuDNNLSTM是有意义的选择。

另外,考虑在较小的数据集上使用GRU,因为它更快且更节省内存。它只会在数据集增长时出现精度问题。

还要考虑在Keras中通过transformers实现的方式。

tf.keras.layers.Attention()

由于所有的输入都一次性被摄入,因此这些也更快。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接