Python 在GPU上加速TF/Keras LSTM文本生成?

Python 在GPU上加速TF/Keras LSTM文本生成?,python,performance,tensorflow,keras,Python,Performance,Tensorflow,Keras,tensorflow文本生成的官方示例()在如下定义的循环中运行。文本生成感觉很慢,根据NVTOP的说法,它只使用了可用GPU资源的一小部分(15-20%) 有没有关于如何加快文本生成的建议?快速查看cprofiler可以发现,90%的时间都花在单行predictions=model(input\u eval)上,因此我认为其他地方没有太多的收益 此外,Tensorflow/Keras文档建议调用函数,如下所示 这种方法是为在大规模输入下的性能而设计的。对于 一批适合的少量输入,直接使用调用

tensorflow文本生成的官方示例()在如下定义的循环中运行。文本生成感觉很慢,根据NVTOP的说法,它只使用了可用GPU资源的一小部分(15-20%)

有没有关于如何加快文本生成的建议?快速查看cprofiler可以发现,90%的时间都花在单行
predictions=model(input\u eval)
上,因此我认为其他地方没有太多的收益

此外,Tensorflow/Keras文档建议调用函数,如下所示

这种方法是为在大规模输入下的性能而设计的。对于 一批适合的少量输入,直接使用调用 建议用于更快的执行,例如型号(x)或型号(x、, 培训(错误)

有没有关于如何加快文本生成的建议?通过同时生成多条线路,是否有可能更好地使用GPU

def generate_text(model, start_string):
  # Evaluation step (generating text using the learned model)

  # Number of characters to generate
  num_generate = 1000

  # Converting our start string to numbers (vectorizing)
  input_eval = [char2idx[s] for s in start_string]
  input_eval = tf.expand_dims(input_eval, 0)

  # Empty string to store our results
  text_generated = []

  # Low temperatures results in more predictable text.
  # Higher temperatures results in more surprising text.
  # Experiment to find the best setting.
  temperature = 1.0

  # Here batch size == 1
  model.reset_states()
  for i in range(num_generate):
      predictions = model(input_eval)
      # remove the batch dimension
      predictions = tf.squeeze(predictions, 0)

      # using a categorical distribution to predict the character returned by the model
      predictions = predictions / temperature
      predicted_id = tf.random.categorical(predictions, num_samples=1)[-1,0].numpy()

      # We pass the predicted character as the next input to the model
      # along with the previous hidden state
      input_eval = tf.expand_dims([predicted_id], 0)

      text_generated.append(idx2char[predicted_id])

  return (start_string + ''.join(text_generated))

不确定您是否可以加快生成。对于批量大小为1的输入,您正在对模型执行
num\u generate
转发调用。在训练期间,您可以对整个序列进行操作并计算其损失,在预测期间,每个新角色取决于先前生成的角色,并且生成函数不会并行运行

如果你想看到更高的GPU利用率,你可以调用predict对一批不同起始字符的输入进行预测——这与你关于“同时生成多行”的问题有关


您还可以尝试使用相同的起始字符并修改隐藏状态以输入到模型中,例如,查看批次的随机采样状态会产生什么,或从训练示例中提取该起始角色的隐藏状态向量,并用这些向量填充批次隐藏状态,以便您的模型与该初始角色的方向不同。

为了加快处理速度,我有两个建议

  • 由于您有GPU支持,您可能需要设置
    GRU
    层的
    unroll=True
    。根据Keras
    GRU
    ,设置
    unroll=True
    通过使用一些额外内存来减少一些计算。由于您的GPU消耗量非常少,您可能希望使用
    unroll=True
    。使用此设置,您可能会注意到多达2倍的速度提升(取决于具体情况)。但是,如果输入序列太长,则应避免使用展开

  • 我注意到,您使用的
    GRU
    层的文本生成架构在
    密集层之前。
    GRU
    被赋予一个参数
    return\u sequences=True
    。这会导致
    GRU
    层将不必要的输出值传递给以下
    密集层
    层,需要更多的计算。通常,仅当模型的下一层也是RNN层时,才应设置
    return\u sequences=True
    。因此,请尝试设置参数
    return\u sequences=False
    。这也可以提高性能


  • 最后,
    模型(x,training=False)
    确实有效。我相信通过维护这三个问题,您可能会注意到显著的性能改进。

    如果您设置
    unroll=True
    ,那么将不会使用GRU的CUDNN实现。CUDNN实现比其他GPU实现快得多(大约10倍)。是的,你是对的。在大多数情况下,CUDNN的性能优于一般实现。但是,我注意到在某些情况下(我相信在大多数情况下),使用“展开”可以提高性能(我不知道为什么,但我经历过)。这就是为什么我已经添加了一个短语“(视情况而定)”。此外,我还记得在前面的一个问题上回答了这个问题。我经历了性能提升,提问的人也经历了。实际上,在我的例子中,使用unroll=True可以提高大约50%的速度。我正在运行一个conv net,后面是一个fc lstm层。您是否尝试将
    @tf.function
    添加到此
    生成文本
    函数?有一些问题需要解决才能使其正常工作,但这将使您从急于执行到图形执行,在图形执行中可以更好地进行编译。