使用 nsys & ncu 分析 vLLM 推理性能

大模型这么火,但却发现网上很少有相关的性能分析的资料,绝大部分都是偏理论的性能分析

最近发现了 nvidia 有很好的性能分析工具,nsys 和 ncu,于是决定用来研究下 vllm 的 decode 性能,本文将是一些记录,方便大家更好的学习和使用

1. nsys & ncu 基础

1.1. 简介

在之前的CUDA版本中,所附带的性能分析工具主要是nvvp(NVIDIA Visual Profiler)和nvprof,前者是带有图形界面的分析工具,后者是命令行工具。在CUDA官方文档中有这样一段描述:

Note that Visual Profiler and nvprof will be deprecated in a future CUDA release.The NVIDIA Volta platform is the last architecture on which these tools are fully supported. It is recommended to use next-generation toolsNVIDIA Nsight Systemsfor GPU and CPU sampling and tracing andNVIDIA Nsight Computefor GPU kernel profiling.

所以nvvpnvprof现在已经废弃了,现在nvidia主要的性能分析工具就是nsys(Nsight System)和ncu(Nsight Compute)。

nsys是系统层面的分析工具,nsys 主要用来分析函数热点,产生类似于火焰图之类的数据。

ncu则是用于分析一个具体的核函数,更多的是看核函数执行过程中 GPU 硬件的性能,比如内存带宽和 SM 利用率等等。

两者均有图形界面版本和命令行版本。这2个工具一般都是组合起来一起使用的

1.2. 安装

需要用邮箱注册一下,然后下载:

  1. ncu:https://developer.nvidia.com/tools-overview/nsight-compute/get-started
  2. nsys:https://developer.nvidia.com/nsight-systems/get-started

需要下载 deb 包和 msi 安装包前者安装在容器镜像里面,用于采集 Profile 数据后者安装在 windows 笔记本上(如果你是 mac,就装 mac 版就行),用于分析 Profile 数据比如我在容器里安装的就是:

NsightSystems-linux-cli-public-2024.6.1.90-3490548.deb

nsight-compute-linux-2024.3.2.3-34861637.run

1.3. 基本用法

nsys:

nsys profile -o /tmp/profile.out -f true python3 vllm_offline.py

运行结束会产生一个 profile.out.nsys-rep 文件

用 windows 打开就得到


SplitWise:分离式架构的影响因子分析

在我们实际测试的过程中,我们发现分离式架构受模型和负载的影响其实是非常大的。

不同的模型,不同的负载,收益大小很不一样

  1. 模型:模型大小,开不开 gqa,等
  2. 负载:输入长度、输出长度、请求的 qps,等

那我们怎么知道什么场景下适合用分离式架构呢?

这篇文章我们从 decode 阶段的理论计算上来尝试推导一下,看模型和负载是如何影响分离式架构的收益的

1. Decode 计算和访存需求

参考:FASTDECODE: High-Throughput GPU-Efficient LLM Serving using Heterogeneous

decode 时间理论计算(假设默认开启 GQA = 8,量化 int8,xx):

batch 计算 batch 访存量
S-part 24bh² (12h² + 10bh) * sizeof(int8) = 12h² + 10bh
R-part 4bhs 2bhs * sizeof(int8) = 2bhs

注意:

  1. 12h² + 10bh,不管是大模型还是小模型,10bh耗时占比1/1000,所以10bh可以直接忽略
  2. R-part的计算耗时 4bhs/312,也是要远远小于其他3项,基本可忽略

所以整个 decode 阶段的耗时,可以按如下计算

TBT = \frac{24blh^2}{312} + \frac{12lh^2}{2} + \frac{2blhs}{2 * GQA} = b(\frac{24lh^2}{312} + \frac{2lhs}{2 * GQA}) + \frac{12lh^2}{2}

因此:TBT 是一个bs的线性函数

2. 分离式架构的理论收益公式

2.1 干扰程度

分离收益的前提,取决于干扰的程度,干扰越大,分离后的收益越大假设一个模型:

  1. tbt:单token输出时间
  2. ttft:首token计算时间
  3. s:输入长度
  4. n:输出长度
  5. λ:请求进来的速率

单个请求端到端的时间:e2e = tbt * n + ttft

受干扰的时间比例: β= \frac{e2e * λ * ttft}{e2e} = λ * ttft


ReFT: Reasoning with REinforced Fine-Tuning

最近 openai 发布圣诞系列的第一弹,就强调了强化微调,基于这个,可以让小模型结合行业数据,做到比大模型更强的推理效果

然后研究了下字节之前发过的类似的一篇论文:https://arxiv.org/pdf/2401.08967

 

1. 背景

1.1. 传统的 CoT 训练方法

虚线之上是传统的 CoT 训练方法,就是使用数据集(x, e, y)不断的训练基础模型,让基础模型获得推理能力

比如 gsm8k 数据集:https://huggingface.co/datasets/openai/gsm8k/viewer/main/train?p=1&row=167

这个数据集里面每一行就是一条训练数据,包括3部分:

x就是问题

e就是解决这个问题的思路

y是答案

但是这种训练方法,模型推理的泛华能力是比较弱的,因为它只能学习到一种解题思路,就是数据集中的思路

1.2. ReFT:Reinforced Fine-Tuning

训练思路和 SFT 很不一样同一条数据集,SFT 会反复训练多次,让模型在数据集上误差最小。这样训练出来的模型,对于解决数据集中的问题肯定是没问题的,但是对于解决数据集的其他问题,就不一定是最佳的了。这个时候回答问题的质量取决于数据集的质量和规模ReFT 只需要1~2次预热,得到一个基础的模型,然后通过强化学习,让模型主动去探索不同的解题路径,这样得到的模型,泛化能力是最强的

如上图,ReFT 有2个核心阶段:

  1. warm-up:xx
  2. 强化学习阶段:specifically Proximal Policy Optimization (PPO)

特别注意:ReFT 并不依赖额外的训练数据集通过这个方法,论文使 CodeLLAMA 和 Galactica 模型在GSM8K、MathQA、SVAMP数据集上,泛化能力得到了显著提高