AWS发布多节点Ray LLM深度学习容器,支持在EKS上跨两块GPU节点做预填充/解码分离推理
AWS在一篇技术文章中介绍了多节点Ray LLM Deep Learning Container:在Amazon EKS上把同一模型拆到两块GPU节点,一块做预填充、一块做解码,通过NIXL借助EFA传输KV缓存,对外只暴露一个OpenAI兼容端点,整个服务应用由一段YAML定义。
AI解读:AWS表示该容器把vLLM、Ray Serve HTTP、NIXL和EFA栈(libfabric、aws-ofi-nccl)打包在一起,应用由build_pd_openai_app通过prefill_config与decode_config生成,无需手写handler、模型归档或自定义镜像。
预填充/解码分离的适用对象是需要跨节点运行超出单卡容量的模型、需要比单副本更高吞吐,或希望把两个推理阶段分开运行的用户;代价是KV缓存必须在节点间传输,因此节点间互连性能决定分离是否划算。
文章给出的示例配置中,两块g6.8xlarge分别运行预填充和解码,使用Qwen3.5-9B,max_model_len 4096、bfloat16、gpu_memory_utilization 0.90、enforce_eager为true,两者各设一个副本。
文中称,NIXL若无法使用libfabric会静默回退到TCP速度的传输,因此建议用worker日志确认实际后端;kv_connector_extra_config中必须写LIBFABRIC,否则默认走UCX,即使在EFA上也只有TCP速度。
文中还给出部署约束:GPU节点组需固定在同一可用区,因为EFA不能跨AZ;worker需privileged: true,以便NIXL把CUDA显存注册给EFA网卡,仅IPC_LOCK不够。
作者称在g6.8xlarge上加载Qwen3.5-9B,按文中缓存配置,模型权重重启加载时间从约 145 秒降到约 2 秒。这是该文针对特定机型与配置给出的单次测量。
AWS在机器学习博客中发布了一篇操作指南,介绍用多节点Ray LLM Deep Learning Container在Amazon Elastic Kubernetes Service(Amazon EKS)上部署单个大语言模型:模型跨两块GPU节点运行,一块负责预填充阶段,一块负责解码阶段,对外提供一个OpenAI兼容端点。文章署名作者为Ananth Raghavendra。
AWS称该容器随附Ray Serve LLM、NVIDIA Inference Transfer Library(NIXL)和Elastic Fabric Adapter(EFA)栈,无需应用代码;完整的示例代码在配套仓库中。
PD分离要解决的问题与文中给出的取舍
文章解释,LLM推理分为两个阶段:预填充并行处理整个输入提示并构建键值(KV)缓存,解码则逐个token生成响应并不断读取和扩展该缓存。预填充受计算限制,解码受内存带宽限制。两个阶段共用一个GPU时会争抢资源,突发的、计算密集的预填充会干扰稳定且对延迟敏感的解码。
把两个阶段放到不同节点后,每个阶段可独立选择硬件和服务属性,并可独立扩缩。AWS在文中指出代价:预填充阶段构建的KV缓存必须交给解码节点,这一传输必须足够快,否则分离带来的收益会被抵消,因此节点间的互连是关键。
- 预填充:计算受限,并行处理整个输入提示,构建KV缓存
- 解码:内存带宽受限,逐token生成,读取并扩展KV缓存
- 分离后的收益以KV缓存跨节点传输速度为前提
容器内容与示例配置
文章称,AWS Deep Learning Containers是预构建、性能优化的Docker镜像,把框架、依赖和GPU栈打包成经过测试和打过补丁的组合;所有组件在每次发布前一起验证,CUDA运行时、框架和服务层之间不会出现版本漂移,安全补丁在构建时应用。Ray LLM DLC把这一方式扩展到分布式LLM服务。
在该文的示例中,应用是manifest/rayservice.yaml里的serveConfigV2块,通过build_pd_openai_app接收prefill_config和decode_config,并在两者之间接上KV缓存传输,路由前缀为 /。示例使用Qwen/Qwen3.5-9B,两块阶段配置均设max_model_len 4096、dtype bfloat16、gpu_memory_utilization 0.90、enforce_eager true,各一个副本。
- 随附:vLLM(推理引擎)、Ray Serve HTTP(服务层)、NIXL(节点间KV缓存传输)、EFA栈libfabric与aws-ofi-nccl
- 两个阶段均使用NixlConnector,kv_role为kv_both,engine_id分别标记prefill与decode
- 必须设置kv_connector_extra_config的backends为LIBFABRIC,否则NIXL默认用UCX,在EFA上也按TCP速度运行
- enforce_eager true跳过CUDA图捕获以降低峰值显存,文中注明这取决于模型和输入
架构与部署步骤
文章描述,部署是一个位于虚拟私有云(VPC)内的EKS集群。节点在私有子网中,出站流量经NAT Gateway。一台CPU系统节点(m7i.xlarge)承载系统工作负载、KubeRay operator和Ray head pod(无GPU);两台GPU工作节点(g6.8xlarge)运行Ray worker,一台服务预填充阶段,一台服务解码阶段。两个节点都从Amazon ECR拉取Ray LLM DLC,KubeRay监听所应用的RayService并自动完成head与worker的连接。
KV缓存通过NIXL从预填充worker流向解码worker,走NIXL的libfabric后端使用EFA。GPU节点组固定在同一可用区,因为EFA不能跨可用区。worker pod各请求一个GPU和一个EFA接口,并以privileged: true运行,因为NIXL要把CUDA显存注册到EFA网卡,仅IPC_LOCK不够;同时设置FI_PROVIDER=efa,从pod IP读取VLLM_HOST_IP并挂载共享内存卷。
- 前提条件包括:启用计费的AWS账户、目标区域至少 64 vCPU的配额(两块g6.8xlarge)、AWS CLI、kubectl、eksctl、helm和envsubst
- 部署分四步:创建EKS集群(全新运行约 15–20 分钟)、添加GPU节点组(启用EFA,约 5–20 分钟)、用Helm安装KubeRay operator(约 1–2 分钟)、应用RayService(每个节点都要加载模型,需数分钟)
- 调用方式:对ray-llm-serve-svc做端口转发后,请求 /v1/models或标准 /v1/chat/completions
- 清理顺序:删除RayService、卸载KubeRay operator、删除GPU节点组、删除EKS集群
验证EFA与现有测量结果
文章提醒,如果NIXL无法使用libfabric,它会回退到TCP速度的传输且不会报错,因此值得确认它实际选择的后端,方法是grep worker日志中的“Backend (LIBFABRIC|UCX) was instantiated”。deploy_node_group.sh在创建节点组时也会打印每个节点上vpc.amazonaws.com/efa的数量;如需跨节点带宽数字,镜像自带 /usr/local/bin/all_reduce_perf中的NVIDIA NCCL基准。
文章给出的一项测量是:在g6.8xlarge上按前述缓存配置加载Qwen3.5-9B模型,重启时模型权重加载从约 145 秒降到约 2 秒。这是作者针对该机型与配置的陈述,文章未提供吞吐或延迟的端到端对比数据。
- NIXL静默回退:未使用libfabric时不报错,需查日志确认
- 文中称加载时间从约 145 秒降至约 2 秒,适用对象为g6.8xlarge上的Qwen3.5-9B及文中缓存配置
- 文章未给出分离相对不分离的端到端性能提升幅度