FastChat 本地 GPU 集群部署指南:Controller-Worker 架构下的多机多卡 LLM 推理实践 FastChat 本地 GPU 集群部署指南Controller-Worker 架构下的多机多卡 LLM 推理实践【免费下载链接】FastChatAn open platform for training, serving, and evaluating large language models. Release repo for Vicuna and Chatbot Arena.项目地址: https://gitcode.com/GitHub_Trending/fa/FastChat本文围绕 FastChat 仓库中的 本地集群部署文档 展开讲解如何用“一个 Controller 多台 GPU 机器上的 Worker”搭建跨节点的大语言模型推理集群覆盖 vLLM Worker、多卡张量并行、multi_model_worker 多模型共卡等典型部署形态读完后你可以直接按节点照抄命令拉起集群并理解每个参数的源码级含义与验证方法。一、集群架构单点 Controller水平扩展 WorkerFastChat 的服务器架构是一个典型的去中心化推理 中心化路由结构完整架构图见 docs/server_arch.md 及上图Controller控制器集群唯一的协调节点维护“模型名 → Worker 地址”的映射表负责 Worker 注册、心跳探活、请求路由。它本身不执行推理。实现位于 controller.py核心类Controller内部用worker_info字典保存每个 Worker 的model_names、speed、queue_length、last_heart_beat等元信息见 controller.py 的WorkerInfo。Model Worker推理节点每台 GPU 机器上可运行任意多个 Worker 进程每个 Worker 独占一张或多张卡加载一个或一组模型启动后向 Controller 注册自己的地址和模型列表并周期性发送心跳。从源码结构看整个集群的协作协议就是三组 HTTP 接口注册Worker 启动后 POST 到 Controller 的/register_worker提交自己的worker_name即对外可达地址、check_heart_beat标志和当前状态模型名、速度、队列长度心跳Worker 每隔WORKER_HEART_BEAT_INTERVAL秒 POST/receive_heart_beatController 端则每CONTROLLER_HEART_BEAT_EXPIRATION秒扫描一次把超时未上报的 Worker 从表中摘除controller.py 的remove_stale_workers_by_expiration路由客户端请求/get_worker_address或直接把请求发给 Controller 的/worker_generate_stream由 Controller 按分发策略选出 Worker 并流式转发。心跳相关的默认值定义在 constants.pyCONTROLLER_HEART_BEAT_EXPIRATION int( os.getenv(FASTCHAT_CONTROLLER_HEART_BEAT_EXPIRATION, 90) ) WORKER_HEART_BEAT_INTERVAL int(os.getenv(FASTCHAT_WORKER_HEART_BEAT_INTERVAL, 45)) WORKER_API_TIMEOUT int(os.getenv(FASTCHAT_WORKER_API_TIMEOUT, 100))即 Worker 每 45 秒上报一次心跳Controller 容忍 90 秒的静默窗口——Worker 意外宕机后最多约 90 秒就会被剔除出路由表。这三个常量都支持用同名环境变量覆盖跨机房部署时网络抖动较大可以适当调大。Controller 自身还提供lottery按速度加权随机和shortest_queue最短队列优先默认两种分发策略见 controller.py 的DispatchMethod可通过--dispatch-method参数选择。二、命令参数逐项解析本地集群文档中所有 Worker 命令都长这样下面先统一解释各参数以 vLLM Worker 为例CUDA_VISIBLE_DEVICES0 python3 -m fastchat.serve.vllm_worker \ --model-path lmsys/vicuna-13b-v1.5 \ --model-name vicuna-13b \ --controller http://node-01:10002 \ --host 0.0.0.0 --port 31000 \ --worker-address http://$(hostname):31000参数作用源码依据CUDA_VISIBLE_DEVICES环境隔离手段指定该 Worker 进程可见的物理 GPU。文档中所有单卡命令都靠它把模型固定到特定卡上操作系统级机制命令中直接前置--model-path模型权重路径本地目录或 Hugging Face 仓库 IDvllm_worker.py--model-name该 Worker 对外注册的模型名可逗号分隔多个。客户端和 Controller 都用这个名字路由请求同上--controllerController 地址所有 Worker 都指向http://node-01:10002同上--host 0.0.0.0 --portWorker 本进程监听的地址和端口每卡一个独立端口避免冲突同上--worker-address向 Controller 注册时上报的对外地址。用$(hostname)而不是localhost因为 Controller 可能运行在别的机器上必须用别的节点也能访问到的主机名同上--num-gpus多卡张量并行卡数例如 33B 模型用 2 张卡见下文 node-01 说明--tokenizer指定与模型不同的 tokenizer如 30B 模型用更小的 tokenizer 仓库加速分词vLLM 引擎参数两点源码层面的补充说明--worker-address与--port的分工是关键--port决定 uvicorn 实际监听哪个端口--worker-address决定 Controller 把请求转发到哪里。单机自测时两者一致跨机部署时--worker-address必须是集群内其他节点可解析、可达的主机名文档统一用http://$(hostname):端口。当前仓库源码中的参数名是--controller-address、--worker-address、--model-names逗号分隔和--limit-worker-concurrency例如 vllm_worker.py 与 multi_model_worker.py 的 argparse 定义部署文档使用了更简短的参数拼写如--controller、--model-name、--limit实际执行时请以你所运行版本的python3 -m fastchat.serve.worker --help输出为准两者语义一致。三、node-01Controller vLLM Worker 多卡张量并行node-01 是整个集群的控制节点也是文档中最“复杂”的一台机器它同时承载 Controller 和 3 个 vLLM Worker演示了单卡、双卡张量并行两种形态。# 1. 启动 Controller集群唯一 python3 -m fastchat.serve.controller --host 0.0.0.0 --port 10002 # 2. 单卡 WorkerGPU0 上加载 13B 模型 CUDA_VISIBLE_DEVICES0 python3 -m fastchat.serve.vllm_worker \ --model-path lmsys/vicuna-13b-v1.5 --model-name vicuna-13b \ --controller http://node-01:10002 --host 0.0.0.0 --port 31000 \ --worker-address http://$(hostname):31000 # 3. 单卡 WorkerGPU1 上再加载一份 13B 模型同名模型多副本 CUDA_VISIBLE_DEVICES1 python3 -m fastchat.serve.vllm_worker \ --model-path lmsys/vicuna-13b-v1.5 --model-name vicuna-13b \ --controller http://node-01:10002 --host 0.0.0.0 --port 31001 \ --worker-address http://$(hostname):31001 # 4. 启动 Ray 集群头节点占用 GPU2/3 CUDA_VISIBLE_DEVICES2,3 ray start --head # 5. 双卡张量并行 Worker2 张卡协同加载 33B 模型 python3 -m fastchat.serve.vllm_worker \ --model-path lmsys/vicuna-33b-v1.3 --model-name vicuna-33b \ --controller http://node-01:10002 --host 0.0.0.0 --port 31002 \ --worker-address http://$(hostname):31002 --num-gpus 2几个值得注意的设计点同名模型多副本GPU0 和 GPU1 上运行两个vicuna-13bWorker端口 31000/31001。Controller 的worker_info以 Worker 地址为键两个副本是两个独立条目请求会被分发策略在两者之间均衡等效于对同一模型做水平扩容。--num-gpus 2与 RayvLLM 的多卡张量并行依赖 Ray 进程组所以 33B Worker 前先执行ray start --head。从源码看vLLM Worker 在启动时若num_gpus 1会将其直接映射为 vLLM 引擎的tensor_parallel_sizevllm_worker.pyif args.num_gpus 1: args.tensor_parallel_size args.num_gpus注意该 Worker 命令本身没有加CUDA_VISIBLE_DEVICES此时 Ray 会按其调度机制使用已暴露的 GPU2/3 两张卡前两条 Worker 则用CUDA_VISIBLE_DEVICES0/1显式钉死在单卡上四张卡互不干扰。vLLM Worker 的并发上限--limit-worker-concurrency默认 1024vllm_worker.py通过 asyncio 信号量控制同时在途请求数vLLM 引擎自身的 continuous batching 在其上继续做细粒度调度两者分层限流。四、node-02 / node-03纯 Worker 节点与 tokenizer 覆盖node-02 和 node-03 上不运行 Controller全部命令都是“指向 node-01 的 Controller”的 Worker。node-024 张卡4 个不同模型全部单卡CUDA_VISIBLE_DEVICES0 python3 -m fastchat.serve.vllm_worker \ --model-path meta-llama/Llama-2-13b-chat-hf --model-name llama-2-13b-chat \ --controller http://node-01:10002 --host 0.0.0.0 --port 31000 \ --worker-address http://$(hostname):31000 \ --tokenizer meta-llama/Llama-2-7b-chat-hf CUDA_VISIBLE_DEVICES1 python3 -m fastchat.serve.vllm_worker \ --model-path meta-llama/Llama-2-13b-chat-hf --model-name llama-2-13b-chat \ --controller http://node-01:10002 --host 0.0.0.0 --port 31001 \ --worker-address http://$(hostname):31001 \ --tokenizer meta-llama/Llama-2-7b-chat-hf CUDA_VISIBLE_DEVICES2 python3 -m fastchat.serve.vllm_worker \ --model-path meta-llama/Llama-2-7b-chat-hf --model-name llama-2-7b-chat \ --controller http://node-01:10002 --host 0.0.0.0 --port 31002 \ --worker-address http://$(hostname):31002 \ --tokenizer meta-llama/Llama-2-7b-chat-hf CUDA_VISIBLE_DEVICES3 python3 -m fastchat.serve.vllm_worker \ --model-path WizardLM/WizardLM-13B-V1.1 --model-name wizardlm-13b \ --controller http://node-01:10002 --host 0.0.0.0 --port 31003 \ --worker-address http://$(hostname):31003node-032 个 Worker各占 2 张卡用于超大模型python3 -m fastchat.serve.vllm_worker \ --model-path mosaicml/mpt-30b-chat \ --controller http://node-01:10002 --host 0.0.0.0 --port 31000 \ --worker-address http://$(hostname):31000 --num-gpus 2 python3 -m fastchat.serve.vllm_worker \ --model-path timdettmers/guanaco-33b-merged --model-name guanaco-33b \ --controller http://node-01:10002 --host 0.0.0.0 --port 31002 \ --worker-address http://$(hostname):31002 --num-gpus 2 \ --tokenizer hf-internal-testing/llama-tokenizer这里的两个细节--tokenizer覆盖Llama-2-13b-chat-hf模型仓库本身没有附带 tokenizer 文件文档统一指定用Llama-2-7b-chat-hf的 tokenizer 代替同理 guanaco-33b 指定 llama-tokenizer。这体现了 vLLM Worker 把 tokenizer 作为独立参数暴露的价值——模型权重与分词器解耦方便跨仓库复用。未指定--model-name时的默认行为node-03 第一条 mpt-30b 命令没有给模型名。从源码结构看Worker 的基类在model_names缺省时取model_path的最后一段作为注册名base_model_worker.py 的self.model_names model_names or [model_path.split(/)[-1]]即该模型会以mpt-30b-chat的名字进入 Controller 的模型列表。node-03 的两条命令没有CUDA_VISIBLE_DEVICES前缀可推断其依赖机器上仅有的两张卡或 Ray/vLLM 的默认设备分配若机器上还有其他 GPU建议按 node-01 的 33B 写法显式指定卡号避免与 Ray 的卡抢占冲突。五、node-04multi_model_worker 多模型共卡node-04 演示了另一种 Worker 形态——multi_model_worker.py它把多个模型放进同一个 Worker 进程适用于“小模型 多卡”的高密度部署官方注释也说明其典型场景是共享同一基座权重的多个 PEFT 模型CUDA_VISIBLE_DEVICES0 python3 -m fastchat.serve.multi_model_worker \ --model-path ~/model_weights/RWKV-4-Raven-14B-v12-Eng98%25-Other2%25-20230523-ctx8192.pth \ --model-name RWKV-4-Raven-14B \ --model-path lmsys/fastchat-t5-3b-v1.0 --model-name fastchat-t5-3b \ --controller http://node-01:10002 --host 0.0.0.0 --port 31000 \ --worker http://$(hostname):31000 --limit 4 CUDA_VISIBLE_DEVICES1 python3 -m fastchat.serve.multi_model_worker \ --model-path OpenAssistant/oasst-sft-4-pythia-12b-epoch-3.5 --model-name oasst-pythia-12b \ --model-path mosaicml/mpt-7b-chat --model-name mpt-7b-chat \ --controller http://node-01:10002 --host 0.0.0.0 --port 31001 \ --worker http://$(hostname):31001 --limit 4 CUDA_VISIBLE_DEVICES2 python3 -m fastchat.serve.multi_model_worker \ --model-path lmsys/vicuna-7b-v1.5 --model-name vicuna-7b \ --model-path THUDM/chatglm-6b --model-name chatglm-6b \ --controller http://node-01:10002 --host 0.0.0.0 --port 31002 \ --worker http://$(hostname):31002 --limit 4 CUDA_VISIBLE_DEVICES3 python3 -m fastchat.serve.vllm_worker \ --model-path ~/model_weights/alpaca-13b \ --controller http://node-01:10002 --host 0.0.0.0 --port 31003 \ --worker-address http://$(hostname):31003其实现机制multi_model_worker.py--model-path/--model-name可重复参数声明为actionappend每次出现追加一组按顺序两两对齐每个 path 内部再按逗号拆成该模型的多个注册名。启动时为一组组模型各创建一个ModelWorker子实例并建立worker_map[model_name] - 子worker的路由映射共享信号量限流由于同一进程内的子模型共享 GPU 内存源码把所有子 Worker 挂到同一个asyncio.Semaphore上multi_model_worker.py即文档中的--limit 4限制的是整卡的在途请求总数而不是单个模型的并发这比“每模型各限 4 并发”更保守、更贴合共享 GPU 的现实合并队列长度上报心跳/worker_get_status返回所有子模型队列长度之和multi_model_worker.py让 Controller 的shortest_queue策略能感知整卡负载该节点最后一张卡GPU3仍跑普通vllm_worker加载本地 alpaca-13b说明多种 Worker 类型可以混布在同一台机器、同一个集群中。六、集群验证test_message 与模型清单全部 Worker 拉起后文档给出的验证命令是python3 -m fastchat.serve.test_message --model vicuna-13b --controller http://localhost:10002从 test_message.py 的实现看这条命令完整走了一遍集群协议是很好的端到端自检先向 Controller 发/refresh_all_workers强制重新探测所有 Worker 存活状态再发/list_models打印当前集群注册的全部模型名通过/get_worker_address按模型名路由到一个 Worker用该模型对应的对话模板conversation template包装一条默认提示词POST 到 Worker 的/worker_generate_stream流式打印回复。如果命令打印出模型列表和流式回复说明注册、心跳、路由、推理四段链路全部打通如果输出No available workers for model则通常是该模型的 Worker 尚未注册成功或心跳被 Controller 判死对照controller.log与model_worker_*.log排查。除test_message外仓库还提供了一个压测脚本 test_throughput.py同样通过 Controller 地址 模型名工作可在集群拉通后评估吞吐。七、实战要点小结端口规划先行文档中每台机器的 Worker 都从 31000 起按卡号递增分配端口且--port必须与--worker-address中的端口一致否则 Controller 转发会失败--worker-address必须跨机可达这是集群部署和单机部署最大的区别。$(hostname)要求集群内各节点的主机名互可解析/etc/hosts 或 DNSController 所在节点node-01:10002必须能反向访问每个 Worker心跳参数按需调整Worker 每 45 秒心跳、90 秒过期constants.py均可用FASTCHAT_WORKER_HEART_BEAT_INTERVAL/FASTCHAT_CONTROLLER_HEART_BEAT_EXPIRATION环境变量覆盖卡分配策略小模型用CUDA_VISIBLE_DEVICES单卡钉死 多副本扩容超大模型用--num-gpus张量并行vLLM 场景需先ray start --head小模型群用multi_model_worker多模型共卡并整卡限流--limit模型名是路由的唯一键客户端Gradio 服务、OpenAI API Server、test_message等全部通过--model-name注册名请求模型部署时应保证命名清晰且不与model-path尾段产生歧义。以上命令与参数均可在当前仓库中逐一对应到源码实现集群路由与心跳见 controller.pyWorker 注册与限流基类见 base_model_worker.pyvLLM 多卡映射见 vllm_worker.py多模型共卡见 multi_model_worker.py端到端验证见 test_message.py。【免费下载链接】FastChatAn open platform for training, serving, and evaluating large language models. Release repo for Vicuna and Chatbot Arena.项目地址: https://gitcode.com/GitHub_Trending/fa/FastChat创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考