lstm 不会使用 cuDNN 内核,因为它不符合标准。在 GPU 上运行时,它将使用通用 GPU 内核作为回退



我在使用GPU的Databricks上运行以下LSTM代码

model = Sequential()
model.add(LSTM(64, activation=LeakyReLU(alpha=0.05), batch_input_shape=(1, timesteps, n_features), 
stateful=False, return_sequences = True))
model.add(Dropout(0.2))
model.add(LSTM(32))
model.add(Dropout(0.2))
model.add(Dense(n_features))
model.compile(loss='mean_squared_error', optimizer=Adam(learning_rate = 0.001), metrics='acc')
model.fit(generator, epochs=epochs, verbose=0, shuffle=False)

但是下面的警告一直出现

WARNING:tensorflow:Layer lstm will not use cuDNN kernels since it doesn't meet the criteria. It will use a generic GPU kernel as fallback when running on GPU.

它的训练速度比没有GPU时慢得多。我使用的是DBR 9.0 ML(包括Apache Spark 3.1.2, GPU, Scala 2.12)为此我需要任何额外的库吗?

CUDNN具有专门加速LSTM和GRU层的功能。这些GRU/LSTM层只有在满足一定标准的情况下才能加速。在您的案例中,问题是您正在使用LeakyReLU激活。CUDNN LSTM加速仅在激活为tanh时有效。

引用文档(https://www.tensorflow.org/api_docs/python/tf/keras/layers/LSTM)

The requirements to use the cuDNN implementation are:
activation == tanh
recurrent_activation == sigmoid
recurrent_dropout == 0
unroll is False
use_bias is True
Inputs, if use masking, are strictly right-padded.
Eager execution is enabled in the outermost context.

你的LSTM应该仍然在gpu上运行,但它将使用扫描和matl操作构建,因此要慢得多。从我的经验来看,CUDNN的LSTM/GRU加速工作得非常好,尽管这一层简单得多,但这两层都比SimpleRNN层运行得更快。

这是Francois Chollet, keras库的创建者,tensorflow框架的主要贡献者,在他的书《Deep Learning with Python 2nd edition》中对RNN运行时性能的看法

具有很少参数的循环模型,如本章中的那些,在多核CPU上往往比在GPU上要快得多,因为它们只涉及小矩阵乘法,并且由于for循环的存在,乘法链不能很好地并行化。但更大的rnn可以从GPU运行时中受益匪浅。

当在带有默认关键字参数的GPU上使用Keras LSTM或GRU层时,您的层将利用cuDNN内核,这是一种高度优化的低级nvidia提供的底层算法实现。像往常一样,cuDNN内核是好坏参半的:它们很快,但不灵活——如果你试图做默认内核不支持的任何事情,你将遭受严重的慢速,这或多或少迫使你坚持使用NVIDIA碰巧提供的东西。例如,LSTM和GRU cuDNN内核不支持循环dropout,所以将它添加到你的层中会迫使运行时回到常规的TensorFlow实现,这在GPU上通常要慢2到5倍(尽管它的计算成本是相同的)。

当你不能使用cuDNN时,作为一种加速RNN层的方法,你可以尝试展开它。展开for循环包括删除循环并简单地将其内容内联N次。对于RNN的for循环,展开可以帮助TensorFlow优化底层计算图。然而,它也会大大增加rnn的内存消耗——因此,它只适用于相对较小的序列(大约100步或更少)。另外,请注意,只有在模型事先知道数据中的时间步长的情况下才能这样做(也就是说,如果您将没有任何None条目的形状传递给初始Input())。它是这样工作的:

inputs = keras.Input(shape=(sequence_length, num_features))
x = layers.LSTM(32, recurrent_dropout=0.2, unroll=True)(inputs)

最新更新