5、LLM训练/推理框架

1、训练框架

一些主流框架,先区分一下这几个东西:
https://zhuanlan.zhihu.com/p/672448526

  • DeepSpeed:这是一个用于加速深度学习模型训练的开源库,由微软开发。它提供了一种高效的训练框架,支持分布式训练、模型并行和数据并行。DeepSpeed 还包括内存优化技术,如梯度累积和激活检查点,以降低内存需求。DeepSpeed 可以与流行的深度学习框架(如 PyTorch)无缝集成。
  • Megatron:Megatron 是 NVIDIA 开发的一个用于训练大规模 transformer 模型的项目。它基于 PyTorch 框架,实现了高效的并行策略,包括模型并行、数据并行和管道并行。Megatron 还采用了混合精度训练,以减少内存消耗并提高计算性能。
  • Megatron-LM:Megatron-LM 是在 Megatron 的基础上,结合了 DeepSpeed 技术的NVIDIA做的项目。它旨在进一步提高训练大规模 transformer 模型的性能。Megatron-LM 项目包括对多种 transformer 模型(如 BERT、GPT-2 和 T5)的支持,以及一些预训练模型和脚本, 主导Pytorch。
  • Megatron-DeepSpeed : 采用了一种名为 ZeRO (Zero Redundancy Optimizer) 的内存优化技术,以降低内存占用并提高扩展性,提供了一些其他优化功能,如梯度累积、激活检查点等。Megatron-DeepSpeed 支持多个深度学习框架,包括 PyTorch、TensorFlow 和 Horovod。这使得 Megatron-DeepSpeed 对于使用不同框架的用户具有更广泛的适用性。

通信优化

链接:https://blog.csdn.net/c9Yv2cf9I06K2A9E/article/details/130570164
NCCL 英伟达集合通信库,是一个专用于多个 GPU 乃至多个节点间通信的实现。它专为英伟达的计算卡和网络优化,能带来更低的延迟和更高的带宽。
a. Broadcast: Broadcast 代表广播行为,执行 Broadcast 时,数据从主节点 0 广播至其他各个指定的节点(0~3)。
b. Scatter: Scatter 与 Broadcast 非常相似,都是一对多的通信方式,不同的是 Broadcast 的 0 号节点将相同的信息发送给所有的节点,而 Scatter 则是将数据的不同部分,按需发送给所有的节点。
c. Reduce: Reduce 称为规约运算,是一系列简单运算操作的统称,细分可以包括:SUM、MIN、MAX、PROD、LOR 等类型的规约操作。Reduce 意为减少/精简,因为其操作在每个节点上获取一个输入元素数组,通过执行操作后,将得到精简的更少的元素。
d. AllReduce: Reduce 是一系列简单运算操作的统称,All Reduce 则是在所有的节点上都应用同样的 Reduce 操作。
e. Gather: Gather 操作将多个 sender 上的数据收集到单个节点上,Gather 可以理解为反向的 Scatter。
f. AllGather: 收集所有数据到所有节点上。从最基础的角度来看,All Gather 相当于一个 Gather 操作之后跟着一个 Broadcast 操作。
g. ReduceScatter: Reduce Scatter 操作会将个节点的输入先进行求和,然后在第0维度按卡数切分,将数据分发到对应的卡上。

并行计算技术

链接:https://blog.csdn.net/c9Yv2cf9I06K2A9E/article/details/130570164
a. 数据并行 DP
DP (Data Parallel):本质上是单进程多线程的实现方式,只能实现单机训练不能算是严格意义上的分布式训练。
分布式数据并行 DDP (Distribution Data Parallel):采用 AllReduce 架构,在单机和多机上都可以使用。负载分散在每个 GPU 节点上,通信成本是恒定的,与 GPU 数量无关。

b. 张量并行(/模型并行):分布式张量计算是一种正交且更通用的方法,它将张量操作划分到多个设备上,以加速计算或增加模型大小。

c. 流水并行( pipeline 并行):无论是数据并行还是模型并行,都会在相应的机器之间进行全连接的通信,当机器数量增大时,通信开销和时延会大到难以忍受。而流水并行既解决了超大模型无法在单设备上装下的难题,又很好解决了机器之间的通信开销的问题,每个阶段(stage) 和下一个阶段之间仅有相邻的某一个 Tensor 数据需要传输,每台机器的数据传输量跟总的网络大小、机器总数、并行规模无关。
pipeline 并行:
1.G-pipe:空泡率比较高
2.PipeDream:但通过合理安排前向和反向过程的顺序,在 step 中间的稳定阶段,形成 1前向1反向 的形式,称为 1F1B 模式,在这个阶段,每个 Device 上最少只需要保存 1 份 micro-batch 的激活值,最多需要保存 p 份激活值。
3.virtual pipeline:但virtual pipeline 的却反其道而行之,在 device 数量不变的情况下,分出更多的 pipeline stage,以更多的通信量,换取空泡比率降低,减小了 step e2e 用时(step e2e 上直观的改善可以看文章题图)。

d. 梯度累加:Gradient Accumulation 就是把一个大 Batch 拆分成多个 micro-batch,每个 micro-batch 前后向计算后的梯度累加,在最后一个 micro-batch 累加结束后,统一更新模型。
在流水并行下, Gradient Accumulation 使得不同 stage 之间可以并行执行不同的 micro-batch, 从而让各个阶段的计算不阻塞,达到流水的目的。如果每个 micro-batch 前向计算的中间结果(activation)被后向计算所消费,则需要在显存中缓存 8多份(梯度累加的次数)完整的前向 activation。这时就不得不用另一项重要的技术:激活检查点(activation checkpointing)。

e. 激活检查点:Checkpointing 的核心思想 是在前向网络中标记少量的 Tensor (被 Checkpointing 的 Tensor ),前向计算就只会保留这些被标记的 Tensor, 其余的前向的 activation,会通过在反向传播中根据 Checkpointing 的 Tensor 临时重新计算一遍前向得到。这样就使得大量的 activation 不需要一直保存到后向计算,有效减少了大量 Tensor 的生命周期,使得内存复用效率大幅提升。

f.ZeRO
ZeRO 将模型训练阶段,每张卡中显存内容分为两类:

  1. 模型状态 (model states):模型参数 (fp16) 、模型梯度 (fp16) 和Adam状态 (fp32 的模型参数备份, 的 momentum 和 fp32 的 variance) 。假设模型参数量 ,则共需要 字节存储,可以看到,Adam 状态占比 。
  2. 剩余状态 (residual states) :除了模型状态之外的显存占用,包括激活值 (activation) 、各种临时缓冲区(buffer)以及无法使用的显存碎片(fragmentation)。

g.混合精度训练
混合精度训练(mixed precision training)[1] 和 Adam [2] 优化器基本上已经是训练语言模型的标配,我们先来简单回顾下相关概念。Adam 在 SGD 基础上,为每个参数梯度增加了一阶动量(momentum)和二阶动量(variance)。混合精度训练,字如其名,同时存在 fp16 和 fp32 两种格式的数值,其中模型参数、模型梯度都是 fp16,此外还有 fp32 的模型参数,如果优化器是 Adam,则还有 fp32 的 momentum 和 variance。

deepspeed

https://github.com/microsoft/DeepSpeed
https://blog.csdn.net/Neleuska/article/details/136645597
一.简介
二.分布式训练方法
1.数据并行
2.张量并行
3.流水线并行
三.ZeRO
1.模型的显存占用
2.ZeRO-1/2/3
3.ZeRO-Offload
4.ZeRO-Infinity
四.总结
分别对forward和backward过程优化

在这里插入图片描述
由上图可以看出:
假如GPU卡数为N=64,Ψ是模型参数,假设Ψ=7.5B,假设使用Adam优化器,在64个GPU下K=12,则:
如果不用ZeRO,需要占用120GB的显存,A100最大才80GB,塞不下
如果用ZeRO Stage1,则占用31.4GB,A100 40GB或者80GB卡都能跑,单机多卡或多机多卡训练的通信量不变
如果用ZeRO Stage2,则占用16.6GB,大部分卡都能跑了,比如V100 32GB,3090 24GB,通信量同样不变
如果用ZeRO Stage3,则占用1.9GB,啥卡都能跑了,但是通信量会变为1.5倍
所以根据实际硬件资源,选择适合Stage策略即可。如果遇到要跑更大的模型,比如想在3090 24GB下跑13B模型,可能Stage3也OOM跑不起来,此时可以开启Optimizer Offload和Param Offload即可跑起来,但相应的性能会受影响。https://zhuanlan.zhihu.com/p/639927499

Megatron

Megatron采用了三种并行技术:张量并行(Tensor Parallelism)、流水线并行(Pipeline Parallelism)和数据并行(Data Parallelism)。这三种并行技术的结合,使得Megatron能够充分利用多节点、多GPU的计算资源,实现高效的并行训练。Megatron通过结合张量并行和流水线并行,可以在每个GPU上处理不同的数据子集,从而实现高效的数据并行训练。

1、数据并行(DP )

概念:相同的模型分布在不同的GPU上,在不同的GPU上使用不同的数据。每一张GPU上有相同的参数,在训练的时候每一个GPU训练不同的数据,相当于增大了训练时候的batch_size。
数据并行基于一个假设:所有节点都可以放下整个模型。这个假设在某些模型上(如GPT3)是不合理的,因此我们还需要模型并行。

DP (Data Parallel):本质上是单进程多线程的实现方式,只能实现单机训练不能算是严格意义上的分布式训练。步骤如下:
首先将模型加载到主 GPU 上,再复制到各个指定从 GPU;
将输入数据按照 Batch 维度进行拆分,各个 GPU 独立进行 forward 计算;
将结果同步给主 GPU 完成梯度计算和参数更新,将更新后的参数复制到各个 GPU。
主要存在的问题:
负载不均衡,主 GPU 负载大
采用 PS 架构通信开销大
分布式数据并行 DDP (Distribution Data Parallel):采用 AllReduce 架构,在单机和多机上都可以使用。负载分散在每个 GPU 节点上,通信成本是恒定的,与 GPU 数量无关。

2、模型并行:

https://zhuanlan.zhihu.com/p/420908718
模型并行,包括Tensor并行和Pipeline并行两种模型并行方式。
相对于Tensor并行的把模型的每一层内部进行切分,Pipeline并行是会在模型的层之间进行切分,不同的层在不同的GPU或机器节点上进行计算。
模型并行分为两种:流水线并行和张量并行,就是把模型切分的方式。

  • 流水线并行(pipeline model parallel)是把模型不同的层放到不同设备之上,比如前面几层放到一个设备之上,中间几层放到另外一个设备上,最后几层放到第三个设备之上。
  • 张量并行则是层内分割,把某一个层做切分,放置到不同设备之上,也可以理解为把矩阵运算分配到不同的设备之上,比如把某个矩阵乘法切分成为多个矩阵乘法放到不同设备之上。链接:https://blog.csdn.net/zwqjoy/article/details/132507636
    在这里插入图片描述
    在这里插入图片描述

3、Pipeline 模型并行

流水线并行:通信在流水线阶段相邻的切分点之上,通信类型是P2P通信,单词通信数据量较少但是比较频繁,而且因为流水线的特点,会产生GPU空闲时间,这里称为流水线气泡(Bubble)。
相对于Tensor并行的把模型的每一层内部进行切分,Pipeline并行是会在模型的层之间进行切分,不同的层在不同的GPU或机器节点上进行计算。由于不同的层间有依赖关系,所以如果直接并行会像下图所示,黑色部分是前向,绿色部分是反向计算,灰色部分是空闲,可以看出GPU的绝大部分时间是在等待。
在这里插入图片描述为了解决这个问题,Megatron把每一个batch分成了更小的microbatch,如下图所示,把batch 1分成了1a,1b,1c,1d四个microbatch,由于不同的microbatch间没有数据依赖,因此互相可以掩盖各自的等待时间,提高GPU利用率,提升整体的性能。
在这里插入图片描述

GPipe 流水线和气泡

https://strint.notion.site/Megatron-LM-86381cfe51184b9c888be10ee82f3812
GPipe 的流水线就实现了严格的 Optimizer 语义。对于 GPipe,只有当一个批次中所有 microbatches 的前向计算完成后,才会执行后向计算。
如下图所示,黑色的竖线对应一次 Pipeline flush. 它之前的区域代表一个 batch 的数据执行的时空图,横向对应时间,纵向代表设备。具体的,这是一个4级流水线,每级一个 device(对应一个 device 上的运算)。一个 batch 被拆分为8个 micro batch。蓝色代表前向运算,绿色代表后向运算。可以看到 GPipe 是先执行完所有 micro batch 的前向,然后再执行所有 micro batch 的后向,然后在 pipeline flush 处进行一次同步。注意这里假设了后向的计算量是前向的2倍。上图中灰色的部分就是设备空闲的情况,在本文中被叫做 pipeline bubble(流水线气泡)。显然这些气泡会降低设备的 MFU。
在这里插入图片描述

PipeDream

PipeDream 的 1F1B(One Forward pass followed by One Backward pass)策略就可以解决缓存 activation 的份数问题,使得 activation 的缓存数量只跟阶段(stage)数相关,从而进一步节省显存。
GPipe需要等所有的microbatch前向传播完成后,才会开始反向传播。PipeDream则是当一个microbatch的前向传播完成后,立即进入反向传播阶段。 理论上,反向传播完成后就可以丢弃掉对应microbatch缓存的激活。由于PipeDream的反向传播完成的要比GPipe早,因此也会减少显存的需求。
下图是PipeDream的调度图,4个GPU和8个microbatchs。蓝色的方块表示前向传播,绿色表示反向传播,数字则是microbatch的id。PipeDream在bubbles上与GPipe没有区别,但是由于PipeDream释放显存的时间更早,因此会降低对显存的需求。
在这里插入图片描述

1F1B 调度(schedule)模式

https://zhuanlan.zhihu.com/p/653860567
上面讲述了 PipeDream,在使用 1F1B 策略时,存在两种调度模式:非交错调度和交错式调度。具体如下图所示,上面的部分显示了默认的非交错式调度(non-interleaved schedule),底部显示的是交错式调度(interleaved schedule)。
在这里插入图片描述
非交错式调度(PipeDream )
非交错式调度可分为三个阶段。第一阶段是热身阶段,处理器进行不同数量的前向计算。在接下来的阶段,处理器进行一次前向计算,然后是一次后向计算。最后一个阶段处理器完成后向计算。
上面的讲到微软的 PipeDream 就是使用非交错式 1F1B 调度。虽然,这种调度模式比 GPipe 更节省内存。然而,它需要和 GPipe 一样的时间来完成一轮计算。

交错式调度(virtual pipeline)
在交错式调度中,每个设备可以对多个层的子集(称为模型块)进行计算,而不是一个连续层的集合。具体来看,在之前非交错式调度中,设备1拥有层1-4,设备2拥有层5-8,以此类推;但在交错式调度中,设备1有层1,2,9,10,设备2有层3,4,11,12,以此类推。在交错式调度模式下,流水线上的每个设备都被分配到多个流水线阶段(虚拟阶段,virtual stages),每个流水线阶段的计算量较少。这种模式既节省内存又节省时间。但这个调度模式要求 micro-batch 的数量是流水线阶段(Stage)的整数倍。英伟达 Megatron-LM 的流水线并行相关的论文(Efficient Large-Scale Language Model Training on GPU Clusters Using Megatron-LM)virtual pipeline中采用了非交错式 1F1B 调度。

virtual pipeline

PipeDream(交错式1F1B)-Megatron-LM,https://zhuanlan.zhihu.com/p/653860567
Megatron-LM 基于 PipeDream-Flush 提出了一个小的Trick:交错式 1F1B 调度,而交错式 1F1B 调度也是 Megatron-LM 论文(Efficient Large-Scale Language Model Training on GPU Clusters Using Megatron-LM),virtual pipeline)中最主要的一个创新点。
传统的流水线并行通常会在一个设备(Device)上放置几个连续的模型层(如:Transformer层)。但 Megatron 这篇论文采用虚拟流水线(virtual pipeline),进行交错式1F1B并行。在设备数量不变的情况下,分出更多的流水线阶段(pipeline stage),以更多的通信量,换取流水线Bubble比率降低。
例如,之前如果每个设备有 4 层(即设备 1 有 1 – 4 层,设备 2 有 5 – 8 层,依此类推),现在我们可以让每个设备对两个模型块执行计算(每个模型块有 2 层) ,即设备 1 有第 1、2、9、10 层; 设备 2 有第 3、4、11、12 层,依此类推。 通过这种方案,流水线中的每个设备都被分配多个流水线阶段(与以前相比,每个流水线阶段的计算量更少)。
此外,该方案要求一个小批次中的微批次数量是管道并行大小(流水线中的设备数量)的整数倍。 例如,对于 4 个设备,一个小批次中的微批次数量必须是 4 的倍数。那虚拟流水线(virtual pipeline)是怎么做到的呢?对照上面示例图举例说明,若网络共16层(编号 0-15),4 个 Device,前述谷歌的 GPipe 和微软的 PipeDream 是分成 4 个 stage, 按编号 0-3 层放 Device1,4-7层放 Device2 ,以此类推。英伟达的 virtual pipeline 则是按照文中提出的 virtual_pipeline_stage 概念减小切分粒度,以 virtaul_pipeline_stage=2 为例,将 0-1 层放 Device1, 2-3 层放在 Device2,…,6-7 层放到 Device4,8-9 层继续放在 Device1,10-11 层放在 Device2,…,14-15 层放在 Device4。

相对于 GPipe,虽然 PipeDream 降低了内存的使用,但是其空泡(Bubble)率并没有降低。Megatron-LM的流水线并行方案中提出了交错式1F1B调度策略。进一步降低空泡(Bubble)率。但是,带来了额外的通信成本。其论文中提到了使用 IB 网络来缓解额外的通信影响。

4、Megatron-LM对比

1). Megatron-LM-1
利用了张量并行和数据并行。

2). Megatron-LM-2
Megatron 2 在 Megatron 1 的基础上新增了 pipeline 并行,提出了 virtual pipeline:1F1B-interleaving,成为和 DeepSpeed 类似的 3D 并行的训练框架,新增的 pipeline 并行就是本文主要所阐述的内容。另外 Megatron-2 论文中还提及了一些通信优化的小 trick,本质是增加本地的 io 操作和通信,从而降低低带宽网络的通信量。
内存占用角度:主要是 G-pipe 到 PipeDream 的进化完成的,通过及时安排反向过程,将前向激活值释放掉,避免积累太多激活值占用内存,提高了模型并行的能力。
空泡比率角度:空泡比率的提升主要从 1F1B 到 1F1B-interleaving 的进化得来。pipeline 并行的一个基本规律就是 pipeline 流水的级数越多,overhead 就越小。

3). Megatron-LM-3
增加了 Sequence Parallelism、Selective Activation Recomputation 和 Checkpointing Skipping 三个 feature。
链接:https://blog.csdn.net/c9Yv2cf9I06K2A9E/article/details/130570164

5、Megatron-DeepSpeed

DeepSpeed团队通过将“下面第一项与后面三项相结合”,开发了一种基于3D并行的实现,这就是Megatron-Deepspeed,它使得千亿级参数量以上的大规模语言模型比如BLOOM的分布式训练变得更简单、高效和有效

Megatron-LM中的张量并行(Tensor Parallelism,可以理解为模型并行的一种)
每个张量都被分成多个块,因此张量的每个分片都位于其指定的 GPU 上,而不是让整个张量驻留在单个 GPU 上。在处理过程中,每个分片在不同的 GPU 上分别并行处理,结果在步骤结束时同步。这就是所谓的水平并行,因为是做的水平拆分
零冗余优化器 (Zero Redundancy Optimizer,简称ZeRO,是微软DeepSpeed库的核心)
也执行与 TP 相类似的张量分片,但整个张量会及时重建以进行前向或反向计算,因此不需要修改模型。它还支持各种卸载技术以补偿有限的 GPU 内存
数据并行(Data Parallelism)
相同的设置和模型被复制多份,每份每次都被馈送不同的一份数据。处理是并行完成的,所有份在每个训练步结束时同步
管道并行(也称流水线并行,Pipeline Parallelism)
模型在多个 GPU 上垂直 (即按层) 拆分,因此只有一个或多个模型层放置在单个 GPU 上。每个 GPU 并行处理流水线的不同阶段,并处理 batch 的一部分数据
链接:https://blog.csdn.net/v_JULY_v/article/details/132462452
在这里插入图片描述

6、DeepSpeed、Megatron-LM与FasterTransformer

https://cloud.baidu.com/article/2707428
在实际应用中,这三个库的选择取决于具体需求和场景。例如,如果需要进行大规模的模型训练,且支持多节点训练,那么Megatron-LM可能是一个不错的选择。如果需要加速推理过程,那么FasterTransformer可能更适合。而如果需要在训练和推理方面都有所提升,那么DeepSpeed可能是一个更好的选择。

7、LLM训练微调框架对比

https://github.com/liguodongiot/llm-action
DeepSpeed Chat:
地址:https://github.com/microsoft/DeepSpeed/tree/master/blogs/deepspeed-chat
简介:该项目提供了一键式RLHF训练框架,只需一个脚本即可实现多个训练步骤,包括SFT,奖励模型微调和基于人类反馈的强化学习(RLHF),此外还实现了DeepSpeed HE,统一的高效混合引擎,达到训练和推理引擎之间的过渡是无缝的。
LLaMA Efficient Tuning:
地址:https://github.com/hiyouga/LLaMA-Efficient-Tuning
简介:该项目提供了易于使用的基于PEFT的LLaMA微调框架,实现了包括全参数,LoRA,QLoRA等的预训练,指令微调和RLHF,并支持LLaMA, BLOOM, Falcon, Baichuan, InternLM等底座模型。
ChatGLM Efficient Tuning:
地址:https://github.com/hiyouga/ChatGLM-Efficient-Tuning
简介:该项目提供了基于PEFT的高效ChatGLM微调,支持LoRA,P-Tuning V2,全参数微调等模式,并适配了多个微调数据集。
bert4torch:
地址:https://github.com/Tongjilibo/bert4torch
简介:该项目提供了一个大模型的训练和部署框架,包含了目前主要的开源大模型,llama系列,chatglm,bloom系列等等,同时还给出了预训练和微调的示例。

2、推理框架

大模型常见推理框架:vLLM、Tensorrt-LLM、DeepSpeed、Text Generation Inference

TensorRT

https://zhuanlan.zhihu.com/p/482473219
https://blog.wanwuguiyi.com/tensorrt-study01/
https://zhuanlan.zhihu.com/p/366713331

一、TensorRT简介

TensorRT是NVIDIA推出的用于高性能深度学习推理的库。它通过优化和裁剪深度学习模型,利用GPU的并行计算能力,实现了比传统推理方式更快速和高效的推理过程。TensorRT支持常见的深度学习框架,如TensorFlow、PyTorch和ONNX等,为开发者提供了灵活的接口和丰富的功能。

二、TensorRT的基本原理

TensorRT在加速深度学习推理过程中主要依靠以下几个核心技术:

  • 模型优化
    TensorRT通过剪枝、量化和融合等技术,对深度学习模型进行优化。其中,剪枝可以去除模型中不必要的权重和连接,减小模型的规模;量化可以将浮点数权重量化为定点数,减少内存占用和计算量;融合可以将多个计算节点合并为一个,减少计算过程中的中间结果。
  • 张量内存管理
    TensorRT使用专门的内存管理器来管理张量(Tensor)的内存,通过内存重用和内存共享等技术,减少内存分配和拷贝的开销,提高内存使用效率。
  • 并行计算
    TensorRT通过并行计算充分发挥GPU的计算潜力。它将模型的计算图划分为多个子图,并利用GPU的多个流(Stream)实现模型的并行计算,提高推理的并行度和效率。

TensorRT 工作流程
在描述 TensorRT 的优化原理之前,需要先了解 TensorRT 的工作流程。首先输入一个训练好的 FP32 模型文件,并通过 parser 等方式输入到 TensorRT 中做解析,解析完成后 engin 会进行计算图优化(优化原理在下一章)。得到优化好的 engine 可以序列化到内存(buffer)或文件(file),读的时候需要反序列化,将其变成 engine以供使用。然后在执行的时候创建 context,主要是分配预先的资源,engine 加 context 就可以做推理(Inference)。
在这里插入图片描述
TensorRT 的优化原理
TensorRT 的优化主要有以下几点:
算子融合(网络层合并):我们知道 GPU 上跑的函数叫 Kernel,TensorRT 是存在 Kernel 调用的,频繁的 Kernel 调用会带来性能开销,主要体现在:数据流图的调度开销,GPU内核函数的启动开销,以及内核函数之间的数据传输开销。大多数网络中存在连续的卷积 conv 层、偏置 bias 层和 激活 relu 层,这三层需要调用三次 cuDNN 对应的 API,但实际上这三个算子是可以进行融合(合并)的,合并成一个 CBR 结构。同时目前的网络一方面越来越深,另一方面越来越宽,可能并行做若干个相同大小的卷积,这些卷积计算其实也是可以合并到一起来做的(横向融合)。比如 GoogLeNet 网络,把结构相同,但是权值不同的层合并成一个更宽的层。
concat 层的消除。对于 channel 维度的 concat 层,TensorRT 通过非拷贝方式将层输出定向到正确的内存地址来消除 concat 层,从而减少内存访存次数。
Kernel 可以根据不同 batch size 大小和问题的复杂度,去自动选择最合适的算法,TensorRT 预先写了很多 GPU 实现,有一个自动选择的过程(没找到资料理解)。其问题包括:怎么调用 CUDA 核心、怎么分配、每个 block 里面分配多少个线程、每个 grid 里面有多少个 block。
FP32->FP16、INT8、INT4:低精度量化,模型体积更小、内存占用和延迟更低等。
不同的硬件如 P4 卡还是 V100 卡甚至是嵌入式设备的卡,TensorRT 都会做对应的优化,得到优化后的 engine。

三、应用部署

什么模型可以转换为TensorRT
https://zhuanlan.zhihu.com/p/371239130
TensorRT官方支持Caffe、Tensorflow、Pytorch、ONNX等模型的转换(不过Caffe和Tensorflow的转换器Caffe-Parser和UFF-Parser已经有些落后了),也提供了三种转换模型的方式:
使用TF-TRT,将TensorRT集成在TensorFlow中
使用ONNX2TensorRT,即ONNX转换trt的工具
手动构造模型结构,然后手动将权重信息挪过去,非常灵活但是时间成本略高,有大佬已经尝试过了:tensorrtx
不过目前TensorRT对ONNX的支持最好,TensorRT-8最新版ONNX转换器又支持了更多的op操作。而深度学习框架中,TensorRT对Pytorch的支持更为友好,除了Pytorch->ONNX->TensorRT这条路,还有:
torch2trt
torch2trt_dynamic
TRTorch
总而言之,理论上95%的模型都可以转换为TensorRT,条条大路通罗马嘛。只不过有些模型可能转换的难度比较大。如果遇到一个无法转换的模型,先不要绝望,再想想,再想想,看看能不能通过其他方式绕过去。

TensorRT部署相关
部署TensorRT的方式,官方提供了三种:
集成在Tensorflow中使用,比例TF-TRT,这种操作起来比较便捷,但是加速效果并不是很好;
在TensorRT Runtime环境中运行模型,就是直接使用TensorRT;
搭配服务框架使用,最配的就是官方的triton-server,完美支持TensorRT,用在生产环境杠杠的!

使用onnxruntime验证一下模型
一般来说,我们在通过不同框架(Pytorch、TF)转换ONNX模型之后,需要验证一下ONNX模型的准确性,否则错误的onnx模型转成的TensorRT模型也100%是错误的。

ONNX转换为TensorRT模型
ONNX模型转换TensorRT模型还是比较容易的,目前TensorRT官方对ONNX模型的支持最好,而且后续也会将精力重点放到ONNX上面(相比ONNX,UFF、Caffe这类转换工具可能不会再更新了)。目前官方的转换工具TensorRT Backend For ONNX(简称ONNX-TensorRT)已经比较成熟了,开发者也在积极开发,提issue官方回复的也比较快。我们就用上述工具来转一下这个模型。我们不需要克隆TensorRT Backend For ONNX,之前下载好的TensorRT包中已经有这个工具的可执行文件了,官方已经替我们编译好了,只要我们的环境符合要求,是直接可以用的。

vLLM

https://blog.vllm.ai/2023/06/20/vllm.html
https://zhuanlan.zhihu.com/p/642802585

llm的作者们观察到,对于LLM来说,所有输入的令牌都会产生它们的注意力键和值张量,并这些张量会被保存在GPU内存中以生成下一个令牌,这被称为KV缓存。然而,这种缓存的特点是大型的和动态的,例如在LLaMA-13B中,单个序列的KV缓存可能高达1.7GB。更重要的是,其大小取决于序列的长度,这个长度是难以预测和有很大变化的。这种情况对KV缓存的有效管理带来了巨大挑战。实际上,现有的系统由于内存的碎片化和过度预留,浪费了60% - 80%的内存资源。
为了解决这个问题,他们提出了PagedAttention,这是一种新的注意力算法。它受到了虚拟内存和操作系统中的分页思想的启发。与传统的注意力算法不同,PagedAttention在非连续的内存空间中存储连续的键和值。PagedAttention的工作原理是,它将每个序列的KV缓存分成若干块,每块负责固定数量的令牌的键和值。在进行注意力计算时,PagedAttention算法能够高效地识别并获取这些块,从而提高了内存使用的效率。配备 PagedAttention 的 vLLM 重新定义了 LLM 服务中的新技术:它提供的吞吐量比 HuggingFace Transformer 高 24 倍,而无需更改任何模型架构。

1、PagedAttention
背景:
LLM 的推理,最大的瓶颈在于显存。
自回归模型的 keys 和 values 通常被称为 KV cache,这些 tensors 会存在 GPU 的显存中,用于生成下一个 token。
这些 KV cache 都很大,并且大小是动态变化的,难以预测。已有的系统中,由于显存碎片和过度预留,浪费了60%-80%的显存。
实现:
受到操作系统中,虚拟内存和分页经典思想的启发
PagedAttention 允许在不连续的内存空间中存储连续的 keys 和 values。 具体来说,PagedAttention 会将每个序列的 KV cache 划分为块,每个块包含固定数量 tokens 的 keys 和 values。 在注意力计算过程中,PagedAttention 内核有效地识别并获取这些块。
分块之后,这些 KV cache 不再需要连续的内存,从而可以像在操作系统的虚拟内存中一样,更灵活地对这些 KV cache 进行管理。
PagedAttention 对于显存的利用接近理论上的最优值(浪费比例低于4%)。通过对显存进行更好的管理,可以使得单次可以使用更大的 batch size,从而进一步利用 GPU 的并行计算能力。
在这里插入图片描述
2、memory sharing
memory sharing 是 PagedAttention 的另一个关键特性。
当用单个 prompt 产出多个不同的序列时,可以共享计算量和显存。
通过将不同序列的 logical blocks 映射到同一个 physical blocks,可以实现显存共享。
为了保证共享的安全性,对于 physical blocks 的引用次数进行统计,并实现了 Copy-on-Write 机制。
这种内存共享机制,可以大幅降低复杂采样算法对于显存的需求(最高可下降55%),从而可以提升2.2倍的吞吐量。
在这里插入图片描述

# CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 python3 -m vllm.entrypoints.openai.api_server \
# --model "/data/NFS/MODELS/openbuddy-llama2-70b-v10.1-bf16" \
# --host 0.0.0.0 \
# --port 6006 \
# --dtype half \
# --tensor-parallel-size 8 \


#拉取vllm镜像,可以改用docker直接执行(czc),
#只能用docker命令运行,进入容器不行,开启容器默认用了python3
#ENTRYPOINT ["python3" "-m" "vllm.entrypoints.openai.api_server"]
#容器创建时用了启动vllm命令
docker run  --gpus all \
    --name vllm_04_test \
    --rm \
    -v /data/Codes:/data/Codes \
    -v /data/NFS:/data/NFS \
    -p 8021:8000 \
    --ipc=host \
    vllm/vllm-openai:v0.4.1 \
    --model /data/NFS/MODELS/openbuddy-llama2-70b-v10.1-bf16 \
    --tensor-parallel-size 8 \
    --dtype half

docker exec -it test2_vllm  python3 -m vllm.entrypoints.openai.api_server  \
    --model /data/NFS/MODELS/openbuddy-llama2-70b-v10.1-bf16 \
    --tensor-parallel-size 8 \
    --dtype half

vLLM和Tensorrt对比

vLLM
vLLM全称Virtual Large Language Model,由Nvidia开源,旨在降低大模型推理的显存占用。其核心思想是将模型的一部分保存在CPU内存或硬盘上,只将当前计算所需的部分加载到GPU显存中,从而打破GPU显存限制。
vLLM支持PyTorch和FasterTransformer后端,可无缝适配现有模型。使用vLLM,在配备96GB内存+440GB A100的服务器上可运行1750亿参数模型,在配备1.5TB内存+880GB A100的服务器上可运行6万亿参数模型。

Tensorrt-LLM
Tensorrt-LLM是Nvidia在TensorRT推理引擎基础上,针对Transformer类大模型推理优化的框架。主要特性包括:
支持多种优化技术,如kernel融合、矩阵乘优化、量化感知训练等,可提升推理性能
支持多GPU多节点部署,可扩展到万亿规模参数
提供Python和C++ API,易于集成和部署
在Nvidia测试中,基于OPT-30B在A100上的推理,Tensorrt-LLM可实现最高32倍加速。

TensorRT-LLM
英伟达出品必是精品,2023年10月19日英伟达发布了一款专为大模型推理的开源库,它的推理效率比vllm还要好。它专为LLM大模型设计,支持市面上主流的模型,同时也实现了其他推理框架比如vllm的各项推理加速技术,其主要的特点如下:
各种attention版本、in-flight batching(也就是continuous batching)、pagedAttention、张量并行、流水线并行、各种量化技术SQ、AWQ以及新的数据类型FP8的支持。同时结合tensorrt高效的cuda算子、层融合、精度校准和内核选择等技术,使得它的推理效率更为高效。下面简单的介绍一下各种量化技术。http://www.mfbz.cn/a/568764.html

trtllm相对vllm来说还是具有一定的优势的,功能齐全,但是目前trtllm还有些不足,构建引擎的时候需要预先指定max_bs/max_input/max_output之类的,不能动态修改,这可能也是trtllm推理速度优化的如此之快的一个必须的措施,灵活性上有所损失;另外trtllm异步推理的时候不支持topk、topp之类的设置,所以只能是greedy seach解码策略进行文本生成。链接:https://blog.csdn.net/HUSTHY/article/details/137241069

LLM七种推理服务框架总结

https://betterprogramming.pub/frameworks-for-serving-llms-60b7f7b23407
https://zhuanlan.zhihu.com/p/653352979
https://blog.csdn.net/WZZ18191171661/article/details/137937461
在这里插入图片描述
LLM推理有很多框架,各有其特点,下面分别介绍一下表中七个框架的关键点:
1.vLLM[1]:适用于大批量Prompt输入,并对推理速度要求高的场景;
2.Text generation inference[2]:依赖HuggingFace模型,并且不需要为核心模型增加多个adapter的场景;
3.CTranslate2[3]:可在CPU上进行推理;
4.OpenLLM[4]:为核心模型添加adapter并使用HuggingFace Agents,尤其是不完全依赖PyTorch;
5.Ray Serve[5]:稳定的Pipeline和灵活的部署,它最适合更成熟的项目;
6.MLC LLM[6]:可在客户端(边缘计算)(例如,在Android或iPhone平台上)本地部署LLM;
7.DeepSpeed-MII[7]:使用DeepSpeed库来部署LLM;

MLC LLM
https://github.com/mlc-ai/mlc-llm
Machine Learning Compilation for Large Language Models (MLC LLM) 是一个高性能的通用部署解决方案,支持任何大语言模型的原生部署。 MLC LLM支持以下平台和硬件: AMD GPU、 NVIDIA GPU、 Apple GPU、 Intel GPU、 Linux / Win、 macOS、 Web 浏览器、 iOS / iPadOS、 Android。
这个框架是陈天奇(tvm发起者)团队开发的,最大的特性是可以部署到iOS 和 Android 设备上,还能在浏览器上运行SD模型和LLM模型。用Python定义模型。MLC提供各种预定义的体系结构,例如Llama(例如,Llama2、Vicuna、OpenLlama、Wizard)、GPT-NeoX(例如,RedPajama、Dolly)、RNN(例如,RWKV)和GPT-J(例如,MOSS)。模型开发人员可以仅用纯Python定义模型,而不必涉及代码生成和运行时。

  • 26
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值