支持新模型:
https://docs.vllm.ai/en/v0.6.3/models/adding_model.html#
https://docs.sglang.io/supported_models/support_new_models.html#how-to-support-a-new-language-model
多模态大语言模型推理原理与实现
基于 nano-sglang 框架的多模态模型处理机制
多模态模型概述
多模态模型的核心思想是将不同模态的数据映射到统一的语义空间,然后利用语言模型进行理解和生成:
123456789101112131415┌─────────────┐ ┌─────────────┐ ┌──────────────┐
│ 文本输入 │ ──→ │ Tokenizer │ ──→ │ Token Embed │
├─────────────┤ ├─────────────┤ ├──────────────┤
│ 图像输入 │ ──→ │ Vision Enc │ ...
NOTE
参考自文章:https://blog.speechmatics.com/cuda-timings
强烈推荐大家去阅读原文
GPU 算子性能测试优化点总结
优化点
核心原理
解决的问题
主机-设备同步 (Host-Device
Sync)
CUDA
核函数是异步执行的。CPU
只是把任务丢进队列就继续往下跑了。
避免只测到了“分发任务”的时间,而不是“执行任务”的时间。
CUDA Events
在 GPU 指令流中插入“时间戳”标记,由 GPU
硬件直接记录。
减少 CPU 侧 perf_counter
带来的系统调用开销和内核启动(Launch)干扰。
预热 (Warmup)
排除 JIT 编译、cudnn
算子自动选择(autotune)、显存重新分配和延迟加载等一次性开销。
避免初次运行的巨大延迟拉高平均值,使数据更符合稳定运行状态。
固定时钟频率 (Fixed
Clocks)
现代 GPU ...
AWQ算子实现
目标
AWQ算子本质上就是实现一个矩阵乘
输入 A: 正常的连续内存 [M, K]。
输入 B: 高度int4压缩。水平方向(N)打包了
bit,垂直方向(K)按 group_size 进行了分块量化。
输出 C: 正常的连续内存 [M, N]
如下图所示:
graph TD
subgraph Input_A [输入矩阵 A: 激活值]
A_data["形状: [M, K]<br/>类型: float16/bfloat16<br/>(连续内存排布)"]
end
subgraph Input_B [输入矩阵 B: 量化权重]
direction TB
subgraph B_Storage [存储结构]
QW["qweight<br/>[K, N/8]<br/>int32 (打包 8个 4-bit)"]
QZ["qzeros<br/>[K/G, N/8]<br/>i ...
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 ...



