- TensorRT: nvidia 开发的,算子优化做的比较好的工具,跑在nvidia自家的卡上,切换不同的卡型,需要在对应的机器上把trt模型再重新转换一下;预设好min_shape, opt_shape, max_shape,最常用的size 设置为opt_shape;
- torch.inductor:对于2.0 以上的torch 代码使用,直接构建图&编译(也会有算子融合),适用于不同的gpu 卡型,在模型第一次infer的时候,进行编译,如果shape发生变化,会重新编译(通常耗费较长的时间)。因此warm-up的阶段,直接用最常用的size 进行编译;
- 计算图:描述了模型结构,是高级IR的一种,节点通常对应高级API(如torch.conv2d),保留了较多的源语言语义。
- 静态图:没有if/else分支;
- 动态图,编译了数据的不同流向;
- IR:(Intermediate Representation),将源语言转换成IR,然后将IR 转换成不同机器的机器码。直接在源语言上做机器的优化,非常复杂,种类很多,M种源语言,N种机器,则需要M*N 种前后端匹配的优化。有了IR之后,只需要M个前端+N 个后端即可。解耦了前后端。
- 编译器:通常分成三个部分
- 前端:理解源语言的语法/语义(c++/python), 生成一个高级的、与源语言紧密相关的 IR
- 中间端 / 优化器:对IR 进行分析转换,在不改变逻辑的情况下进行优化,比如算子融合,循环展开,消除冗余代码;
- 后端:比如TensorRT、PyTorch (torchscript/inductor)、ONNX Runtime、TensorFlow 。优化后的 IR 转换为特定目标硬件的机器码。比如寄存器分配,汇编代码/机器码生成等。
- vLLM :对于通用的LLM AR 结构,性能优化的很好
- 核心:pagedAttention,解决kv cache 内存管理的问题;
- 常规的kv cache内存浪费严重:比如huggingface transformer的实现,是对kv cache 预先分配一块很大的连续存储空间,但是实际使用的时候可能只用一小部分,这样导致即使显存剩余够用,但是无法找到一块完整的空间而无法使用。
- 随便化kv cache:将gpu 显存划分成若干个固定大小的物理块,对于同一个序列的kv cache,可能被分配到若干个不连续的显存空间,管理的是不同块的地址信息;提升了内存利用效率,进而可以增大batch_size,提升吞吐;
- pagedAttention 和flash attention的关系
- 两者不冲突,搭配使用更佳
- pagedAttention负责快速的的读写数据,找到数据,只能用于infer阶段;
- flash attention负责底层的计算速度加快,减少内存 I/O,训练加速都能使用;