NOTE
对一个推理框架来说,要推理一个量化后的模型,会需要知道几件事情:
怎么知道这是一个量化模型
怎么知道这个模型量化了哪些层
具体是怎么多态实现到量化上的
量化的算子计算实现是什么
后续的内容都是以llama2-7b-awq举例,其它模型或者量化方法本质上都是相似的
怎么知道这是一个量化模型
观察config.json可以看到里面有quantization的配置:
123456789101112131415161718192021222324252627282930313233343536LlamaConfig {
"architectures": [
"LlamaForCausalLM"
],
"attention_bias": false,
"attention_dropout": 0.0,
"bos_token_id": 1,
"dtype": "float16",
"eos_token_i ...
概述
在 PD(Prefill-Decode)分离架构中,Prefill 和 Decode
的性能是完全独立的。TTFT(Time To First Token)和 TPOT(Time Per Output
Token)的指标完全取决于输入/输出吞吐和具体的机器配比。本文介绍如何分别测试和确定
Prefill 与 Decode 的最佳性能配比。
测试 Prefill 性能
测试原理
Prefill 性能测试相对简单,因为 Decode 性能通常会远强于 Prefill
性能,因此只需要一个普通的 Decode 节点即可。
测试方法
设置 Decode 节点:启动一个普通的 Decode 节点
配置 Bench 参数:
输出长度设置为 1
这样可以完整包含 Prefill 的计算和 PD 传输过程
设置合理的并发数
示例配置:
输入:8k tokens
输出:1 token
并发:128
这样可以通过测试计算出 Prefill 最大的 RPS(Requests Per
Second)。
多组测试维度
建议进行多组测试以找到最佳配置:
不同卡数:8 卡、16 卡等 ...
关于chunked prefill
NOTE
为什么要有chunked prefill?
减少prefill过程中的激活值占用空间,防止OOM,主要是,这个矩阵乘的维度和序列长度有关,切成小块可以有效减少大小
另一个好处是在序列较长且混合时可以更好的利用单次推理的空余空间
在完整sglang的实现中,跟prefill分块的参数有两个:
--max-prefill-tokens
单次forward能够跑的最大的长度(这个参数可以不管,这个算是历史遗留参数,在没有chunked-prefill-size时才有用)
--chunked-prefill-size
每个请求被chunk拆分的块长度(关键看这个参数,决定了prefill单个forward
batch的tokens个数)
为什么要有这两个值:
第一个是限制系统总体prefill推理时的计算量,这个是可以有很多个req组成的(可以不关注)
第二个是为了把一个长请求拆分成更小的块, ...
OOM堆栈不准
GPU执行kernel是异步的,报错堆栈可能不准确。
设置环境变量让GPU同步执行,获得准确堆栈:
1export CUDA_LAUNCH_BLOCKING=1
decode阶段CUDA Graph
decode开启CUDA
Graph时,OOM可能在replay时报错,无法定位具体算子,需要禁用后复现:
1python -m sglang.launch_server --model-path /path/to/model --disable-cuda-graph
GPU死锁
py-spy查看线程栈
1py-spy dump -p <pid>
判断GPU任务卡住
CPU卡在同步任务(如.tolist())时,如果GPU核心100%满载且无波动,说明GPU任务卡住。
cuda-gdb查看GPU栈
12cuda-gdb -p <pid>
(gdb) bt
环境不匹配
如果bt卡在CUDA的.so动态库,说明nvcc/CUDA驱动/torch
runtime版本不匹配。
12nvcc -V
pip show nvidia-cuda-runtim ...
other
未读
国内无法正常从官方网址docker pull拉取镜像
有以下几种方法可以使用:
使用镜像站
例如本来要执行docker pull nginx:latest
在地址前面添加镜像站地址:docker pull docker.1ms.run/nginx:latest
当然这个镜像站不一定存了最新的镜像,可以去网址上搜索看一下版本:https://1ms.run/
配置http代理
修改docker
daemon配置文件设置代理,但是这种方法需要重启docker服务,不适用于多人共用服务器场景
首先为docker创建systemd配置目录:
1sudo mkdir -p /etc/systemd/system/docker.service.d
创建或编辑配置文件:
1sudo vim /etc/systemd/system/docker.service.d/http-proxy.conf
添加以下内容:
1234[Service]
Environment="HTTP_PROXY=http://proxy.example.com:8080"
Environment="HTTPS ...
uvicorn/fastapi/flash/asyncio区别
项目
类型
作用
与 asyncio 的关系
asyncio
Python标准库
提供异步编程基础
基础异步运行时
Uvicorn
ASGI服务器
运行异步Web应用
基于 asyncio 构建
FastAPI
Web框架
构建Web API
内部使用 asyncio 处理异步请求
Flask
Web框架
构建Web应用
传统同步,可搭配异步但非原生
关键区别:
asyncio 是底层异步引擎
Uvicorn 是利用 asyncio 的服务器
FastAPI 是基于 asyncio 的异步框架
Flask 是同步框架,需要额外适配才能用
asyncio
关系层级
关系层级:
1客户端请求 → Uvicorn(服务器) → FastAPI/Flask(Web框架) → 你的代码
Flask:同步WSGI框架,通常使用 Gunicorn +
Werkzeug 作为服务器
FastAPI:异步ASGI框架,通常使用
Uvicorn 作为服务器
Uvicorn 是
服务 ...
NVIDIA显卡对比
GPU 型号
架构
FP64 TFLOPS
FP32 TFLOPS
FP16 TFLOPS
INT8 TFLOPS
FP8 TFLOPS
FP4 TFLOPS
显存
显存类型
内存带宽(GB/s)
NVLink
RDMA
PCIe
CUDA 核心
TDP (W)
V100
Volta
7.8
15.7
125
250
—
—
16/32 GB
HBM2
900
300 GB/s
✓
PCIe 3.0
5120
250–300
A100
Ampere
9.7
19.5
312
624
—
—
40/80 GB
HBM2e
1555/2039
600 GB/s
✓
PCIe 4.0
6912
300–400
A800
Ampere
9.7
19.5
312
624
—
—
40 GB
HBM2
1500
400 GB/s
RTX 4090
Ada
—
82.6
165
330
330
—
24 GB
GDDR6X
1000
-
—
PCIe 4.0
16384
~450
RTX 60 ...
在sglang中,对内存的管理总共分成了三个核心组件
RadixTree
ReqToTokenPool
TokenToKVPool
三个的大概结构如下图所示:
RadixTree 前缀树,用户匹配请求的前缀,对应到vllm的paged
attention的page结构
ReqToTokenPool
请求和token的对应表,每个请求一行数据,列表示第k个token对应到TokenToKVPool的id
TokenToKVPool
token对应到kvcache的id,是一个一维超长数组,size大小就是系统存储的kvcache
tokens的总数
依靠这三个组件,相互配合就可以完成对请求的kvcache内存管理
组件使用
我们从请求调度流程的视角,看一下三大组件是怎么管理一个请求的内存声明周期的
首先是来了请求,需要在RadixTree做前缀匹配
做Prefill和Decode
请求完成后需要清空内存(减少引用计数,只有内存不够时才真的清除)
可以观察到,一个请求最后计算完成的状态下,相比计算前,三大组件的状态发生了以下改变:
ReqToTokenPoo ...



