导语摘要在大模型本地部署场景中很多服务器并不是标准的同构 GPU 配置而是同时存在不同型号的显卡。例如一台机器中既有RTX 4090D又有两张 A100-SXM4-40GB。这种机器资源看起来很强但真正部署 vLLM 时会遇到一个问题三张卡型号不同能不能放在同一个 vLLM 实例里一起跑如果直接使用CUDA_VISIBLE_DEVICES0,1,2 --tensor-parallel-size3看似简单但在异构 GPU 场景下并不一定稳定。因为 Tensor Parallelism 会把同一层计算切到多张 GPU 上执行对 GPU 性能一致性和通信能力要求更高。本文整理一种更适合当前机器的方案方案 A单实例三卡部署使用 Pipeline Parallelism配置为TP1PP3。也就是CUDA_VISIBLE_DEVICES0,1,2 --tensor-parallel-size1--pipeline-parallel-size3这套方案的目标不是盲目追求极限吞吐而是先让4090D A100 A100三张异构 GPU 在同一个 vLLM 实例中稳定参与推理。一、部署背景为什么要做异构三卡当前服务器 GPU 配置如下GPU 0NVIDIA GeForce RTX 4090 DGPU 1NVIDIA A100-SXM4-40GBGPU 2NVIDIA A100-SXM4-40GB如果只追求稳定其实最简单的方式是只使用两张 A100CUDA_VISIBLE_DEVICES1,2--tensor-parallel-size2这种部署方式属于双 A100 同构部署稳定性较好适合生产主服务。但问题是服务器上还有一张 4090D如果完全不用就会造成资源浪费。因此我们希望实现三张 GPU 都参与同一个 vLLM 实例对外提供服务尽量规避异构 TP 带来的问题通过 systemd 统一管理服务使用 OpenAI 风格接口对外调用这就是本文的方案 A。二、为什么不推荐直接使用 TP3很多人看到三张 GPU会直接想到CUDA_VISIBLE_DEVICES0,1,2 --tensor-parallel-size3这表示把三张 GPU 放进同一个 Tensor Parallel 组里。如果三张卡都是同型号比如三张 A100这种方式相对更容易理解和调优。但当前机器是4090DA100A100这属于异构 GPU 组合。2.1 Tensor Parallelism 对 GPU 一致性要求更高Tensor Parallelism 会把同一层的矩阵计算拆分到多张 GPU 上执行。这意味着多张 GPU 之间需要频繁同步中间结果。在异构 GPU 场景下不同显卡之间存在差异架构不同计算能力不同显存规格不同通信效率不同单步计算耗时不同最终可能导致一个问题快卡在等慢卡。这会让整体性能不一定比双 A100 更好。2.2 参数不一致时容易启动失败如果你设置了--tensor-parallel-size3但是当前进程实际只看到了两张 GPU就会出现类似错误World size (3) is larger than the number of available GPUs (2)这个错误的意思非常直接world size 是 3但当前节点可用 GPU 只有 2所以 vLLM 无法启动这种问题通常由下面几种情况引起CUDA_VISIBLE_DEVICES只暴露了两张卡--tensor-parallel-size却设置成了 3systemd 旧配置没有重新加载实际生效的启动参数和预期不一致因此在异构三卡场景下不建议一开始就直接上TP3。三、方案 A 的核心思路方案 A 的核心配置是CUDA_VISIBLE_DEVICES0,1,2 --tensor-parallel-size1--pipeline-parallel-size3它的含义是三张 GPU 全部暴露给 vLLM不做三卡张量并行改用 Pipeline Parallelism将模型按层切成三个阶段每张 GPU 负责一个 pipeline stage3.1 核心并行关系vLLM 中可以简单理解为world_size tensor_parallel_size × pipeline_parallel_size本方案中world_size 1 × 3 3正好对应三张 GPU。3.2 为什么 PP 更适合异构三卡Pipeline Parallelism 是按模型层切分。它不是把同一层计算强行拆给三张不同型号 GPU而是让不同 GPU 负责模型的不同层段。这样做有几个好处避免异构 GPU 直接进入同一个 Tensor Parallel 组三张卡仍然可以参与同一个模型实例部署结构更清晰更适合先验证异构三卡可行性不过也要注意Pipeline Parallelism 并不保证一定比双 A100 TP 更快。因为如果某一个 pipeline stage 较慢其他 stage 仍然可能等待。所以方案 A 更适合异构三卡单实例验证资源充分利用实验vLLM PP 部署实践非极致吞吐优先场景四、方案 A 总体架构图图 1 展示了方案 A 的核心结构vLLM API Server 对外提供统一接口GPU 0 的 4090D 作为 Pipeline Stage 0GPU 1 的 A100 作为 Pipeline Stage 1GPU 2 的 A100 作为 Pipeline Stage 2整体配置为TP1PP3这种方式让三张异构 GPU 都参与同一个 vLLM 实例。五、最终 systemd 配置下面是完整可用的 systemd 配置。文件路径/etc/systemd/system/vllm-gemma.service完整内容如下[Unit] DescriptionvLLM Gemma GGUF Service Afternetwork-online.target Wantsnetwork-online.target [Service] Typesimple Userroot Grouproot WorkingDirectory/data/models EnvironmentCUDA_DEVICE_ORDERPCI_BUS_ID EnvironmentCUDA_VISIBLE_DEVICES0,1,2 EnvironmentPYTHONUNBUFFERED1 EnvironmentHF_HOME/root/.cache/huggingface ExecStart/root/miniconda3/envs/vllm/bin/vllm serve /data/vllm/models/gemma-3-12b-it-qat-q4_0-gguf/gemma-3-12b-it-q4_0.gguf \ --tokenizer /data/vllm/models/gemma-3-27b-it \ --served-model-name gemma3-12b-q4 \ --tensor-parallel-size 1 \ --pipeline-parallel-size 3 \ --host 0.0.0.0 \ --port 8000 \ --api-key sk-gemma \ --language-model-only \ --max-model-len 16384 \ --gpu-memory-utilization 0.90 \ --max-num-seqs 64 \ --max-num-batched-tokens 16384 Restartalways RestartSec10 TimeoutStartSec0 LimitNOFILE1048576 [Install] WantedBymulti-user.target六、关键配置解释6.1 固定 CUDA 设备顺序EnvironmentCUDA_DEVICE_ORDERPCI_BUS_ID异构 GPU 环境下建议保留这个配置。它可以让 CUDA 按 PCI Bus ID 顺序枚举设备避免因为默认设备排序导致 GPU 编号和预期不一致。6.2 暴露三张 GPUEnvironmentCUDA_VISIBLE_DEVICES0,1,2这表示当前 vLLM 进程可以看到三张 GPUGPU 04090DGPU 1A100GPU 2A100如果写成EnvironmentCUDA_VISIBLE_DEVICES1,2那 vLLM 只能看到两张 A1004090D 不会参与。6.3 不做三卡 TP--tensor-parallel-size1这表示不做 Tensor Parallelism。6.4 使用三段 PP--pipeline-parallel-size3这表示把模型按层切成三个 pipeline stage。6.5 模型服务名保持一致--served-model-name gemma3-12b-q4这里建议服务名和实际模型保持一致。因为实际加载的是gemma-3-12b-it-q4_0.gguf如果服务名还写成类似gemma3:27b-it-q8_0后续接口调用、日志排查、监控都会比较混乱。6.6 删除 TRANSFORMERS_CACHE不建议再配置EnvironmentTRANSFORMERS_CACHE/root/.cache/huggingface保留下面这一行即可EnvironmentHF_HOME/root/.cache/huggingface七、TP3 与 PP3 的对比图 2 展示了两种部署思路第一种是直接TP3同一层计算拆到三张 GPU对 GPU 一致性和通信要求更高异构卡场景下可能被慢卡拖住第二种是TP1PP3模型按层切成三段三张 GPU 分别负责不同 stage更适合异构三卡先跑通因此对于当前的4090D A100 A100组合建议优先使用方案 A。八、启动与验证方式8.1 重新加载 systemd 配置修改 service 后执行sudosystemctl daemon-reload8.2 重启 vLLM 服务sudosystemctl restart vllm-gemma.service8.3 查看服务状态sudosystemctl status vllm-gemma.service-n100--no-pager重点观察是否出现Python tracebackworld size 报错CUDA 报错显存不足模型路径错误tokenizer 路径错误8.4 实时查看日志journalctl-uvllm-gemma.service-f8.5 观察 GPU 使用情况watch-n1nvidia-smi正常情况下三张卡都应该出现 vLLM 进程并且显存会有明显占用。请求进入时三张卡的 GPU Util 会出现一定波动。8.6 测试模型列表接口curlhttp://127.0.0.1:8000/v1/models\-HAuthorization: Bearer sk-gemma正常情况下会返回类似{object:list,data:[{id:gemma3-12b-q4,object:model}]}8.7 测试对话接口curlhttp://127.0.0.1:8000/v1/chat/completions\-HContent-Type: application/json\-HAuthorization: Bearer sk-gemma\-d{ model: gemma3-12b-q4, messages: [ { role: user, content: 请用100字解释什么是 Pipeline Parallelism } ], temperature: 0.7, max_tokens: 256 }如果可以正常返回内容说明 vLLM OpenAI 风格接口已经可用。九、部署与验证流程图图 3 展示了方案 A 的完整部署流程修改 systemd service设置三卡可见配置TP1PP3重载 systemd重启 vLLM 服务查看日志使用nvidia-smi观察三张卡使用 curl 测试接口这个流程可以作为后续所有 vLLM 服务调试的基础模板。十、常见问题排查10.1 报错World size 大于可见 GPU 数量典型错误World size (3) is larger than the number of available GPUs (2)原因是并行参数要求 3 张 GPU但当前进程只看到 2 张 GPU常见错误配置CUDA_VISIBLE_DEVICES1,2--tensor-parallel-size3修复方式CUDA_VISIBLE_DEVICES0,1,2 --tensor-parallel-size1--pipeline-parallel-size3同时确认 systemd 已经重新加载sudosystemctl daemon-reloadsudosystemctl restart vllm-gemma.service10.2 服务还是使用旧参数如果你已经改了 service但日志里还是出现旧参数可能是没有执行sudosystemctl daemon-reload建议直接查看当前 systemd 实际加载的配置sudosystemctlcatvllm-gemma.service确认里面是否仍然存在旧参数比如--tensor-parallel-size310.3 仍然出现 TRANSFORMERS_CACHE 警告如果日志里仍然看到Using TRANSFORMERS_CACHE is deprecated说明配置里还残留EnvironmentTRANSFORMERS_CACHE/root/.cache/huggingface删除它只保留EnvironmentHF_HOME/root/.cache/huggingface然后重新加载服务sudosystemctl daemon-reloadsudosystemctl restart vllm-gemma.service10.4 三张卡显存不完全一致这是正常现象。Pipeline Parallelism 是按层切分模型不是让每张卡做完全一样的事情。因此三张 GPU 的显存占用、GPU Util 不一定完全相同。只要满足下面条件就说明服务基本正常三张 GPU 都有 vLLM 进程三张 GPU 都有显存占用请求能够正常返回日志没有持续报错10.5 服务启动慢vLLM 启动时需要加载模型、初始化 tokenizer、分配 KV cache、构建执行图因此大模型首次启动慢是正常现象。建议通过下面命令观察journalctl-uvllm-gemma.service-f如果长时间卡住可以重点检查模型路径是否正确tokenizer 路径是否正确显存是否不足是否开启了过大的max-model-len是否设置了过大的max-num-seqs十一、性能调优建议11.1 首次启动建议保守一点如果是第一次验证异构三卡 PP建议先用保守配置--max-model-len8192--gpu-memory-utilization0.85--max-num-seqs32--max-num-batched-tokens8192等服务稳定后再逐步提高到--max-model-len16384--gpu-memory-utilization0.90--max-num-seqs64--max-num-batched-tokens1638411.2 不要默认认为三卡 PP 一定更快方案 A 的重点是三张卡都参与单实例部署异构 GPU 验证模型按层切分但它不一定比双 A100 TP2 更快。原因是 PP 会受到最慢 stage 的影响。如果 4090D 所在 stage 较慢两张 A100 可能需要等待。所以建议你实际对比方案配置特点适合场景双 A100 TPCUDA_VISIBLE_DEVICES1,2TP2稳定、简单、性能好生产主服务三卡 TPCUDA_VISIBLE_DEVICES0,1,2TP3看起来简单但异构不稳不建议优先使用三卡 PPCUDA_VISIBLE_DEVICES0,1,2TP1,PP3三卡都参与适合异构验证本文方案 A双实例分流A100 实例 4090D 实例更灵活、更适合长期生产进阶方案11.3 建议压测指标后续可以重点观察这些指标首 token 延迟平均 tokens/s并发请求数GPU 利用率显存占用请求失败率请求排队时间vLLM 日志中的调度信息测试时建议分别对比双 A100 TP2三卡 PP3单 4090D单 A100双实例分流这样才能判断当前方案是否真的适合你的业务请求类型。十二、适合放到文章中的最终配置总结本文最终采用的部署方式是CUDA_DEVICE_ORDERPCI_BUS_IDCUDA_VISIBLE_DEVICES0,1,2vLLM 并行参数是--tensor-parallel-size1--pipeline-parallel-size3完整目标是4090D 参与两张 A100 参与单实例部署不做异构 TP使用 Pipeline Parallelism 按层切分通过 OpenAI 风格接口对外服务十三、总结对于RTX 4090D 双 A100这种异构 GPU 服务器最直观的想法是直接使用--tensor-parallel-size3但这种方式不一定适合异构场景。更稳妥的方案是--tensor-parallel-size1--pipeline-parallel-size3也就是本文的方案 A。它的核心价值在于三张 GPU 都能参与同一个 vLLM 实例避免异构 GPU 直接进入同一个 Tensor Parallel 组配置相对清晰适合先验证三卡异构推理可行性方便后续和双 A100 TP2 做性能对比不过也要明确方案 A 不一定是极致吞吐最优解它更适合作为异构三卡单实例部署的验证方案。如果后续追求长期生产稳定可以继续演进为A100 A100 作为主推理服务4090D 作为独立副服务前面通过 API 网关按请求类型分流这样既能利用所有 GPU也能让整体架构更加稳定、可控、易维护。