C++ GPT 运行时
TensorRT-LLM 包含一个 C++ 组件,用于执行使用 Python API 构建的 TensorRT 引擎,如 TensorRT-LLM 架构 部分所述。该组件称为 C++ 运行时。
C++运行时的API由在cpp/include/tensorrt_llm/runtime中声明并在cpp/tensorrt_llm/runtime中实现的类组成。
即使该文档中描述的不同组件在其名称中提到了GPT,它们也不仅限于此特定模型。例如,这些类可用于实现自回归模型,如BLOOM、GPT-J、GPT-NeoX或LLaMA。
对编码器-解码器模型(如T5)的完整支持将在未来的版本中添加到TensorRT-LLM中。目前,一个实验版本(仅限Python)可以在examples/enc_dec文件夹中找到。
概述
运行时模型由
ModelConfig
类的实例和必须执行的TensorRT引擎的指针描述,以执行推理。
环境通过
WorldConfig
配置(该名称来自
MPI 及其“著名的”
MPI_COMM_WORLD 默认通信器)。
SamplingConfig
类封装了控制新令牌
生成的参数。
模型配置
模型配置是ModelConfig类的一个实例。该类封装了以下参数(它们被声明为私有成员变量,并通过getter和setter方法暴露):
vocabSize, 词汇表的大小,numLayers,模型中的层数,numHeads,注意力块中的头数,numKvHeads,注意力组件中K和V的头数。 当K/V头的数量与(Q)头的数量相同时,模型使用多头注意力。当K/V头的数量为1时,它使用多查询注意力。否则,它使用组查询注意力。更多信息请参考多头、多查询和组查询注意力,hiddenSize,隐藏层的大小,dataType,用于构建TensorRT引擎的数据类型,并且必须在推理期间用于运行模型,useGptAttentionPlugin,表示Multi-Head, Multi-Query, and Group-Query Attention操作符是否使用了GPT Attention插件进行编译,inputPacked,表示输入必须被打包(或在设置为false时进行填充)。出于性能考虑,建议始终使用打包,即使其默认设置为false(将在未来的版本中更改)。更多信息请参考多头、多查询和组查询注意力,pagedKvCache,表示K/V缓存是否使用分页。 更多信息请参考多头、多查询和组查询注意力,tokensPerBlock,是K/V缓存中每个块的令牌数量。 当启用分页K/V缓存时,它是相关的。默认情况下,该值为64。有关更多信息,请参阅多头、多查询和组查询注意力,quantMode,控制量化方法。更多信息请参考数值精度。maxBatchSize,表示TensorRT引擎构建时的最大批量大小,maxInputLen,输入序列的最大长度,maxSequenceLen,序列的最大总大小(输入+输出)。
世界配置
熟悉 MPI 不是使用 TensorRT-LMM C++ 运行时的必要条件。你需要知道的主要有两点:
TensorRT-LLM中的C++运行时使用 进程来在不同的GPU上执行 TensorRT引擎。这些GPU可以位于单个节点上,也可以位于集群中的不同节点上。每个进程在MPI中被称为 rank。
排名按通信组进行分组。TensorRT-LLM C++ 运行时调用将该组称为 world。
世界配置是
WorldConfig
类的一个实例,它封装了以下参数:
tensorParallelism,协作实现张量并行(TP)的等级数量。使用TP时,每个GPU执行模型所有层的计算。其中一些计算分布在GPU之间。在大多数情况下,TP比管道并行(PP)更平衡,但需要GPU之间更高的带宽。在GPU之间存在NVLINK的情况下,这是推荐的设置。pipelineParallelism,协作实现管道并行(PP)的等级数量。使用PP时,每个GPU处理一组连续的层。GPU之间的通信仅在层的子集边界处发生。使用PP时,很难保证GPU的完全利用率,但它需要的内存带宽较少。在没有GPU之间的NVLINK的情况下,这是推荐的设置。rank,排名的唯一标识符,gpusPerNode,表示每个节点上的GPU数量。拥有这些信息可以让C++运行时优化节点内GPU之间的通信(例如利用A100 DGX节点中GPU之间的NVLINK互连优势)。
采样参数
SamplingConfig 类封装了控制新令牌生成的参数。选择解码方法的比较如下表所示(X 表示尚未支持)。除了 beamWidth 参数外,所有字段都是可选的,如果用户未提供值,运行时将使用默认值。对于向量字段,TensorRT-LLM 运行时支持每个序列一个值(即向量包含 batchSize 个值)。如果所有序列对给定参数使用相同的值,则向量可以限制为单个元素(即 size() == 1)。
HF中的方法名称 |
HF中的条件 |
TRT-LLM中的方法名称 |
TRT-LLM中的条件 |
|---|---|---|---|
辅助解码 |
|
X |
|
束搜索解码 |
|
束搜索 |
|
波束搜索多项式采样 |
|
X |
|
受限束搜索解码 |
|
X |
|
对比搜索 |
|
X |
|
多样化的束搜索解码 |
|
X |
|
贪婪解码 |
|
采样 |
|
多项式采样 |
|
采样 |
|
通用
TRT-LLM中的名称 |
描述 |
数据类型 |
值的范围 |
默认值 |
HF中的名称 |
|---|---|---|---|---|---|
|
采样工作流中对logits的调制 |
浮点数列表 |
[0.0f, $+\infty$) |
|
|
|
生成的令牌数量的下限 |
整数列表 |
[0, $+\infty$) |
|
|
|
惩罚重复的标记 |
浮点数列表 |
[0.0f, $+\infty$) |
|
|
|
惩罚已存在的令牌 |
浮点数列表 |
($-\infty$, $+\infty$) |
|
不 |
|
惩罚已存在的令牌 |
浮点数列表 |
($-\infty$, $+\infty$) |
|
不 |
|
整数列表 |
[0, $+\infty$) |
|
|
在将
repetitionPenalty、presencePenalty和frequencyPenalty应用于logits时,输入提示的tokens被包含在内。参数
repetitionPenalty,presencePenalty, 和frequencyPenalty并不相互排斥。
采样
TRT-LLM中的名称 |
描述 |
数据类型 |
值的范围 |
默认值 |
HF中的名称 |
|---|---|---|---|---|---|
|
随机数生成器的随机种子 |
Int64 |
[0, 2^64-1] |
|
不 |
|
从中采样的logits数量 |
整数列表 |
[0, 1024] |
|
|
|
从中采样的最高P概率 |
浮点数列表 |
[0.0f, 1.0f] |
|
|
|
在 |
浮点数列表 |
(0.0f, 1.0f] |
|
不 |
|
|
浮点数列表 |
(0.0f, 1.0f] |
|
不 |
|
|
整数列表 |
[-1, $+\infty$) |
|
不 |
如果设置
topK = 0和topP = 0.0f,则执行贪婪搜索。如果设置
topK > 0并且topP = 0.0f,topK个最高概率的标记将成为采样的候选(在TRT-LLM中称为TopK sampling)。如果设置
topK = 0和topP > 0.0f,令牌将按概率降序排序,然后累积概率大于topP的最高概率令牌将成为采样的候选(在TRT-LLM中称为TopP sampling)。如果设置
topK > 0和topP > 0.0f,将选择概率最高的topK个标记,然后这些选定的标记将按概率降序排序,并且它们的概率将被归一化,然后归一化概率最高的标记,其累积概率大于topP的标记将成为采样的候选(在TRT-LLM中称为TopKTopP sampling)如果为批次中的不同序列提供了不同的
topK值,实现的性能将取决于最大的值。出于效率考虑,我们建议将具有相似topK值的请求批次处理在一起。topPDecay、topPMin和topPResetIds在 Factuality Enhanced Language Models for Open-Ended Text Generation 中有解释。topPDecay是衰减率,topPMin是下限,topPResetIds表示在哪里重置衰减。
Beam-search
TRT-LLM中的名称 |
描述 |
数据类型 |
值的范围 |
默认值 |
HF中的名称 |
|---|---|---|---|---|---|
|
beam-search算法的宽度 |
整数 |
[0, 1024] |
|
|
|
生成标记的多样性 |
浮点数列表 |
[0, $+\infty$) |
|
|
|
惩罚较长的序列 |
浮点数列表 |
[0, $+\infty$) |
|
|
|
请参阅以下描述 |
整数列表 |
($-\infty$, $+\infty$) |
|
|
Beam-search算法: beam search.
参数
diversity_penalty在 HF 中仅用于diverse beam-search decoding(或称为Group-Beam-Search),TRT-LLM 目前还不支持此功能。如果设置
earlyStopping = 1,一旦生成beamWidth个完成的句子,解码将停止。如果设置
earlyStopping = 0,解码将继续进行,直到无法生成更好的句子(具有更高的分数)。如果将
earlyStopping设置为其他值,解码将仅取决于lengthlengthPenalty。beamWidth参数是一个标量值。这意味着在 TensorRT-LLM 的这个版本中,无法为每个输入序列指定不同的宽度。这个限制可能会在未来的版本中被移除。
会话
运行时会话已被弃用,推荐使用Executor API。 它将在未来的TensorRT-LLM版本中被移除。
一个关于如何使用GptSession来运行类似GPT的自回归模型的示例可以在
cpp/tests/runtime/gptSessionTest.cpp中找到。
内部组件
GptSession 类封装了两个主要组件。TllmRuntime 负责执行 TensorRT 引擎。GptDecoder 负责从 logits 生成 tokens。TllmRuntime 类是一个内部组件,您不需要直接使用该类。GptDecoder 可以直接用于实现自定义生成循环,以及用于 GptSession 中的实现无法满足的用例。
飞行中批处理支持
支持使用每个请求的独立解码器进行飞行中的批处理。与使用单个解码器相比,最大的区别在于如何管理从logits生成的令牌。一个批次被分割成batchSize个独立请求,并使用独立的CUDA流发出内核。这种行为可能会在未来的版本中重新审视,以保持批次的结构并提高效率。
已知问题和未来变更
在当前版本的TensorRT-LLM中,C++和Python运行时是两个独立的软件组件,C++运行时正在更积极地开发(具有如飞行批处理等功能)。未来的一个目标可能是在C++运行时的基础上重建Python运行时。