├── README.md
├── export
├── bert_onnx.py
├── gpt2_onnx.py
├── llama2_onnx.py
├── llama_onnx.py
├── onnx-limited.md
└── vit_onnx.py
├── llama.cpp
└── readme.md
├── tensorrt-llm
├── .gitkeep
├── cutlass
│ ├── .gitkeep
│ └── readme.md
├── flash-attention.md
├── img
│ ├── .gitkeep
│ ├── Continuous-Batching.png
│ ├── GQA.png
│ ├── Static-Batching.png
│ ├── awq-2.png
│ ├── awq.png
│ ├── fmha-2.png
│ ├── fmha.png
│ ├── gptq.png
│ ├── how-to-add-custom-op-2.png
│ ├── how-to-add-custom-op.png
│ ├── how-to-debug.png
│ ├── how-to-use--llama.png
│ ├── how-to-use.png
│ ├── in-flight-batching.png
│ ├── int8-w-o.png
│ ├── mgmn-2.png
│ ├── mgmn.png
│ ├── mmha.png
│ ├── next-hw-sw-2.png
│ ├── next-hw-sw.png
│ ├── oss.png
│ ├── parallel_wall.jpg
│ ├── precision.png
│ ├── ptq.png
│ ├── python-api.png
│ ├── qat.png
│ ├── smooth-q-2.png
│ ├── smooth-q.png
│ └── tp-pp.png
├── mha
│ └── readme.md
├── op_fusion.md
├── python
│ └── export_ln_prenorm_in_encoder.py
├── readme.md
├── transformer.md
└── 工程解读.md
├── transformer-family.md
└── vllm
├── .gitkeep
├── 0.png
├── 1.png
├── 2.png
├── 3.png
├── 4.png
├── 5.png
├── b-1.png
├── b-2.png
├── b-a.png
├── b0.png
├── readme.md
├── shm-0.png
├── shm-1.png
├── shm-2-1.png
├── shm-2-2.png
├── shm-2-3.png
├── shm-3.png
├── shm-4.png
├── shm-5.png
└── shm-6.png
/README.md:
--------------------------------------------------------------------------------
1 | ## LLM 推理加速
2 |
3 | 
4 | |模型组成|方法|备注|
5 | |-------|----|----|
6 | |cnn-based(backbone) + cnn(head)| [tensorrt](https://github.com/lix19937/trt-samples-for-hackathon-cn/blob/master/cookbook/readme_cn.md) 基于TRT,自定义插件完成低效模块的计算,最终仍back到TRT中 |-|
7 | |transformer-based(decoder)| [tensorrt-llm](tensorrt-llm/readme.md)
https://github.com/NVIDIA/TensorRT-LLM
对于无cnn的,如GPT2,不借助onnx解析器,自己搭建网络推理,典型的llama.cpp,llama2.c 这类针对特定结构开发的推理项目,
以及 [vllm](./vllm/readme.md)
https://lilianweng.github.io/posts/2023-01-10-inference-optimization/#distillation |- |
8 | |cnn + transformer| tensorrt[plugin] + tensorrt-llm
如[detr3d](https://github.com/lix19937/tensorrt-insight/tree/main/plugin/detr3d/decoder), vit 需要tensorrt[plugin] 与 tensorrt-llm 一起使用,实现最优效果| -|
9 |
10 | -------------------------------
11 | https://developer.nvidia.com/blog/mastering-llm-techniques-inference-optimization/
12 |
13 | ## LLM Inference --算法与工程的协作
14 |
15 | |方向/技术点|说明 |
16 | |----------|----|
17 | |Inference算法部分| Transformer inference过程及加速原理|
18 | |解码策略及调参| GreedySearch、BeamSearch、Sampling、top_k、top_p、temperature、no_repeated_ngram_size等优化|
19 | |多机多卡的GPU集群分布式解码,并行(Tensor/Pipeline/MoE Expert parallelism)| 集群的搭建、不同机器以及卡的高效通信等|
20 | |高并发处理和优化|负载均衡,batch_size调优等|
21 | |系统底层相关|不同显卡型号、底层GPU驱动、内存管理、算子等|
22 | |其他工程相关|GPU集群管理,稳定性,日常维护等|
23 |
24 | ### Inference优化指标
25 |
26 | |指标 | 说明 |
27 | |---- | ----|
28 | | Latency | 关注服务体验,也就是返回结果要快,用户体验好。
延时,主要从用户的视角来看,也就是用户提交一个prompt,然后得到response的时间。特殊情况batch_size=1只给一个用户进行服务,Latency是最低的。计算方法为生成一个token所需要的单位时间数,如16 ms/token。 实时场景非常注重,如自动驾驶|
29 | | Throughput |关注系统成本,高Throughput则系统单位时间处理的量就大,系统利用率高,但是会影响latency。
吞吐率,主要是从系统的角度来看,单位时间内能处理的tokens数,如16 tokens/sec。扩大Throughput的方法一般就是提升Batch_size,也就是将一个一个用户的请求由之前的串行改为并行。 并发高场景,如互联网 |
30 |
31 | 高并发时,把用户的prompt合并扩大batch_size能提升Throughput,但会一定程度上损害每个用户的 Latency,因为以前只计算一个请求,现在合并计算多个请求,每个用户等待的时间就长了。从实际的测试结果可以看到,Throuput随着batch_size的增大而增大,但是 Latency是随着增大的,当然 Latency 在可接受范围内就是ok的。因此这两个指标需要 **trade-off** 。
32 | 简单计算,对于一次请求来说:
33 | ```py
34 | latency=batch_size * output_sequence_length / Throughput
35 | ```
36 | 提升batch_size会提升Throughput,但Throughput与batch_size并不是同比例增大的,因此导致Latency随着batch_size增大而增大。
37 |
38 | ### 优化方法
39 |
40 | |指标| 方法|
41 | |--- |--- |
42 | |Latency|优化底层的OP算子(高效kernel,如FMHA)、矩阵优化、并行、更高效的C++解码等,如FasterTransformer以及DeepSpeed。针对Latency的优化可以提升Throughput,但没有直接用batch_size提升的更显著。
**量化技术**,如gptq |
43 | |Throughput|主要是**KV Cache存取优化**,将transformer attention计算中的Key和Value张量集合缓存下来,避免每输出一个token都重复计算。本质是降低显存开销,从而可以提升batch size。这方面工作相对多一些,如**offloading技术**,就是如何高效利用第三方存储CPU/DRAM/Disk,使得GPU显存能空出来进而增大batch_size。
如vLLM中的 **PagedAttention** 技术就是借鉴OS中的分页以及虚拟存储思想实现显存动态分配,也能节省很多显存空间。
如**continuous batching**,变传统的static batch为动态可复用的batch分配,同样也能尽可能扩大batch_size,进而提升Throughput。|
44 |
45 | ### Inference过程
46 |
47 | |阶段 | 说明|
48 | |----| ----|
49 | |Prefill Phase|预处理/Encoding。计算并缓存每一层的key和value,其他的不需要缓存。每一个请求的prompt需要经过这个阶段,**它只计算一次,是并行计算的**。这个缓存称为KV Cache,KV Cache是整个解码过程中最为核心关键的一块。|
50 | |Decoding Phase|生成新token阶段,它是串行的,也就是decode one by one。它用上一步生成的token,称为当前token放到input中,然后生成下一个token。具体包括两步,一是Lookup KV Cache计算并输出当前token最终embedding用来预测下一个token,二是缓存计算过程中得到的当前token在每一层的key和value,update到第一阶段Prefill Phase中的KV Cache中。|
51 |
52 | 这样划分(2个阶段 Prefill Phase和 Decoding Phase(见FlexGen))的好处是,每次解码,不需要对整个网络全部进行计算,`相当于计算复杂度从O(n^3)变为O(n)了`。Prefill Phase只需要计算一次,核心就是GPT-style的transformer是单向的,而不是双向的。每一个token只与它前面的tokens有关系,其key,value也只与它前面的tokens有关系,因此可以只计算一次且可以并行。后面decoding phase就很快了,避免了重复计算。整个的开销就只有key-value cache的update以及look-up的时间。
53 | 有文章里面提出LLM inference is memory-IO bound, not compute bound。从下面的量化分析来看确实如此。
54 |
55 | ### Inference量化分析
56 | Inference的核心是KV Cache,以FP16为例,其对显存的占用量化分析如下。
57 |
58 | 其对显存占用分为两块,一是Weights、二是KV Cache。
59 | ```
60 | Weights占用大约为layer_num * ( 8 * hidden_size * hidden_size + 4 * hidden_size * MLP_hidden_size )。 head_num=8
61 | KV Cache的占用为4 * batch_size * layer_num * hidden_size * ( input_length + output_length )。
62 | ```
63 | 以OPT-175B 为例(layer_num = 96, hidden_size = 12288, MLP_hidden_size = 49152,batch_size=512,input_length=512, output length=32)。
64 |
65 | Weights差不多占用 325G, KV cache 差不多占用 1.2T。对内存消耗是非常惊人。里面唯一可以调节的参数是batch_size,显存占用基本与batch_size呈正比关系。显存的大小限制了batch_size,而batch_size的大小就限制了Throughput。因此就有很多加速工作就是想办法节省显存,进而扩大batch_size。
66 |
67 | ### 一些主流加速框架
68 |
69 | | 名称| 出品方| 主打| 方法 | 备注 |
70 | | ----|------| ----| ---- | -------|
71 | | FasterTransformer| Nvidia | Latency| 90%的时间消耗在12层Transformer的前向计算上,总结优化点如下:https://zhuanlan.zhihu.com/p/79528308
为了减少kernel调用次数,将除了矩阵乘法的kernel都尽可能合并(这个可能是主要的)
针对大batch单独进行了kernel优化
支持选择最优的矩阵乘法(启发式搜索与cutlass)
在使用FP16时使用half2类型,达到half两倍的访存带宽和计算吞吐
优化gelu、softmax、layernorm的实现以及选用rsqrt等
使用硬件加速的底层函数,如__expf、__shfl_xor_sync | - |
72 | |DeepSpeed|微软|Latency和 Throughput| 优化Latency:a multi-GPU inference solution.
parallelism:Tensor parallelism、Pipeline parallelism、Expert Parallelism(MoE)。对多机多卡之间的通信带宽要求较高
communication optimization
optimized sparse kernels
优化Throughput:Zero-Inference也用到了offloading技术
如何结合GPU显存以及其他外部存储设备如DRAM、NVMe等加载大模型,问题变为How to apportion GPU memory among model weights, inference inputs and intermediate results
然后可以接受大的batch size,进而提升Throughput。| - |
73 | |llama.cpp|ggerganov| Latency| offloading、高效C++解码
面向消费级CPU/GPU的Inference框架,主打易用性,CPU支持
GPU多核计算能力:通过调用CUDA、OpenCL等API,来利用GPU的并行能力。
CPU SIMD和多核:单指令多数据SIMD在x86上有SSEx和AVX等指令,在ARM上有NEON和SVE,都广泛被使用,也有库通过OpenMP再叠加多核能力。| -|
74 | |vLLM |UC Berkeley| Throughput| paged attention,动态分配K-V Cache,提升Batch_size
KV cache占用大量GPU内存,一个13B模型每个输出token对应的KV张量,需要800KB,而最长输出长度2048个token的话,一个请求就需要1.6GB显存。因此vLLM引入类似操作系统中的分页机制,大幅减少了KV cache的碎片化,提高性能。 | - |
75 | |FlexGen |Stanford/UC Berkeley/CMU/META | Throughput| 在有限资源情况下如何高效利用CPU/Disk以提升Throughput | - |
76 | |Hugging Face pipeline Accelerate |HuggingFace | Latency| distributed Inference (https://huggingface.co/docs/accelerate/usage_guides/distributed_inference)| - |
77 |
78 | -------------------------------------------------------
79 |
80 | 要想最大化提升推理的性能,必须得先了解机器的算力资源以及其峰值算力,优化的过程其实就是不断逼近峰值算力的过程。本文我们仅讨论使用GPU进行推理的场景。图1 中是A10的核心参数,从右侧SPECIFICATIONS中可以看到其FP32最大算力是31.2TFLOPS, Memory BandWidth为600GB/s, 但是这个数值是如何得来的呢?
81 | ```
82 | 峰值算力公式:单核单周期计算次数 × 处理核(cuda core)个数 × 主频
83 | ```
84 | 比如A10: 2*1.7x10^9*9216/10^12=31.2TFLOPS
85 | ```
86 | 峰值带宽公式:内存主频 x 位宽x 2/ 8
87 | ```
88 | 比如A10:6251x10^6X384x2(DDR)/8=600GB/s
89 |
90 | 从以上公式可以看出,必须所有的cuda core同时参与计算才可以达到峰值算力,这也给我们优化程序提供了思路,只有尽可能的提升cuda core的使用率,才可以更加的逼近峰值算力。不过影响程序的可能不仅是算力,还有可能是IO,很多时候会因为IO提前到达峰值而导致算力资源没有数据可算,这时就需要分析我们的程序是计算约束还是访存约束了。
91 |
92 | ## 计算约束or 内存约束
93 |
94 | 如何判断程序是compute-bound还是memory-bound。假设一个函数的执行通常经过以下流程:
95 | 1)从memory中读取input。2)执行算术运算。3)将output写回memory
96 | 
97 |
98 | 看看深度神经网络的一些具体例子,如下表1所示。对于这些例子,我们将比较在V100上算法的算术强度与操作数与字节比. V100的峰值数学运算速率为125 FP16 Tensor TFLOPS,片外存储器带宽约为900 GB / s,片上L2带宽为3. 1 TB / s,使其操作数与字节比率在40和139之间,取决于操作数据的来源(片上或片外存储器)。
99 | 
100 |
101 | 如表所示,许多常见操作的**算术强度**都很低,有时仅对从内存读取并写入内存的每个2字节元素执行一个操作。请注意,这种分析方法是一种简化,因为我们只计算所使用的算法运算。实际上,函数还包含算法中没有明确表示的操作指令,如内存访问指令、地址计算指令、控制流指令等。
102 |
103 | 算术强度和操作:字节比分析假设工作负载足够大,足以使给定处理器的数学和内存管道饱和。但是,如果工作负载不够大,或者没有足够的并行性,则处理器的利用率将不足,性能将受到延迟的限制。例如,考虑启动一个线程,该线程将访问16个字节并执行16000个数学运算。虽然算术强度为1000 FLOPS/B,并且在V100 GPU上的执行应该受到数学限制,但仅创建一个线程严重利用GPU不足,几乎所有的数学管道和执行资源都处于空闲状态。此外,算术强度计算假设从存储器访问输入和输出恰好一次。算法实现多次读取输入元素并不罕见,这将显著地降低运算强度。
104 |
105 | DNN中到底哪些算子是计算约束的,哪些又是内存约束的呢?
106 | Elementwise 类型的算子,比如Relu、sigmoid, tanh, Reduction类型的算子比如 pooling、softmax、batchnorm等都属于memory-bound型
107 | 对于卷积、全连接这些,当batch size比较小时也都是memory-bound的。也就是说神经网络的大部分层都是memory-bound,而batch size可以有效减少memory io次数,所以推理时增加batch size可以显著提升吞吐量。
108 |
109 | ## 主流优化方案的底层原理
110 |
111 | + 算子融合。不管是tensorrt、fastertransformer、还是tensorflow、onnx,在图优化阶段都会有算子融合的优化手段,融合后的算子,其计算量并没有减少,但是其的确可以提升模型的性能,为什么呢,这要从cuda程序的执行来说了,假如有A、B、C三个kernel代表三个算子,他们的执行顺序为A->B->C, kernel函数的执行是在gpu上计算的,但是kernel函数的启动是由cpu控制。每执行一个kernel,cpu需要调用cuda driver来执行LaunchKernel的操作,今年GTC2023,英伟达介绍SwinTransformer里有提到,Launch Kernel之间会存在1us+的开销,如果将A\B\C合成一个算子,那么可以减少两次kernel launch的时间。另外kernel函数的输入和输出都是暂存于DRAM(也就是全局内存中),拿最常见的conv+bn+relu来说,conv算子执行完之后需要把tensor写回DRAM,bn算子再从DRAM中读取tensor进行操作,之后再写回DRAM,接着relu再次从DRAM中读取bn算子写回的tensor,将A、B、C三个算子融合后,conv的执行结果无需写回DRAM中,将在寄存器或者L1 Cache/shared memory中直接参与bn的计算,L1 Cache的带宽是DRAM的10倍以上,所以算子融合可以大幅减少DRAM的访存次数,进而提升模型性能。
112 | + 模型量化。模型量化可以降低模型参数占用显存的大小,但模型量化为什么可以多于两倍的性能提速呢。这需要从两个方面来解释,第一,比如由FP32精度量化到FP16精度,相同的访存带宽下可以读写两倍的操作数,同时一个FP32 cuda core也可以一次操作两个FP16的计算,第二,从volta架构以后,nvidia gpu引入了tensor core,这是转为矩阵计算提供的专门硬件,其性能是cuda core的数倍(可以参考:模型推理场景该如何选型GPU - 知乎 (zhihu.com))。然而大部分神经网络的算子其内部多为一些GEMM操作,在使用低精度推理时都可以用上tensor core,所以模型量化效果会非常显著。
113 | + batch推理、多cuda流并行、并实例并行。这三个放在一块说主要是因为他们都可以同时处理多条请求,但是他们的底层原理并不一致。
114 | 
115 | + FlashAttention是一种创新的注意力计算方法,旨在提高计算效率、节省显存,并降低IO感知。这种方法有效地缓解了传统注意力机制在计算和内存管理方面的问题。FlashAttention并没有减少计算量FLOPs,但其创新之处在于,从IO感知的角度出发,减少了HBM(高带宽存储器)的访问次数。这种优化策略不仅提高了计算效率,还显著减少了计算时间的总体耗费。在论文中,作者使用了"wall-clock time"这个词,该词综合考虑了GPU运行耗时和IO读写阻塞时间。而FlashAttention通过**运用tiling技术和算子融合**,有效地降低了HBM的访问次数,从而显著减少了时钟时间。FlashAttention之所以能够实现高效的优化,是因为注意力操作是一种memory-bound操作。对于这类操作,减少HBM(DRAM)的访问次数是最有效的优化手段。因此,FlashAttention为解决注意力机制的计算效率和内存管理问题提供了一种新颖且实用的解决方案。
116 |
117 | ## gpu角度下dnn性能
118 | [understand-perf ](https://docs.nvidia.com/deeplearning/performance/dl-performance-gpu-background/index.html#understand-perf)
119 | 解读
120 | https://docs.nvidia.com/deeplearning/performance/dl-performance-gpu-background/index.html
121 |
122 |
123 | https://zhuanlan.zhihu.com/p/649640010
124 |
125 |
126 |
127 |
128 |
--------------------------------------------------------------------------------
/export/bert_onnx.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/export/gpt2_onnx.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/export/llama2_onnx.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/export/llama_onnx.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/export/onnx-limited.md:
--------------------------------------------------------------------------------
1 |
2 | 对于大模型,一般采用 `参数` 和 `结构` 分离
3 |
4 | |graph| data/struct|
5 | |---|---|
6 | |  ||
7 |
8 | ## Ref
9 | https://github.com/onnx/onnx/issues/3275
10 | https://github.com/onnx/onnx/blob/main/docs/PythonAPIOverview.md#Loading%20An%20ONNX%20Model%20with%20External%20Data
11 | https://blog.csdn.net/u013701860/article/details/130337446?spm=1001.2014.3001.5502
12 |
--------------------------------------------------------------------------------
/export/vit_onnx.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/llama.cpp/readme.md:
--------------------------------------------------------------------------------
1 | https://developer.nvidia.com/zh-cn/blog/optimizing-llama-cpp-ai-inference-with-cuda-graphs/
2 |
3 | https://github.com/ggerganov/llama.cpp/issues/6763
4 |
5 |
6 | https://triton-lang.org/main/getting-started/tutorials/index.html
7 |
--------------------------------------------------------------------------------
/tensorrt-llm/.gitkeep:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/tensorrt-llm/cutlass/.gitkeep:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/tensorrt-llm/cutlass/readme.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | https://zhuanlan.zhihu.com/p/677616101
4 |
--------------------------------------------------------------------------------
/tensorrt-llm/flash-attention.md:
--------------------------------------------------------------------------------
1 | + Execution Model
2 | GPUs have a massive number of threads to execute an operation (called a kernel).
3 | `Each kernel loads inputs from HBM to registers and SRAM`, computes, then writes outputs to HBM.
4 |
5 | + Performance characteristics
6 | Depending on the balance of computation and memory accesses, operations
7 | can be classified as either compute-bound or memory-bound. This is commonly measured by the
8 | arithmetic intensity [85], which is the `number of arithmetic operations per byte of memory access`.
9 |
10 | + Compute-bound
11 | the time taken by the operation is determined by how many arithmetic operations there
12 | are, while time accessing HBM is much smaller. Typical examples are matrix multiply with large inner
13 | dimension, and convolution with large number of channels.
14 | 含有大量内乘的矩阵乘法,含有大量通道的卷积
15 |
16 | + Memory-bound
17 | the time taken by the operation is determined by the number of memory accesses, while
18 | time spent in computation is much smaller. Examples include most other operations: `elementwise (e.g.,
19 | activation, dropout), and reduction (e.g., sum, softmax, batch norm, layer norm)`.
20 |
21 | + Kernel fusion
22 | The most common approach to accelerate memory-bound operations is kernel fusion: if there are multiple operations applied to the same input, the input can be loaded once from HBM, instead of multiple times for each operation. Compilers can automatically fuse many elementwise operations,However, in the context of model training, the intermediate values still need to be written to HBM to save for the backward pass, reducing the effectiveness of naive kernel fusion.
23 |
24 |
25 | 核心思想:传统减少HBM的访问,将QKV切分为小块后放入SRAM中
26 | 核心方法:tiling, recomputation
27 |
28 | softmax操作是row-wise的,即每行都算一次softmax,所以需要用分块计算softmax。
29 | 原始softmax数值不稳定,为了数值稳定性,FlashAttention采用safe softmax
30 | ```
31 | 上溢出
32 | 一种严重的误差是上溢出overflow:当数值非常大,超过了计算机的表示范围时,发生上溢出。
33 |
34 | 当所有的xi 都等于常数c时,考虑 c 是一个非常大的正数(如20000,或比如趋近正无穷),
35 | 则exp^(xi) 趋于 无穷大,分子分母均会上溢出。
36 |
37 | 下溢出
38 | 一种严重的误差是下溢出underflow:当接近零的数字四舍五入为零时,发生下溢出。
39 | 许多函数在参数为零和参数为一个非常小的正数时,行为是不同的。如:对数函数要求自变量大于零,除法中要求除数非零。
40 |
41 | 当所有的xi 都等于常数c时,考虑 c 是一个非常大的负数(如-20000,或比如趋近负无穷),
42 | 则exp^(xi) 趋于 0,此时 softmax分母趋于0,下溢出。
43 | ```
44 |
45 | FlashAttention算法的目标:在计算中减少显存占用,从O(N*N) 大小降低到线性,这样就可以把数据从HBM 加载到SRAM中,提高IO速度。
46 |
47 | 解决方案:传统Attention在计算中需要用到Q,K,V去计算S,P两个矩阵,FlashAttention引入softmax中的统计量( , ℓ),结合output O和在SRAM中的Q,K,V块进行计算。
48 |
49 | https://zhuanlan.zhihu.com/p/669926191
50 |
--------------------------------------------------------------------------------
/tensorrt-llm/img/.gitkeep:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/tensorrt-llm/img/Continuous-Batching.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/Continuous-Batching.png
--------------------------------------------------------------------------------
/tensorrt-llm/img/GQA.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/GQA.png
--------------------------------------------------------------------------------
/tensorrt-llm/img/Static-Batching.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/Static-Batching.png
--------------------------------------------------------------------------------
/tensorrt-llm/img/awq-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/awq-2.png
--------------------------------------------------------------------------------
/tensorrt-llm/img/awq.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/awq.png
--------------------------------------------------------------------------------
/tensorrt-llm/img/fmha-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/fmha-2.png
--------------------------------------------------------------------------------
/tensorrt-llm/img/fmha.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/fmha.png
--------------------------------------------------------------------------------
/tensorrt-llm/img/gptq.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/gptq.png
--------------------------------------------------------------------------------
/tensorrt-llm/img/how-to-add-custom-op-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/how-to-add-custom-op-2.png
--------------------------------------------------------------------------------
/tensorrt-llm/img/how-to-add-custom-op.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/how-to-add-custom-op.png
--------------------------------------------------------------------------------
/tensorrt-llm/img/how-to-debug.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/how-to-debug.png
--------------------------------------------------------------------------------
/tensorrt-llm/img/how-to-use--llama.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/how-to-use--llama.png
--------------------------------------------------------------------------------
/tensorrt-llm/img/how-to-use.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/how-to-use.png
--------------------------------------------------------------------------------
/tensorrt-llm/img/in-flight-batching.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/in-flight-batching.png
--------------------------------------------------------------------------------
/tensorrt-llm/img/int8-w-o.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/int8-w-o.png
--------------------------------------------------------------------------------
/tensorrt-llm/img/mgmn-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/mgmn-2.png
--------------------------------------------------------------------------------
/tensorrt-llm/img/mgmn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/mgmn.png
--------------------------------------------------------------------------------
/tensorrt-llm/img/mmha.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/mmha.png
--------------------------------------------------------------------------------
/tensorrt-llm/img/next-hw-sw-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/next-hw-sw-2.png
--------------------------------------------------------------------------------
/tensorrt-llm/img/next-hw-sw.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/next-hw-sw.png
--------------------------------------------------------------------------------
/tensorrt-llm/img/oss.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/oss.png
--------------------------------------------------------------------------------
/tensorrt-llm/img/parallel_wall.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/parallel_wall.jpg
--------------------------------------------------------------------------------
/tensorrt-llm/img/precision.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/precision.png
--------------------------------------------------------------------------------
/tensorrt-llm/img/ptq.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/ptq.png
--------------------------------------------------------------------------------
/tensorrt-llm/img/python-api.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/python-api.png
--------------------------------------------------------------------------------
/tensorrt-llm/img/qat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/qat.png
--------------------------------------------------------------------------------
/tensorrt-llm/img/smooth-q-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/smooth-q-2.png
--------------------------------------------------------------------------------
/tensorrt-llm/img/smooth-q.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/smooth-q.png
--------------------------------------------------------------------------------
/tensorrt-llm/img/tp-pp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/tensorrt-llm/img/tp-pp.png
--------------------------------------------------------------------------------
/tensorrt-llm/mha/readme.md:
--------------------------------------------------------------------------------
1 | https://github.com/alpha0422/mha/tree/main
2 |
--------------------------------------------------------------------------------
/tensorrt-llm/op_fusion.md:
--------------------------------------------------------------------------------
1 |
2 | # 算子融合
3 |
4 | ## 有依赖的融合
5 | 减少了访存-内存墙
6 |
7 | 从合并难度的角度,算子又被分为
8 | + pointwise(elementwise)
9 | + reduction
10 | + 计算密集型Compute-bound,以下称CB,如matmul和convolution
11 | + 访存密集型Memory-bound,以下称MB
12 | elementwise + elementwise, elementwise + reduction, reduction + elementwise, reduction + reduction
13 |
14 | A = relu(B + C)
15 |
16 | 算子融合技术路线:
17 | + 遍历路线:针对特定设备,枚举实现典型的CB+MB形式的融合算子,如Conv+ReLU/Conv+BN+ReLU/Dense+ReLU/Conv+Sum等等,Intel的oneDNN以及国内很多大厂的推理框架走的都是这个路线。
18 | + 规则路线:基于规则实现算子融合,以TVM为例,其将所有算子分为Opaque/Injective/Reduction/Complex-out四类,并设定融合规则形如Complex-out+Injective/Injective+Injective/Injective+Reduction等,以此实现所有符合规则的子图融合。
19 |
20 |
21 |
22 | ## 无依赖的融合
23 | 可能会减少launch kernel时间和重复访存 - 并行墙
24 | 保证计算图执行非CB部分的子图时也能充分利用设备的计算资源,这方面典型的工作是 TASO 和 RAMMER
25 | 将计算过程中互不依赖的低计算量子图打包为一个kernel并行计算以提升资源利用率即识别无计算依赖的算子做并行计算。这里的关键在于如何在避免组合爆炸的前提下对可以并行的子图分组。
26 | 
27 |
28 |
29 | https://arxiv.org/pdf/2108.13342.pdf
30 |
31 | --------------------------------------------
32 |
33 | ## 特殊的layer
34 |
35 | ## sigmoid
36 | 是 elementwise op
37 | 单调函数 多标签分类
38 |
39 | ## softmax
40 | 是 reduction op 多类别分类
41 |
42 | 一般方法是 3次kernel `获得全局最大值 M= max(x_i), S=sum_i(exp(x_i - M)), y_i = x_i /S`
43 | online方法 或 1-pass方法
44 |
45 | 先把全部数据集中到一个线程块,然后在一个线程块内做规约,由此得到全局最大值呢?
46 | 如果这种方法行得通,我们就可以马上利用相同的方法把数据全部集中到一个线程块,然后再一个线程块做sum规约得到全局求和,到此最后在接入更新向量的过程即可。
47 | 整个过程理论上只需要一次kernel就可以完成,同时还可以减少内存的开销
48 |
49 |
50 | ## bn ln
51 | Welford 对数组一次遍历,即可同时得到mean和variance
52 |
53 | ## Ref
54 | https://zhuanlan.zhihu.com/p/561627225
55 | https://zhuanlan.zhihu.com/p/672960528
56 |
--------------------------------------------------------------------------------
/tensorrt-llm/python/export_ln_prenorm_in_encoder.py:
--------------------------------------------------------------------------------
1 |
2 |
3 | import torch
4 | from loguru import logger
5 |
6 | # Each module is a dummy implementation
7 |
8 | class NORM(torch.nn.Module):
9 | def __init__(self):
10 | super().__init__()
11 | self.act = torch.nn.LayerNorm((256,), eps=1e-05, elementwise_affine=True) # --------
12 |
13 | def forward(self, x): # torch.Size([1, 16000, 256])
14 | out = self.act(x)
15 | return out
16 |
17 |
18 | class FFN(torch.nn.Module):
19 | def __init__(self):
20 | super().__init__()
21 | self.act = torch.nn.ReLU() # --------
22 |
23 | def forward(self, x, identity=None, inner_add=True):
24 | out = self.act(x)
25 | if identity is None:
26 | identity = x
27 | if inner_add:
28 | return identity + out
29 | return out
30 |
31 | class SelfAttention(torch.nn.Module):
32 | def __init__(self):
33 | super().__init__()
34 | self.act = torch.nn.GELU() # --------
35 |
36 | def forward(self, x, identity=None, inner_add=True):
37 | out = self.act(x)
38 | if identity is None:
39 | identity = x
40 | if inner_add:
41 | return identity + out
42 | return out
43 |
44 |
45 | class CrossAttention(torch.nn.Module):
46 | def __init__(self):
47 | super().__init__()
48 | self.act = torch.nn.Sigmoid() # --------
49 |
50 | def forward(self, x, identity=None, inner_add=True):
51 | out = self.act(x)
52 | if identity is None:
53 | identity = x
54 | if inner_add:
55 | return identity + out
56 | return out
57 |
58 |
59 | class TransformerBlock(torch.nn.Module):
60 | def __init__(self):
61 | super(TransformerBlock, self).__init__()
62 | self.pre_norm = False
63 | self.operation_order=('self_attn', 'norm', 'cross_attn', 'norm', 'ffn', 'norm')
64 | self.attentions = [SelfAttention(), CrossAttention()]
65 | self.ffns = [FFN()]
66 | self.norms = [NORM(), NORM(), NORM()]
67 |
68 | def forward(self, query):
69 | norm_index = 0
70 | attn_index = 0
71 | ffn_index = 0
72 | identity = query
73 |
74 | for layer in self.operation_order:
75 | # temporal self attention
76 | if layer == 'self_attn':
77 | query = self.attentions[attn_index](
78 | query, identity if self.pre_norm else None)
79 | attn_index += 1
80 | identity = query
81 |
82 | elif layer == 'norm':
83 | query = self.norms[norm_index](query)
84 | norm_index += 1
85 |
86 | # spaital cross attention
87 | elif layer == 'cross_attn':
88 | query = self.attentions[attn_index](
89 | query, identity if self.pre_norm else None)
90 | attn_index += 1
91 | identity = query
92 |
93 | # ffn
94 | elif layer == 'ffn':
95 | query = self.ffns[ffn_index](
96 | query, identity if self.pre_norm else None)
97 | ffn_index += 1
98 |
99 | return query
100 |
101 |
102 | def forward_eq(self, query):
103 | norm_index = 0
104 | attn_index = 0
105 | ffn_index = 0
106 | identity = None
107 |
108 | for layer in self.operation_order:
109 | # temporal self attention
110 | if layer == 'self_attn':
111 | identity = query
112 | query = self.attentions[attn_index](
113 | query, identity if self.pre_norm else None, inner_add=False)
114 | attn_index += 1
115 |
116 | elif layer == 'norm':
117 | query = self.norms[norm_index](query + identity)
118 | norm_index += 1
119 |
120 | # spaital cross attention
121 | elif layer == 'cross_attn':
122 | identity = query
123 | query = self.attentions[attn_index](
124 | query, identity if self.pre_norm else None, inner_add=False)
125 | attn_index += 1
126 |
127 | # ffn
128 | elif layer == 'ffn':
129 | identity = query
130 | query = self.ffns[ffn_index](
131 | query, identity if self.pre_norm else None, inner_add=False)
132 | ffn_index += 1
133 |
134 | return query
135 |
136 | logger.info("start ...")
137 |
138 | model = TransformerBlock()
139 | x = torch.randn(1, 16000, 256, dtype=torch.float32)
140 | t = model.forward(x)
141 | r = model.forward_eq(x)
142 |
143 | ret = torch.equal(t, r)
144 | logger.info(ret)
145 |
--------------------------------------------------------------------------------
/tensorrt-llm/readme.md:
--------------------------------------------------------------------------------
1 |
2 | [transformer 模块的算子间优化](transformer.md)
3 | [transformer 模块的算子内融合](op_fusion.md)
4 | [flash-attention论文解读](flash-attention.md)
5 |
6 |
7 | -----------------------------------------------------------------------------
8 |
9 | TensorRT-LLM 是 NVIDIA 用于做 LLM(Large Language Model)的可扩展推理方案
10 | + 该方案是基于 TensorRT 深度学习编译框架来构建、编译并执行计算图
11 | + 借鉴了许多 FastTransformer 中高效的 Kernels 实现; tensorrt-llm 与fastertransformer的关系 ?
12 | + 利用了 NCCL 完成设备之间的通讯
13 | + 考虑到技术的发展和需求的差异,开发者还可以定制算子来满足定制需求,比如基于 cutlass 开发定制 GEMM
14 |
15 | ## 背景
16 | 当前 LLM 模型推理的主要瓶颈是 GPU 显存资源不足。因此,各类加速框架主要集中于降低 GPU 显存峰值和提高 GPU 使用率两大目标。
17 |
18 | ---------
19 | ## 核心技术
20 | + FMHA kernel
21 | `见下文`
22 | + 量化
23 | `见下文`
24 | + In-Flight Batching
25 | `见下文`
26 | + Graph Rewriting
27 | `TensorRT-LLM 在将 LLM 模型编译为 TensorRT Engines 时会对神经网络进行优化,提升执行效率。`
28 |
29 | -------
30 |
31 | 除了绿色 TensorRT 编译部分和一些涉及硬件信息的 kernels 外,其他部分都是开源的。
32 | 
33 |
34 | -------
35 | TensorRT-LLM 提供了类 Pytorch 的 API 来降低开发者的学习成本,并提供了许多预定义好的模型供用户使用。
36 | 
37 |
38 | -------
39 | 考虑到大语言模型参数规模比较大,有可能单卡放不下,需要多卡甚至多机推理,因此 TensorRT-LLM 还提供了 Tensor Parallelism 和 Pipeline Parallelism 两种并行机制来支持多卡或多机推理。
40 |
41 | 
42 |
43 | -------
44 | TensorRT-LLM 默认采用 FP16/BF16 的精度推理,并且可以利用业界的量化方法,使用硬件吞吐更高的低精度推理进一步推升推理性能。
45 | 
46 |
47 | |类型|说明 | 备注 W weight; A activate |
48 | |----|----| ------|
49 | |W8A8 SQ|INT8, INT8| SmoothQuant 技术 ,模型权重和激活层都降低为 INT8 精度|
50 | |W4A16 |INT4, FP16| 模型权重为 INT4,激活层为 FP16 精度 |
51 | |W8A16 |INT8, FP16| 模型权重为 INT8,激活层为 FP16 精度 |
52 | |W4A16 AWQ|INT4, FP16| AWQ 论文中提到的量化方法 |
53 | |W4A16 GPTQ|INT4, FP16| GPTQ 论文中提到的量化方法 |
54 |
55 | -------
56 | 另外一个特性就是 **FMHA(fused multi-head attention) kernel** 的实现。由于 Transformer 中最为耗时的部分是 self-attention 的计算,因此官方设计了 FMHA 来优化 self-attention 的计算,并提供了累加器分别为 fp16 和 fp32 不同的版本。另外,除了速度上的提升外,对内存的占用也大大降低。提供了基于 flash attention 的实现,可以将 sequence-length 扩展到任意长度。
57 | 
58 |
59 | -------
60 | 如下为 FMHA 的详细信息,其中 MQA 为 Multi Query Attention,GQA 为 Group Query Attention。
61 | 
62 |
63 | Attention 机制用于从序列中提取关键/重要信息,在情感识别、翻译、问答等任务中起着至关重要的作用。Attention 机制按照演进顺序可以分为 MHA(Multi-head Attention)、MQA(Multi-query Attention) 以及 GQA(Group-query Attention)机制。MQA 和 GQA 都是 MHA 的变种。
64 | 
65 |
66 | + MHA 是标准的多头注意力机制,每个 query 存储一份 KV,因此需要使用较多的显存。
67 | + MQA 所有 query 共享一份 KV,推理时容易丢失一些细节信息。
68 | + GQA 将 query 进行分组,组内共享一份 KV,可以有效避免 MHA 和 MQA 的问题。
69 |
70 | TensorRT-LLM 支持 MHA、MQA 及 GQA 方式,可以在 tensorrt_llm.functional.gpt_attention 查看具体实现。
71 |
72 | -------
73 | 另外一个 Kernel 是 MMHA(Masked Multi-Head Attention)。FMHA 主要用在 context phase 阶段的计算,而 MMHA 主要提供 generation phase 阶段 attention 的加速,并提供了 Volta 和之后架构的支持。相比 FastTransformer 的实现,TensorRT-LLM 有进一步优化,性能提升高达 2x。
74 | 
75 |
76 | -------
77 | 另外一个重要特性是**量化技术**,以更低精度的方式实现推理加速。常用量化方式主要分为 PTQ(Post Training Quantization)和 QAT(Quantization-aware Training),对于 TensorRT-LLM 而言,这两种量化方式的推理逻辑是相同的。对于 LLM 量化技术,一个重要的特点是算法设计和工程实现的 co-design,即对应量化方法设计之初,就要考虑硬件的特性。否则,有可能达不到预期的推理速度提升。
78 | 
79 |
80 | -------
81 | TensorRT 中 PTQ 量化步骤一般分为如下几步:
82 | + 首先对模型做量化
83 | + 然后对权重和模型转化成 TensorRT-LLM 的表示
84 | 对于一些定制化的操作,还需要用户自己编写 kernels。常用的 PTQ 量化方法包括 INT8 weight-only、SmoothQuant、GPTQ 和 AWQ,这些方法都是典型的 co-design 的方法。
85 | 
86 |
87 | -------
88 | INT8 weight-only 直接把权重量化到 INT8,但是激活值还是保持为 FP16。该方法的好处就是模型存储2x减小,加载 weights 的存储带宽减半,达到了提升推理性能的目的。这种方式业界称作 W8A16,即权重为 INT8,激活值为 FP16/BF16——以 INT8 精度存储,以 FP16/BF16 格式计算。该方法直观,不改变 weights,容易实现,具有较好的泛化性能。
89 | 
90 |
91 | -------
92 | 第二个量化方法是 SmoothQuant,该方法是 NVIDIA 和社区联合设计的。它观察到权重通常服从高斯分布,容易量化,但是激活值存在离群点,量化比特位利用不高。
93 | 
94 |
95 | -------
96 | SmoothQuant 通过先对激活值做平滑操作即除以一个scale将对应分布进行压缩,同时为了保证等价性,需要对权重乘以相同的 scale。之后,权重和激活都可以量化。对应的存储和计算精度都可以是 INT8 或者 FP8,可以利用 INT8 或者 FP8 的 TensorCore 进行计算。在实现细节上,权重支持 Per-tensor 和 Per-channel 的量化,激活值支持 Per-tensor 和 Per-token 的量化。
97 | 
98 |
99 | -------
100 | 第三个量化方法是 GPTQ,一种逐层量化的方法,通过最小化重构损失来实现。GPTQ 属于 weight-only 的方式,计算采用 FP16 的数据格式。该方法用在量化大模型时,由于量化本身开销就比较大,所以作者设计了一些 trick 来降低量化本身的开销,比如 Lazy batch-updates 和以相同顺序量化所有行的权重。GPTQ 还可以与其他方法结合使用如 grouping 策略。并且,针对不同的情况,TensorRT-LLM 提供了不同的实现优化性能。具体地,对 batch size 较小的情况,用 cuda core 实现;相对地,batch size 较大时,采用 tensor core 实现。
101 | 
102 |
103 | ------
104 | 第四种量化方式是 AWQ。该方法认为不是所有权重都是同等重要的,其中只有 0.1%-1% 的权重(salient weights)对模型精度贡献更大,并且这些权重取决于激活值分布而不是权重分布。该方法的量化过程类似于 SmoothQuant,差异主要在于 scale 是基于激活值分布计算得到的。
105 | 
106 |
107 | 
108 |
109 | ------
110 | 除了量化方式之外,TensorRT-LLM 另外一个提升性能的方式是利用**多机多卡推理**。在一些场景中,大模型过大无法放在单个 GPU 上推理,或者可以放下但是影响了计算效率,都需要多卡或者多机进行推理。
111 | 
112 |
113 | -----------
114 | TensorRT-LLM 目前提供了两种并行策略,Tensor Parallelism (张量并行)和 Pipeline Parallelism (流水线并行)。TP 是垂直地分割模型然后将各个部分置于不同的设备上,这样会引入设备之间频繁的数据通讯,一般用于设备之间有高度互联的场景,如 NVLINK。另一种分割方式是横向切分,此时只有一个横前面,对应通信方式是点对点的通信,适合于设备通信带宽较弱的场景。
115 | 
116 |
117 | 与NVIDIA TensorRT等其他编译器相比,FT 的最大特点是它支持以分布式方式进行 Transformer 大模型推理。
118 | 当每个张量被分成多个块时,就会发生张量并行,并且张量的每个块都可以放置在单独的 GPU 上。在计算过程中,每个块在不同的 GPU 上单独并行处理;最后,可以通过组合来自多个 GPU 的结果来计算最终张量。
119 | 当模型被深度拆分,并将不同的完整层放置到不同的 GPU/节点上时,就会发生流水线并行。
120 |
121 |
122 | --------------
123 | 最后一个要强调的特性是 **In-flight batching**。Batching 是提高推理性能一个比较常用的做法,但在 LLM 推理场景中,一个 batch 中每个 sample/request 的输出长度是无法预测的。如果按照静态batching的方法,一个batch的时延取决于 sample/request 中输出最长的那个。因此,虽然输出较短的 sample/request 已经结束,但是并未释放计算资源,其时延与输出最长的那个 sample/request 时延相同。In-flight batching 的做法是在已经结束的 sample/request 处插入新的 sample/request。这样,不但减少了单个 sample/request 的延时,避免了资源浪费问题,同时也提升了整个系统的吞吐。这是一种优化的调度技术,可以更有效地处理动态负载。它允许 TensorRT-LLM 在其他请求仍在进行时开始执行新请求,从而提高 GPU 利用率。
124 | 传统的 Batching 技术为 Static Batching 的,需要等 Batching 中所有序列推理完成后才能进行下一次批次。下图为一个输出最大 Token 为 8,Batch size 为 4 的推理过程,使用 Static Batching 技术。S3 序列在 T5 时刻就已经完成推理,但是需要等到 S2 序列在 T8 时刻推理完成后才会处理下一个 sequence,存在明显的资源浪费。
125 | 
126 |
127 | In-flight batching 又名 Continuous Batching 或 iteration-level batching,该技术可以提升推理吞吐率,降低推理时延。Continuous Batching 处理过程如下,当 S3 序列处理完成后插入一个新序列 S5 进行处理,提升资源利用率。详情可参考论文 Orca: A Distributed Serving System for Transformer-Based Generative Models。
128 | 
129 |
130 | 
131 |
132 | --------------
133 | ## TensorRT-LLM 的使用流程
134 | TensorRT-LLM 与 TensorRT的 使用方法类似,首先需要获得一个预训练好的模型,然后利用 TensorRT-LLM 提供的 API 对模型计算图进行改写和重建,接着用 TensorRT 进行编译优化,然后保存为序列化的 engine 进行推理部署。
135 | 
136 |
137 | ---------------
138 | 以 Llama 为例,首先安装 TensorRT-LLM,然后下载预训练模型,接着利用 TensorRT-LLM 对模型进行编译,最后进行推理。
139 | 
140 |
141 | ---------------
142 | 对于模型推理的调试,TensorRT-LLM 的调试方式与 TensorRT 一致。由于深度学习编译器,即 TensorRT,提供的优化之一是 layer 融合。因此,如果要输出某层的结果,就需要将对应层标记为输出层,以防止被编译器优化掉,然后与 baseline 进行对比分析。同时,每标记一个新的输出层,都要重新编译 TensorRT 的 engine。
143 | 
144 |
145 | ------------
146 | 对于自定义的层,TensorRT-LLM 提供了许多 Pytorch-like 算子帮助用户实现功能而不必自己编写 kernel。如样例所示,利用 TensorRT-LLM 提供的 API 实现了 rms norm 的逻辑,TensorRT 会自动生成 GPU 上对应的执行代码。
147 | 
148 |
149 | -----------------
150 | 如果用户有更高的性能需求或者 TensorRT-LLM 并未提供实现相应功能的 building blocks,此时需要用户自定义 kernel,并封装为 plugin 供 TensorRT-LLM 使用。示例代码是将 SmoothQuant 定制 GEMM 实现并封装成 plugin 后,供 TensorRT-LLM 调用的示例代码。
151 | 
152 |
153 | LLM 是一个推理成本很高、成本敏感的场景。为了实现下一个百倍的加速效果,需要算法和硬件的共同迭代,通过软硬件之间 co-design 来达到这个目标。硬件提供更低精度的量化,而软件角度则利用优化量化、网络剪枝等算法,来进一步提升性能。
154 |
155 | ## 问答环节
156 | Q1:是否每一次计算输出都要反量化?做量化出现精度溢出怎么办?
157 | A1:目前 TensorRT-LLM 提供了两类方法,即 FP8 和刚才提到的 INT4/INT8 量化方法。低精度如果 INT8 做 GEMM 时,累加器会采用高精度数据类型,如 fp16,甚至 fp32 以防止 overflow。关于反量化,以 fp8 量化为例,TensorRT-LLM 优化计算图时,可能动自动移动反量化结点,合并到其它的操作中达到优化目的。但对于前面介绍的 GPTQ 和 QAT,目前是通过硬编码写在 kernel 中,没有统一量化或反量化节点的处理。
158 |
159 | Q2:目前是针对具体模型专门做反量化吗?
160 | A2:目前的量化的确是这样,针对不同的模型做支持。我们有计划做一个更干净的api或者通过配置项的方式来统一支持模型的量化。
161 |
162 | Q3:针对最佳实践,是直接使用 TensorRT-LLM 还是与 Triton Inference Server 结合在一起使用?如果结合使用是否会有特性上的缺失?
163 | A3:因为一些功能未开源,如果是自己的 serving 需要做适配工作,如果是 triton 则是一套完整的方案。
164 |
165 | Q4:对于量化校准有几种量化方法,加速比如何?这几种量化方案效果损失有几个点?In-flight branching 中每个 example 的输出长度是不知道的,如何做动态的 batching?
166 | A4:关于量化性能可以私下聊,关于效果,我们只做了基本的验证,确保实现的 kernel 没问题,并不能保证所有量化算法在实际业务中的结果,因为还有些无法控制的因素,比如量化用到的数据集及影响。关于 in-flight batching,是指在 runtime 的时候去检测、判断某个 sample/request 的输出是否结束。如果是,再将其它到达的 requests 插进来,TensorRT-LLM 不会也不能预告预测输出的长度。
167 |
168 | Q5:In-flight branching 的 C++ 接口和 python 接口是否会保持一致?TensorRT-LLM 安装成本高,今后是否有改进计划?TensorRT-LLM 会和 VLLM 发展角度有不同吗?
169 | A5:会尽量提供 c++ runtime 和 python runtime 一致的接口,已经在规划当中。之前团队的重点在提升性能、完善功能上,以后在易用性方面也会不断改善。这里不好直接跟 vllm 的比较,但是 NVIDIA 会持续加大在 TensorRT-LLM 开发、社区和客户支持的投入,为业界提供最好的 LLM 推理方案。
170 |
171 | [1] continuous-batching-llm-inference
172 | https://www.anyscale.com/blog/continuous-batching-llm-inference
173 | [2] SmoothQuant技术
174 | https://arxiv.org/abs/2211.10438
175 | [3] AWQ
176 | https://arxiv.org/abs/2306.00978
177 | [4] GPTQ
178 | https://arxiv.org/abs/2210.17323
179 | [5] Orca: A Distributed Serving System for Transformer-Based Generative Models
180 | https://help.aliyun.com/zh/eventbridge/user-guide/transform/?spm=a2c4g.11186623.0.0.501b5750w5RP1Q
181 | [6] MQA(Multi-query Attention)
182 | https://arxiv.org/abs/1911.02150
183 | [7] GQA(Group-query Attention)
184 | https://arxiv.org/abs/2307.09288
185 |
186 |
187 |
--------------------------------------------------------------------------------
/tensorrt-llm/transformer.md:
--------------------------------------------------------------------------------
1 |
2 | ## transformer 模块优化的核心
3 |
4 | + ffn (gemm)
5 |
6 | + mha (softmax gemm)
7 |
8 | + ca
9 |
10 | + ln (pre norm /post norm)
11 | self.operation_order=('self_attn', 'norm', 'cross_attn', 'norm', 'ffn', 'norm')
12 | ```py
13 | for layer in self.operation_order:
14 | # temporal self attention
15 | if layer == 'self_attn':
16 | identity = query # !!!
17 | query = self.attentions[attn_index](
18 | query, identity if self.pre_norm else None, inner_add=False)
19 | attn_index += 1
20 |
21 | elif layer == 'norm':
22 | query = self.norms[norm_index](query + identity) # post norm
23 | norm_index += 1
24 |
25 | # spaital cross attention
26 | elif layer == 'cross_attn':
27 | identity = query # !!!
28 | query = self.attentions[attn_index](
29 | query, identity if self.pre_norm else None, inner_add=False)
30 | attn_index += 1
31 |
32 | # ffn
33 | elif layer == 'ffn':
34 | identity = query # !!!
35 | query = self.ffns[ffn_index](
36 | query, identity if self.pre_norm else None, inner_add=False)
37 | ffn_index += 1
38 |
39 | return query
40 | ```
41 | 详细优化[验证脚本](python/export_ln_prenorm_in_encoder.py)
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/tensorrt-llm/工程解读.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/transformer-family.md:
--------------------------------------------------------------------------------
1 | https://github.com/lix19937/dnn-cookbook/blob/main/doc/transformer.md
2 |
--------------------------------------------------------------------------------
/vllm/.gitkeep:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/vllm/0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/vllm/0.png
--------------------------------------------------------------------------------
/vllm/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/vllm/1.png
--------------------------------------------------------------------------------
/vllm/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/vllm/2.png
--------------------------------------------------------------------------------
/vllm/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/vllm/3.png
--------------------------------------------------------------------------------
/vllm/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/vllm/4.png
--------------------------------------------------------------------------------
/vllm/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/vllm/5.png
--------------------------------------------------------------------------------
/vllm/b-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/vllm/b-1.png
--------------------------------------------------------------------------------
/vllm/b-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/vllm/b-2.png
--------------------------------------------------------------------------------
/vllm/b-a.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/vllm/b-a.png
--------------------------------------------------------------------------------
/vllm/b0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/vllm/b0.png
--------------------------------------------------------------------------------
/vllm/readme.md:
--------------------------------------------------------------------------------
1 | ## 主要是解决 通量的
2 |
3 | + 采用了 PagedAttention,可以有效管理 attention 的 keys、values
4 | + 吞吐量(通量)最多可以达到 huggingface 实现的24倍,并且不需要对模型结构进行任何的改变
5 |
6 | + State-of-the-art serving **throughput**
7 | + Efficient management of attention key and value memory with PagedAttention
8 | + Continuous batching of incoming requests
9 | + Fast model execution with CUDA/HIP graph
10 | + Quantization: GPTQ, AWQ, SqueezeLLM, FP8 KV Cache
11 | + Optimized CUDA kernels
12 |
13 | ### 背景
14 | + LLM 的推理,最大的瓶颈在于显存。
15 | + **自回归模型**的 keys 和 values 通常被称为 KV cache,这些 tensors 会存在 GPU 的显存中,用于生成下一个 token。这些 KV cache 都很大,并且大小是动态变化的,难以预测。已有的系统中,由于显存碎片和过度预留,浪费了60%-80%的显存。
16 | > 自回归模型? https://github.com/lix19937/dnn-cookbook/blob/main/doc/transformer.md
17 | > 模型通常指仅使用解码器的Transformer模型。在每个阶段,对于给定的单词,注意力层只能获取到句子中位于将要预测单词前面的单词。预训练任务通常是Next word prediction,这种方式又被称为Causal language modeling。这个Causal就是“因果”的意思,对于decoder,它在训练时是无法看到全文的,只能看到前面的信息。这些模型通常被称为自回归模型。
18 |
19 | ### 实现
20 | 受到操作系统中,虚拟内存和分页经典思想的启发。
21 | PagedAttention 允许在不连续的内存空间中存储连续的 keys 和 values。
22 |
23 | 具体来说,PagedAttention 会将每个序列的 KV cache 划分为块,每个块包含固定数量 tokens 的 keys 和 values。在注意力计算过程中,PagedAttention 内核有效地识别并获取这些块。
24 | 分块之后,这些 KV cache 不再需要连续的内存,从而可以像在操作系统的虚拟内存中一样,更灵活地对这些 KV cache 进行管理。
25 |
26 | PagedAttention 对于显存的利用接近理论上的最优值(浪费比例低于4%)。通过对显存进行更好的管理,可以使得单次可以使用更大的 batch size,从而进一步利用 GPU 的并行计算能力。
27 |
28 | ### memory sharing
29 | + memory sharing 是 PagedAttention 的另一个关键特性。
30 | + 当用单个 prompt 产出多个不同的序列时,可以共享计算量和显存。
31 | 怎么理解**单个 prompt 产出多个不同的序列** ?
32 | + 通过将不同序列的 logical blocks 映射到同一个 physical blocks,可以实现显存共享。
33 | + 为了保证共享的安全性,对于 physical blocks 的引用次数进行统计,并实现了 **Copy-on-Write** 机制。这种内存共享机制,可以大幅降低复杂采样算法对于显存的需求(最高可下降55%),从而可以提升2.2倍的吞吐量。
34 |
35 |
36 |
37 | pip install vllm
38 |
39 | ```
40 | # 离线推理
41 | from vllm import LLM
42 |
43 | prompts = ["Hello, my name is", "The capital of France is"] # Sample prompts.
44 | llm = LLM(model="lmsys/vicuna-7b-v1.3") # Create an LLM.
45 | outputs = llm.generate(prompts) # Generate texts from the prompts.
46 | ```
47 |
48 | https://zhuanlan.zhihu.com/p/642802585
49 | https://blog.vllm.ai/2023/06/20/vllm.html
50 |
--------------------------------------------------------------------------------
/vllm/shm-0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/vllm/shm-0.png
--------------------------------------------------------------------------------
/vllm/shm-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/vllm/shm-1.png
--------------------------------------------------------------------------------
/vllm/shm-2-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/vllm/shm-2-1.png
--------------------------------------------------------------------------------
/vllm/shm-2-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/vllm/shm-2-2.png
--------------------------------------------------------------------------------
/vllm/shm-2-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/vllm/shm-2-3.png
--------------------------------------------------------------------------------
/vllm/shm-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/vllm/shm-3.png
--------------------------------------------------------------------------------
/vllm/shm-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/vllm/shm-4.png
--------------------------------------------------------------------------------
/vllm/shm-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/vllm/shm-5.png
--------------------------------------------------------------------------------
/vllm/shm-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lix19937/llm-deploy/9f955a2393a85fc5acf66cc4edec1459cf28a53b/vllm/shm-6.png
--------------------------------------------------------------------------------