PS:下面的内容会非常枯燥,没有耐心的肯定看不下去。因为我写的时候也是觉得很枯燥。。
但这个对于模型运行来说非常重要,理解原理后配置相关参数则不会像无头苍蝇一样胡乱配置。除下面所介绍的参数和名词,还有很多,有兴趣可查看官方文档。
为什么需要计算最大token数和最大并发数?
1)在同一台服务器中,同一个模型在不同参数下的表现不同。模型在一定条件下可正常运行甚至流畅运行,但参数不对的情况下可能出现OOM从而导致模型崩溃的问题;
2)模型下载前可查看模型内的config文件,可通过计算所得此模型是否可在本机器上正常运行,避免下载后无法使用或OOM浪费时间和资源。
本文背景
最近在测试模型稳定性时反复出现掉模型的现象,研究时发现模型稳定与各类参数相互作用。模型参数设置对于模型稳定至关重要。模型参数使用默认值或配置不合理时则会出现模型不稳定或者OOM直接将模型冲爆,导致掉模型。观点为:模型可用显存>模型运行最大值
每个模型参数都有默认值,如默认值未人为设置,则会出现OOM。在下载的模型中都会有个config.json,config.json中会有部分默认值。以下为Qwen3-32B的配置文件
案例解析
假如现在有台机器使用8*4090显卡,单显卡24G。使用vllm + transformers 框架运行Qwen3-32B模型,后续使用vllm serve方式启动, --gpu-memory-utilization 设置0.75,--dtype 设置为 float16,--max-model-len 8192 那么最大token数和最大并发数为多少?
Qwen3-32B config.json文件如下所示:
{
"architectures": [
"Qwen3ForCausalLM"
],
"attention_bias": false,
"attention_dropout": 0.0,
"bos_token_id": 151643,
"eos_token_id": 151645,
"head_dim": 128,
"hidden_act": "silu",
"hidden_size": 5120,
"initializer_range": 0.02,
"intermediate_size": 25600,
"max_position_embeddings": 40960,
"max_window_layers": 64,
"model_type": "qwen3",
"num_attention_heads": 64,
"num_hidden_layers": 64,
"num_key_value_heads": 8,
"rms_norm_eps": 1e-06,
"rope_scaling": null,
"rope_theta": 1000000,
"sliding_window": null,
"tie_word_embeddings": false,
"torch_dtype": "bfloat16",
"transformers_version": "4.51.0",
"use_cache": true,
"use_sliding_window": false,
"vocab_size": 151936
}
模型术语及config名词介绍
模型术语
1)OOM:内存溢出(out of memory)。当模型运行时超出总显存时,则会出现内存溢出。溢出最直接的后果模型崩溃退出;
2)模型精度:模型的精密度,常见的有FP32,FP16/BF16,INT8,INT4。FP32>FP16/BF16>INT8>INT4,精度越高,所消耗的显存越多。可通过【--dtype】进行设置精密度;
3)总显存:整台机器可用的显存数,在此案例中的总显存数为8 × 24=192G;
4)模型可用显存:默认模型可用GPU的显存数,如使用vllm + transformers 框架,可用显存默认数值为0.9,即默认模型可使用90%GPU资源。可通过vllm 中的参数 --gpu-memory-utilization 进行调整空出一部分的显存。(数值不是越大越好,如90%被模型使用,剩下的剩余显存无法给其他模型使用)
5)模型权重:模型加载行时所要用到显存(固定值)。根据模型精度计算,如FP32:4 Bytes,FP16/BF16:2 Bytes,INT8:1 Byte,INT4:0.5 Byte,如在启动Qwen3-32B时写入参数--dtype float16,那么单单模型在加载启动时就需32 × 2=64G显存。
6)模型启动固定花销:包括框架初始化开销,激活值,中间计算结果和内存管理开销,消耗的是可用显存。不太严谨的说,如在本案例中可将所有的显存固定值大概4G-6G左右。(4G-6G是单卡固定显存花销数,以5G计算,8卡则需要40G显存)
7)KV_cache可用显存:将模型可用显存-模型权重-模型固定显存开销即可得到模型最终可支配的kv_cache可用缓存。
图示如下:
config名词介绍
1)最长上下文长度:输入+输出的最大值。如单次询问超过最长上下文长度,则会停止输出。不同的模型默认值不同,可在【--max-model-len 】添加参数固定值。
2)最大并发数:可同时对模型询问的数量。不同的模型默认值不同,可在【--max-num-seqs】添加参数固定值。
3)head_dim::头维度,每个注意力头(attention head)的向量维度大小,一般config.json会有,如果没有可通过计算head_dim = hidden_size / num_attention_heads。
Qwen3-32B的配置文件不适用此公式。因为Qwen3-32B 这种使用分组查询注意力(GQA),标准公式在 GQA 模型中不成立,所以直接使用config.json文件的head_dim参数而不能使用公式。(别问,问就是就是这样回答)
4)num_key_value_heads:KV头数量,这是分组查询注意力(GQA) 或多查询注意力(MQA) 的关键参数;
5)num_hidden_layers:Transformer模型的层数,用于计算token输出花销;
6)单层单token显存花销:单层输出每个token的所消耗的显存花销;
7)全层单token显存花销:全层数即全部Transformer模型的层数输出每个单token显存花销。
最终计算公式
PS:以下一切算法均是约等于。
1)可用显存=总显存 × gpu-memory-utilization
本案例中可用显存为=(24G×8张) × 0.75=144G
2)模型权重=模型参数 × dtype精度
本案例中模型精度float16=2 Bytes,所以数值为2。模型权重≈32B × 2≈64G
3)可用于KV缓存的显存≈可用显存-模型权重-模型启动固定花销
本案例中可用于KV缓存的显存≈144G-64G-40G≈40G
4)单层单token显存花销=2 × num_key_value_heads × head_dim×dtype精度。第一个2是固定值,因为【--dtype float16】,模型精度float16=2 Bytes,所以数值为2。
本案例中单层单token显存花销=2 × 8 × 128 × 2Bytes=4096 Bytes/token
5)全层单token显存花销=num_hidden_layers × 单层单token显存花销
本案例中全层单token显存花销=64 × 4096≈262144 Bytes=256 KB/token,即一个token在正常情况下需要消耗8张卡的256KB显存。
6)最大token数≈可用于KV缓存的显存/全层单token显存花销
本案例中最大token数≈(144G-64G-40G)/256KB≈163840 token
7)最大并发数≈最大token数/最大上下文长度
本案例中最大并发数≈163840 token/8192 token≈20 个。
本文由 yorickbao 创作,采用 知识共享署名4.0 国际许可协议进行许可。
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。