部署方案
大模型服务化部署通常采用什么架构?如何实现负载均衡和弹性伸缩?¶
大模型(LLM)服务化部署的典型架构分层如下:
-
接入层:提供统一 API 端点(通常兼容 OpenAI API 格式),处理鉴权、限流、请求路由。通常由 API 网关(如 Nginx、Kong、Envoy)承担,支持 HTTP/2、gRPC、WebSocket 流式输出。
-
调度层(Orchestrator / Dispatcher):接收并解析请求,根据模型类型、请求优先级、长度预估、负载状态等,将请求分发至后端的推理实例。调度器可能是无状态的独立微服务,通过消息队列(Kafka、Redis Streams)或直接 RPC 与推理引擎通信。
-
推理引擎层(Inference Engine):运行在 GPU 节点上的高性能推理运行时,如 vLLM、TensorRT-LLM、SGLang 等。每个引擎进程掌管一个模型副本,负责 Continuous Batching、KV cache 管理、模型计算。
-
模型存储与版本管理:模型权重存储在分布式文件系统(如 HDFS、S3、MinIO、NFS)或模型注册中心(MLflow、Harbor 等),推理实例启动时通过高速网络加载或 mmap。
-
基础设施与编排层:基于 Kubernetes(K8s)进行容器化编排,配合 Operator(如 KubeRay、Triton Inference Server 的 K8s 部署)管理推理 Pod 的生命周期。
负载均衡实现:
-
基于请求特性的路由:调度器根据请求类型(prefill 权重还是 decode 权重)分发到不同优化策略的实例组。对于长 prompt、短 prompt 或实时/批量请求,可采用独立实例池。
-
最少连接 / 最短队列:监控每个推理实例的队列深度(当前并发 batch 大小、等待请求数),新请求被导向负载最轻的实例。引擎常直接暴露/metrics端点,供调度器决策。
-
一致性哈希:如果某些请求需要前缀缓存(Prefix Caching)以提高性能,可通过一致性哈希将相同前缀的请求路由到同一实例,最大化缓存命中率。
-
引擎内负载均衡(多卡分布式):当使用张量并行(TP)或流水线并行(PP)将一个模型分布在多卡/多节点时,推理框架内部使用 NCCL 通信,对外表现为一个逻辑实例,负载均衡单元只需与该实例通信。
弹性伸缩实现:
-
基于 GPU 利用率的水平伸缩(HPA):监控 GPU 计算利用率(SM 占用)或 KV cache 使用率(显存压力),当超过阈值(如 80%)则增加推理 Pod 副本;低于阈值则缩减。需配合 K8s 的 HPA 或定制 Controller。
-
基于请求队列长度的伸缩:若等待请求数持续大于 0,则自动扩展实例。常通过 Prometheus 采集指标,由 KEDA(Kubernetes Event-driven Autoscaling)触发伸缩。
-
预热与模型加载优化:新实例启动需加载模型权重(几十 GB),为减少冷启动延迟,可利用节点本地 SSD 缓存、P2P 分发(如 Dragonfly)、或使用模型预热容器(init container)提前下载。也可配合内存快照(例如 vLLM 的模型状态保存/恢复)加速。
-
混合 GPU 资源池:结合不同 GPU 型号(A100, H100)的节点池,通过标签选择器将不同 SLA 的请求调度到不同硬件,精细化成本控制。
-
Serverless 推理:极端场景下可将模型包装成无服务函数(如 KNative),请求驱动伸缩到零,适合间歇性调用,但冷启动是挑战。
如何评估推理服务的性能指标?如 TTFT、TPOT、吞吐量。¶
核心指标围绕延迟和吞吐,需在特定负载和并发下测量:
-
TTFT(Time to First Token,首令牌时间):从请求到达服务端到返回第一个生成的 token 之间的延迟。它反映 prompt 处理效率、调度排队延迟和 prefill 计算速度。低 TTFT 对交互式应用至关重要。
-
TPOT(Time per Output Token,每输出令牌时间):生成阶段相邻两个 token 之间的平均时间(或中位数),也称为 ITL(Inter-Token Latency)。实际衡量的是每次自回归解码迭代的耗时。对于流式输出,TPOT 的平稳性直接影响用户体验。
-
总请求延迟:从收到请求到完整响应返回的总时间,即 TTFT + (输出长度 - 1) × 平均 TPOT。长文本生成场景下它是主要关注点。
-
吞吐量(Throughput):单位时间内成功生成的 token 总数(token/s)或完成的请求数(RPS)。分为:
- 单请求吞吐:单个请求的 token 生成速率(1/TPOT),受模型大小、序列长度影响。
-
系统总吞吐:在给定 SLA 下,整个系统能承载的最大总 token/s。通常用渐进增加并发请求数的方法测试,找到延迟可接受下的最大吞吐。
-
QPS(Queries Per Second):每秒完成的请求数。结合请求平均 token 长度可换算为 token/s。
-
批处理效率(Batch Size Utilization):Continuous Batching 中批次内实际活跃请求的平均数量与最大可能的比率,反映调度效率。
-
显存利用率:KV cache 已用块数 / 总块数,该值越高意味着能容纳更多并发请求,但也可能接近 OOM 风险点。
-
排队时间:请求在调度队列中等待被首次 picked 的时间。TTFT 减去理论纯计算 prefill 时间即可得出。
评估方法论:
-
使用标准化负载测试工具(如 vLLM 的 benchmark、Locust 定制脚本、GenAI-Perf),模拟真实输入/输出长度分布、到达率模式。
-
固定并发数,记录稳态下指标的百分位(P50, P90, P99),尤其关注尾延迟。
-
测量峰值压力下的降级行为,确定系统饱和点和最大有效吞吐。
在云原生环境部署 LLM,你如何利用 GPU 虚拟化(如 MIG)?¶
NVIDIA 的多实例 GPU(MIG)可将一块大显存 GPU(如 A100 80GB、H100)在硬件级别分割为多个独立的小 GPU 实例,每个拥有自己的显存、缓存和计算资源,且故障隔离。利用 MIG 可在云原生 K8s 中实现:
-
细粒度资源分片:将 1 个 80GB A100 切分成多个较小的 GPU 实例(如 3 个 20GB 的切片 + 1 个 10GB 切片),避免为小模型(如 7B 参数)独占整卡,浪费算力和显存。每个 MIG 实例分配给不同推理 Pod,可服务不同模型或多副本。
-
多模型共卡部署:在同一物理 GPU 上同时运行多个 LLM 推理实例(例如一个大模型独占大切片,几个小模型占小切片),资源共享且互相隔离,最大化 GPU 总利用率。
-
混合优先级服务:可将高优先级在线服务部署于计算资源更有保障的 MIG 实例上,较低优先级的批处理任务使用其余实例,避免互相干扰。
-
Kubernetes 集成:通过 NVIDIA MIG Manager 或 GPU Operator,将 MIG 设备以 Kubernetes 扩展资源(
nvidia.com/mig-1g.10gb)的方式暴露。Pod 可以按需申请精确的 MIG 实例,调度器将 Pod 绑定到对应物理 GPU 的切片。 -
热迁移支持不中断? MIG 的配置修改需重启 GPU 驱动,不能热切换,但可通过滚动更新 Pod、预先划分多种 MIG 几何配置来间接管理。通常将 MIG 配置作为节点池的静态划分,由节点选择器把不同规格的推理工作负载调度到匹配的节点。
注意:MIG 会引入一些限制(如 P2P 通信可能受影响,部分 CUDA 特性不支持),在采用前需评估推理框架兼容性。对于需要大显存带宽的大模型,或许整卡更优,但 MIG 对于中、小模型的多租户共卡效率提升极大。
模型热更新怎么实现?如何在不中断服务的情况下切换模型版本?¶
实现不停服切换模型版本,本质是把流量从旧模型实例平滑迁移到新模型实例,并可即时回滚。
主流方案:
-
蓝绿部署(Blue/Green):同时运行旧版本(Blue)和新版本(Green)的所有实例,待 Green 全部健康就绪后,通过 API 网关或调度器一次性将全部流量切到 Green。如果出现问题,瞬间切回 Blue。优点是简单,缺点是需要两倍硬件资源。
-
金丝雀(Canary)发布:新版本先拉起少量实例,导入少量比例流量(如 5%),观察一段时间(错误率、延迟等),确认无异常后再逐步提升流量比例至 100%,同时逐步缩减旧实例。可通过 Service Mesh(如 Istio)或 API 网关的加权路由精准控制。
-
滚动更新(Rolling Update):K8s 原生支持的 Deployment 策略,逐个将旧 Pod 替换为新 Pod。为了不中断服务,需配合健康检查与优雅终止:
- 推理框架需支持优雅退出:收到 SIGTERM 后,完成当前正在处理的请求,同时不再接受新请求。
- 配合调度器的排空(Drain)功能,通知负载均衡器该实例即将下线,新请求不再发往该实例。
-
需确保至少一个实例始终可用,且 KV cache 切换时会导致正在进行的请求被丢弃(除非做状态迁移,极难)。因此对长连接流式请求,热更新会造成中断,需由客户端重试或设计应用层容错。
-
推理引擎内模型热切换:部分框架(如 Triton Inference Server)支持同一个进程内动态加载/卸载模型版本。当新模型加载到 GPU 显存后,Triton 自动将新请求路由到新版本,旧版本在所有进行中请求完成后被卸载。这要求显存足够容纳新旧双模型,切换粒度更细。对于显存紧张场景,可采用「先缩容旧模型,加载新模型,再扩容」的操作顺序。
-
共享 KV Cache 前缀的极限方案:如果新老模型只是 LoRA adapter 或部分权重不同,可通过只替换特定参数矩阵而不重启,实现真正的零停机。但如为全量模型变动,必须重载权重。
最佳实践:在 K8s 中使用 Deployment 滚动更新 + preStop hook 通知引擎暂停接收新请求并等待排空;配合 Envoy/Istio 实现流量的一键加权切换与健康检查,可实现数分钟内完成无感知的模型版本升级。
多租户场景下,推理服务如何实现安全和资源隔离?¶
多租户指不同用户或团队共享推理集群,需在性能和安全性上严格隔离。
资源隔离:
-
硬件级(MIG/GPU 分区):对高等级租户,可独占一个 MIG 实例甚至整张 GPU,彻底避免显存、计算和缓存的竞争。
-
显存与计算隔离:在共享推理引擎中,通过配额机制限制每个租户的并发请求数、最大输入+输出总 token 数、可使用的 KV cache 内存上限。调度器跟踪租户使用量,超量即返回限流错误。
-
GPU 时间片隔离:使用 CUDA MPS(Multi-Process Service)或 vGPU 技术,在软件层面隔离上下文;但安全性和性能隔离不如 MIG 彻底,适用于隔离要求不高的场景。
-
网络与存储隔离:不同租户的模型权重存储可位于不同 bucket,通过独立凭证访问;推理 Pod 通过 NetworkPolicy 限制通信,仅允许与调度器和存储的必要交互。
安全隔离:
-
API 鉴权与认证:每个租户分配独立的 API Key,API 网关进行鉴权,识别租户身份。
-
数据隔离:同一引擎同时服务多租户时,请求数据(prompt、生成的文本)通过逻辑隔离保障。调度器绝不会将 A 租户的请求发送给 B 租户专属的实例;共享实例内部需保证请求间不存在数据泄露(例如 batch 中不同序列相互不可见,注意力掩码硬隔离)。应禁止将租户数据用于任何形式的缓存复用,除非该缓存是租户专属且加密隔离。
-
推理内容安全:即使模型共用,也要保证租户 A 不能通过 prompt 注入读取其他租户的上下文(共享 prefix cache 除外,但 prefix cache 通常只缓存系统公共提示,不缓存用户私人历史)。可通过每次请求时清空聊天历史、使用唯一会话 ID 隔离 KV cache 页,实现会话级隔离。
-
代码执行与依赖:如推理平台支持用户自定义预处理/后处理函数,必须置于严格沙箱(如 gVisor、WebAssembly)运行,避免逃逸。
多租户调度策略:
-
可为每个租户设置独立的请求队列,并使用权重公平调度(WFQ)防止某个租户的突发流量饿死其他租户。
-
在过载时,按租户级别进行优先级抢占和限流,保障 SLA 承诺高的租户资源。
如果要在移动端运行一个小型 Transformer 模型,你会选择什么框架?技术路线是什么?¶
框架选择:
-
llama.cpp(通过其 C++ 库以及移动端优化):GGUF 量化格式 + 整型内核,支持 Android (通过 NDK) 和 iOS (通过 Metal 或 CPU NEON)。已有成熟的移动端 LLM 应用案例(如 Ollama 间接支持,或直接编译)。
-
Google MediaPipe 或 TensorFlow Lite:专门为移动端优化的推理框架,支持 GPU delegate(OpenGL ES / Metal),可运行小型 Transformer(如 MobileBERT)。对量化、剪枝友好,但需模型转换为 TFLite 格式。
-
ExecuTorch(PyTorch 出品):PyTorch 的端侧推理解决方案,支持 8-bit 量化、Metal 后端、Android 上 Vulkan 委托,生态迅速完善,非常适合从 PyTorch 训练导出的 Transformer 模型。
-
ONNX Runtime Mobile:支持 INT8 量化、多种执行提供器(如 CPU, XNNPACK, 以及有限的 GPU),跨平台易用,但 Transformer 类模型需仔细适配融合。
技术路线:
-
模型压缩:从大模型出发,通过蒸馏、结构化剪枝、低秩分解得到参数量 < 1B 的小模型(如 TinyLLaMA、Phi 系列)。或直接从开源预训练小模型开始。
-
量化:应用 4-bit 或 8-bit 的整数量化(INT4/INT8),常见方案为 GPTQ、AWQ 或 GGUF 的 K-quants。重点是采用块状量化和混合精度,尽量减少在移动端 CPU 上的精度损失。也可使用带有整数激活的量化方案以完全避开浮点运算。
-
框架编译与优化:将量化后的模型导出为对应移动框架的格式(如
.gguf或.pte),使用厂商提供的编译器/转换工具进行运算符融合、内存规划优化。 -
移动端运行时集成:
- Android:使用 JNI 调用 C/C++ 推理库(如 llama.cpp 的 Android 编译),或集成 ExecuTorch 运行时。可充分利用 NEON SIMD 加速。
-
iOS:利用 Core ML 将模型转换为
.mlmodelc并利用 ANE(Apple Neural Engine)加速;或直接使用 Metal Performance Shaders 后端(如 llama.cpp 的 Metal 支持),在 GPU 上运行量化计算。 -
性能与内存优化:对移动端内存极度敏感,需要:
- 使用 mmap 直接映射模型文件,延迟加载,避免全部读入内存。
- 优化 KV cache 占用,可结合滑动窗口注意力或 PagedAttention 的块管理思想,限制最大缓存长度。
-
限制并发请求,单线程推理,防止 APP 卡顿。
-
应用层优化:流式输出、预测即输入,对延迟敏感的 UI 采用异步处理,必要时可在 App 后台预热模型。
典型路线:选用预训练小模型(如 Qwen2-0.5B)→ 使用 llama.cpp 进行 Q4_K_M 量化 → 编译 Android 库集成到 APP → 使用 JNI 流式推理,延迟可控制在每 token 几十毫秒。
推理时是否可以使用 CPU 与 GPU 混合执行?哪些层适合放 CPU?¶
可以。混合执行也称异构推理,在 LLM 场景下可将部分计算卸载到 CPU/内存,以弥补 GPU 显存不足或利用 CPU 的特定优势。
哪些层适合放在 CPU 执行:
-
Embedding 层:输入 token 的嵌入查找通常是对权重矩阵的单纯查表,计算量小,显存占用巨大(vocab_size × hidden_dim),且可以高效运行在 CPU 上,并利用 CPU 的大容量内存。将 Embedding 权重放在 CPU 可节省数 GB 显存。
-
输出层(LM Head):最后一层的线性投影 + 采样,权重形状也为 vocab_size × hidden_dim,同样占显存较大,可放在 CPU 计算 logits 并采样,将结果 token id 传回 GPU。这在 llama.cpp 等框架中是常用策略。
-
LayerNorm / RMSNorm:这些逐元素操作计算量极低,但需要显存带宽;放在 CPU 无速度优势,通常还是放 GPU。但对于某些极端显存不足情况,也可卸载。
-
低活跃度的子层(MoE 共享部分或某个注意力头):若采用 MoE 架构,可将某些 expert 放在 CPU 内存,在需要时通过 PCIe 传输激活值,实现 CPU-GPU 协同(例如 DeepSpeed-Inference 的 ZeRO-Inference 特性)。
-
KV Cache 的交换:当 GPU 显存不够时,可将部分层或部分序列的 KV cache 卸载到 CPU 内存(swap out),只在注意力计算时异步拷贝回 GPU。这是 PagedAttention swap 机制的物理基础。
实现框架:
-
DeepSpeed-Inference / ZeRO-Inference:提供高效的 CPU/GPU 内存池管理,可自动将权重和 KV cache 分布到不同存储,并进行最小化数据传输的调度。
-
llama.cpp:在 GPU 后端下,可配置
-ngl参数指定多少层放到 GPU,剩余层留在 CPU 运行,实现逐层混合执行。 -
手工定制推理引擎:通过 CUDA 的
cudaMallocManaged或显式拷贝,在自定义推理循环中指定每个算子的执行设备,实现流水线掩盖传输延迟。将 embedding 和 LM head 永久置于 CPU,在预填阶段预取 embedding 到 GPU,后处理阶段从 GPU 取 hidden state 到 CPU 计算 logits。
混合执行的关键是隐藏 PCIe 延迟:通过异步拷贝与计算重叠,例如在 GPU 执行第 N 层时,CPU 侧可预计算下一迭代所需的 embedding 或执行 logits 采样,使得传输开销几乎不可见。
低延迟交互场景(如语音助手)中,如何优化 Transformer 推理的尾延迟?¶
语音助手要求 TTFT 和 TPOT 的 P99 延迟都非常低(通常 < 200ms TTFT,TPOT < 30ms),尾延迟优化是核心。
-
提前退出(Early Exit):在 Transformer 的多层堆叠中插入多个分类头,一旦中间层的置信度超过阈值就提前停止计算,大幅减少短回复的推理深度。结合知识蒸馏让浅层输出质量提高。
-
投机采样:用极小的草稿模型并行预测,降低大模型调用频率,并减少每个 token 的有效延迟抖动。
-
Chunked Prefill 与优先级调度:语音助手常有较长的对话历史(prompt 长),若一次性 prefill 会拉长 TTFT。将 prefill 切成小块与 decode 混合执行,可平滑处理长上下文,并允许新到达的高优请求更快插队。调度器始终优先调度新到达的简短交互。
-
KV Cache 前缀缓存:语音助手常以固定的系统 prompt 开始,将其 KV cache 永久缓存在显存中,所有请求复用,TTFT 可降低数十倍。
-
量化与内核调优:使用 INT8/FP8 量化降低数据传输时间,并使用针对 decode 极致优化的低延迟内核(如 FlashDecoding),减少每次迭代的偏差。
-
流式传输与解耦:输出 token 一旦生成即刻推送给客户端,同时并行执行下一 token 生成,从感知上降低延迟。语音合成(TTS)可在首个 token 收到后就启动音频合成,实现流水线。
-
资源隔离与过载控制:为语音交互保留专用的推理实例或 MIG 分区,避免被其他批量任务影响;并启用严格的并发限制,一旦超过并发数立即排队或降级,防止资源争抢导致的尾延迟爆炸。
-
通信与系统优化:优化服务端网络栈(使用 DPDK 用户态协议栈、gRPC 异步流、WebSocket 等),降低请求-响应的系统抖动;利用 NUMA 绑定减少 CPU-GPU 通信延迟。
-
预热与模型驻留:保持模型常驻 GPU 显存,杜绝冷启动;并将执行器与 CUDA context 预热好,排除首次调用 Kernel 的额外延迟。
综合手段:通过投机采样 + 前缀缓存 + 提前退出 + 专用硬件分区,可实现语音助手场景下苛刻的 P99 延迟。
监控推理服务的哪些关键指标可以提前发现性能劣化?¶
构建可观测性系统,重点关注:
-
延迟百分位:TTFT、TPOT、请求总延迟的 P50、P90、P99。当 P99 大幅上升,表示出现长尾阻塞,可能是队列堆积或 GC 影响。
-
吞吐量(token/s, RPS):持续监测总吞吐量,若在流量平稳时突然下降,说明推理效率降低(如 KVCache 碎片化、显存带宽瓶颈)。
-
请求排队深度:调度队列中等待处理的请求数。持续增长意味处理能力不足或调度异常,需扩容。
-
GPU 计算利用率(SM 活动率):高吞吐时此值应接近 100%。若下降,说明 kernel 执行中等待数据(内存带宽受限)或存在 CPU 瓶颈。
-
GPU 显存使用率与 KV Cache 占用率:当 KV Cache 块使用率接近 100% 时,极易引发 swap 或拒绝请求。突然下降可能表示 cache 碎片严重或内存泄漏。监控“可用块数”趋势。
-
CPU 使用率:推理服务的主机和 CPU 端服务(分词、调度、数据传输)的 CPU 利用率。若 CPU 成为瓶颈,GPU 会“挨饿”。需特别关注预处理开销。
-
网络指标:服务端与客户端间及多 GPU 节点间通信的延迟和带宽。NCCL 通信异常会导致分布式推理 hang 或大幅变慢。
-
错误率:按错误类型分类(4xx 用户错误、5xx 服务错误、OOM 错误、超时错误)。5xx 或 OOM 的突增直接指示服务劣化。
-
请求端到端成功率与超时率:客户端视角的指标,反映真实用户体验。
-
模型加载/卸载时间:热更新时模型的加载耗时,若显著变长,说明存储或网络有问题,影响弹性能力。
-
操作系统级指标:磁盘 I/O(模型权重加载)、上下文切换、内存带宽饱和度等,辅助定位瓶颈。
通过 Grafana 等面板关联上述指标,可设定预警规则:例如“当 P99 TTFT 超过 500ms 且排队深度>10 持续 5 分钟”触发报警,或在 KVCache 可用率 < 20% 时自动触发扩容。
设计一个能够同时服务多个下游任务的 LLM 推理平台,关键技术点有哪些?¶
一个多任务推理平台需要在统一的基础设施上高效支持摘要、翻译、代码生成、对话等多样化任务,核心挑战是任务隔离、资源复用、差异化优化和易用性。
关键技术点:
- 模型仓库与多模型管理:
- 支持多种模型(不同参数量、不同架构)的注册、版本控制、安全扫描和自动加载。平台可同时运行多个模型实例(或 LoRA 适配器),根据任务路由到不同模型。
-
利用 PagedAttention 的内存池统一管理不同模型的 KV cache 块,提升显存复用。
-
自适应批处理与调度:
- 智能路由器,解析请求的模型名、任务类型(chat/completion/embeddings)、预估长度和优先级,将其分派到对应的推理引擎实例或 LoRA 组。
- 全局调度器负责在多个模型实例间实现公平的 GPU 资源共享(时间片或加权调度),防止一个任务占满资源。
-
对于共享基础模型但不同 LoRA 的任务,可在同一批次中混合服务多个 LoRA 适配器(vLLM 已支持),大幅提升硬件利用率。
-
多模态与异构任务支持:
- 扩展引擎以处理图像、音频等多模态输入(多模态 Transformer),需要融合视觉/音频编码器,统一 token 生成流水线。
-
对 embedding 任务(无需生成,只有 prefill)和生成任务(prefill+decode)进行分离优化,前者可快速批量完成,后者需要 Continuous Batching。
-
前缀缓存与任务模板:
-
许多任务共享系统提示或任务前缀(如“将以下文本翻译为法语:”),平台应自动识别并缓存这些前缀的 KV cache,跨请求复用,大幅降低高并发下相同任务的延迟与计算开销。
-
多租户隔离与计费:
-
实现以项目/团队为单位的资源配额,按 token 使用量精确计费。对每个租户的请求限流、优先级控制,并确保数据和模型隔离(对于私有模型或微调适配器,需加载到专用显存区域)。
-
LoRA/适配器即服务:
-
提供在线热插拔 LoRA 适配器能力,允许用户上传、管理自有微调适配器,平台自动挂载到底座模型上。需适配器权重安全隔离、版本化、度量其推理成本。
-
弹性伸缩与成本优化:
- 不同任务有不同波峰波谷,平台应能对每种模型实例进行独立的弹性伸缩,甚至利用 Spot 实例承载可中断的批处理任务,降低成本。
-
对延迟不敏感的任务可排队并合并批次,增大 batch size,提升吞吐。
-
观测与反馈闭环:
- 记录每条请求的详细 trace(包括模型、任务、长度、延迟、适配器等),提供租户维度和任务维度的性能报表。
-
基于反馈自动优化调度策略(如调整不同任务的权重、调整批处理参数)。
-
统一网关与开发者体验:
- 提供与 OpenAI API 兼容的统一接口,屏蔽底层多模型的复杂度。开发者只需指定
model字段(可映射到具体模型+任务组合),即可调用。
通过上述设计,平台能以一种经济高效的方式,在一套集群中同时服务差异化的下游任务,并具备良好的可扩展性和观测性。
在 Kubernetes 中部署 LLM 推理服务,如何配置 HPA 实现自动伸缩?指标用 GPU 利用率还是队列长度?¶
在 K8s 中为 LLM 推理服务配置水平自动伸缩(HPA),核心是选择能真实反映服务质量与资源饱和度的指标。推荐以队列长度或请求等待数作为主要伸缩信号,GPU 利用率作为辅助参考。
为什么队列长度优于 GPU 利用率?
-
GPU 利用率(SM 活动比例)主要反映计算单元忙碌程度。但 LLM 解码阶段往往是内存带宽受限,Tensor Core 利用率可能并不高(甚至 30%~50%),而请求却大量积压。此时 GPU 利用率可能无法准确指示需要扩容。
-
推理引擎内部通常有 pending queue(等待被编入 Continuous Batching 的请求数)。该队列长度与用户感知的 TTFT 直接相关,能真实反映服务过载程度,且不受 GPU 架构差异影响。
具体配置步骤:
-
暴露自定义指标:在推理框架中,将实时队列长度上报到 Prometheus。vLLM 等可直接暴露
/metrics接口,包含vllm:num_requests_waiting或类似的等待请求数指标。 -
安装 Prometheus Adapter:配置
CustomMetricAPI,将 Prometheus 中的num_requests_waiting映射为 K8s 自定义指标。 -
创建 HPA 对象,参考配置:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: llm-inference
minReplicas: 1
maxReplicas: 10
metrics:
- type: Pods
pods:
metric:
name: num_requests_waiting
target:
type: AverageValue
averageValue: "2" # 期望每个 Pod 平均排队不超过 2 个请求
- 结合 GPU 利用率:可添加 GPU 利用率作为上限指标,防止单纯队列信号导致扩容过猛。例如当 GPU 利用率连续 5 分钟超过 80% 再配合队列长度触发。
高级策略:
-
使用 KEDA 基于事件伸缩:除了 Prometheus,KEDA 可对接 Redis、Kafka 等消息队列,更适合异步离线批处理推理的伸缩。
-
冷却策略:推理服务扩容后模型加载耗时较长(数十秒到数分钟),需设置较长的缩容冷却时间(如 300 秒)避免 Pod 反复启动。
-
预热机制:新 Pod 启动后需要预热模型、预热 CUDA context,可通过
init container或框架的 warmup 请求,并在就绪探针确认可服务后再被加入负载均衡。
综上,队列长度为核心,GPU 利用率为辅助,能让伸缩更贴合服务质量目标。
如果要同时提供高吞吐离线推理和低延迟在线服务,如何设计统一的推理平台?¶
设计统一平台需在资源隔离、调度策略、请求路由上做出区分,保证两种负载互不干扰。
-
物理/逻辑资源池隔离
-
通过 K8s 节点池划分:给在线服务分配带有高优保障的 GPU 节点(如按需实例),设置污点与容忍度,确保在线 Pod 独占或优先使用;离线任务可使用廉价 Spot 节点、或在线节点的低优资源池。
-
在线实例常驻运行,始终保持预热;离线实例可弹性伸缩甚至缩零。
-
调度层优先级与抢占
-
在请求入口处打上优先级标签(如
latency-criticalvsthroughput)。调度器维护多个队列。 -
在线请求可抢占离线请求的资源:利用 PagedAttention 的 swap 机制,将离线请求的 KV cache 块换出到 CPU 内存,让出显存给在线请求,处理完后再换回。
-
若使用统一实例混合服务,引擎内部需支持优先级队列,保证在线请求优先被编入 batch,离线请求填充剩余算力。
-
分离 Prefill 与 Decode 的调度
-
离线批处理常涉及巨量 prompt 的 prefill,这会导致迭代时间尖刺。可将 Prefill 与 Decode 拆分到不同实例组,在线 decode 实例只处理 decode 和短 prefill,离线 prefill 由专用实例完成。调度器根据请求阶段智能路由。
-
或采用 chunked prefill,把长 prefill 切分,在 decode 批次中插空执行,降低对在线响应的干扰。
-
统一模型仓库与配置
-
平台维护同一份模型权重,通过 model registry 加载。在线和离线实例启动时,可从同一分布式存储(如 S3、PVC)加载模型。
-
使用相同的推理引擎和运行时版本,方便监控、运维和更新。
-
超额订阅与成本优化
-
在线服务保障严格 SLA,可超额部署少量离线实例。当在线负载低时,离线实例启动,充分利用空闲 GPU。通过 K8s HPA 和 KEDA 根据离线队列长度自动伸缩,将成本降至最低。
-
隔离与观测
-
对不同类型服务打上独立 label,分别监控 P50/P99 延迟、吞吐、排队时间。设定 SLO,对在线服务设置预警阈值,离线服务只需关注成功率和完成时间。
通过“隔离资源 + 优先级调度 + 混合池”的方案,单一平台可以同时承载高吞吐离线与低延迟在线推理,实现硬件利用率最大化。
如何实现推理服务的“金丝雀发布”,逐步将流量切换到新模型版本?¶
金丝雀发布的核心是将少量真实流量导入新版本,验证其稳定性和质量后逐步扩大占比,同时可随时回滚。
步骤详解:
- 部署新旧两个 Deployment
- 旧版本:
llm-v1,保持现有流量。 -
新版本:
llm-v2,使用新模型镜像、权重或适配器。初始设置replicas为较小数量(如 1 个 Pod),待正常启动。 -
借助 Service Mesh 或 Ingress 实施流量分割
- 使用 Istio VirtualService 实现细粒度加权路由:
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: llm-inference
spec:
hosts:
- llm-service
http:
- match:
- headers:
canary:
exact: "true"
route:
- destination:
host: llm-v2
- route:
- destination:
host: llm-v1
weight: 95
- destination:
host: llm-v2
weight: 5 # 5% 流量到 v2
-
同时可配合 header、cookie 等将特定测试用户或内部账号绑定到 v2,进行定向测试。
-
若无 Service Mesh,可使用 Nginx Ingress 的
canary注解实现基于权重的分流。 -
逐步调整权重并观测
- 初始 5% 流量导入 v2,持续观察 15~30 分钟。关键指标:错误率、P50/P99 TTFT/TPOT、OOM 事件、输出质量抽样结果(可通过自动化评估)。
-
无异常后将权重调至 25% → 50% → 100%。每次提升后监控一段时间。
-
处理长连接与流式请求
- LLM 推理通常为流式 gRPC/WebSocket 长连接,连接建立时路由到特定版本后,直到会话结束不应切换版本,否则会因 KV cache 丢失而中断。
- Istio 支持
consistentHash基于 session id 或 token,保证同一会话粘滞到固定 Pod,直到其完成。 -
金丝雀发布过程中,旧版本 Pod 可设置为优雅终止,等待所有活跃长连接关闭后再退出。
-
回滚机制
- 如发现问题,立即将新版本权重置为 0,流量全部切回 v1。然后排查并撤回 v2 部署。
- 由于推理服务的状态性(KV cache),回滚只会影响新建立的会话,旧 v2 的会话可能报错,但影响面小。
补充要点:
-
模型前置缓存:使用公共前缀缓存(如系统提示)时,v2 需预热自己的缓存,避免初期延迟尖刺。
-
自动化部署流水线:集成到 CI/CD 中,利用 Argo Rollouts 或 Flagger 实现指标驱动的金丝雀发布自动化(例如,自动检测延迟超过阈值则自动回滚)。
通过金丝雀发布,可在生产环境中安全地验证模型更新,将风险控制在极小范围。
多租户下,使用 GPU 的 MIG 模式与时分复用模式,分别适合什么场景?¶
| 特性 | MIG(多实例 GPU) | 时分复用(Time-slicing/MPS) |
|---|---|---|
| 隔离级别 | 硬件级:显存、缓存、计算单元完全隔离 | 软件级:显存无隔离,算力时间片轮转 |
| 显存划分 | 静态切分,每实例固定显存大小 | 共享整个显存,易出现 OOM 争抢 |
| 性能可预测性 | 极高,每个 MIG 实例性能稳定,无干扰 | 较低,一个实例的 kernel 执行可能阻塞其他 |
| 灵活性 | 低:划分固定,修改需重启 GPU | 高:动态共享,可超量使用,配置简单 |
| 资源利用率 | 可能产生碎片,如切分后小模型无法用满算力 | 高利用率,超量复用可能最大化吞吐 |
| 多租户场景 | 严格隔离需求,SaaS 化服务不同客户;或不同 SLA 等级服务 | 内部团队共用,突发负载互借资源;离线批处理混合 |
| 对 Tensor Parallel 等分布式推理支持 | 受限:MIG 实例间不能 P2P 通信,无法做 NCCL 跨实例归约 | 支持:MPS 下多进程共享 GPU,P2P 可用,适合 TP |
| 显存保护 | 有,单个实例的 OOM 不影响其他 | 无,一个进程 OOM 可能导致整卡崩溃或驱逐 |
适合 MIG 的场景:
-
需要严格资源配额的多租户云服务,为每个客户分配独立 GPU 切片,保证性能和故障隔离。
-
在单 GPU 上同时运行多个不同的小模型(如多个 LoRA 服务),每个模型给予固定算力和显存,避免互相拖慢。
-
高安全合规要求,不希望数据通过侧信道或缓存残留被其他租户访问。
适合时分复用(MPS / vGPU 时间片)的场景:
-
内部多个团队共享大型 GPU 集群,请求负载峰谷交错,通过超额订阅提高整体利用率。
-
模型较大的情况,单 MIG 切片显存可能不够,必须共享整卡显存。
-
需要分布式推理(TP)时,不能切分 MIG,只能使用整卡 MPS 或直接共享。
-
成本敏感,希望尽量榨干 GPU,不介意偶发的性能抖动。
综合来看,MIG 提供“硬隔离、稳性能”但牺牲灵活度;时分复用提供“高灵活、低成本”但隔离性差。实际平台可以混合使用:高优租户分配 MIG 独占切片,低优离线任务共用剩余整卡并打开 MPS 提升利用率。
端侧模型部署时,如何利用手机 NPU 加速 Transformer?通常需要哪些算子支持?¶
手机 NPU(神经网络处理单元)是专门为低功耗 AI 推理设计的异质计算单元,擅长定点矩阵运算和卷积,能效比远高于 CPU/GPU。利用 NPU 加速 Transformer 的主要步骤如下:
-
模型量化与格式转换
-
将 Transformer 量化为 INT8 或 FP16。NPU 通常对 INT8 有最佳效能,所以常用训练后量化(PTQ)或量化感知训练(QAT)得到 INT8 模型。
-
导出为 NPU 厂商支持的中间格式。例如:
- 高通 Hexagon NPU:使用 SNPE(Snapdragon Neural Processing Engine)或 QNN(Qualcomm Neural Network),将 ONNX/TensorFlow 模型转换为
.dlc或 QNN 格式。 - 苹果 ANE(Neural Engine):通过 Core ML Tools 将 PyTorch/TF 模型转为
.mlmodelc,并启用computeUnits= .all来使用 ANE。 - 联发科 APU:NeuroPilot SDK 转换 ONNX 模型。
-
通用路径:使用 ExecuTorch 并选择相应委托(Delegate),如高通的 QNN Delegate,Apple 的 Core ML Delegate,以及 Android 的 NNAPI Delegate。
-
算子支持与降级策略
Transformer 核心算子及 NPU 支持情况:
-
全连接(Linear):普遍支持,是 NPU 强项。
-
矩阵乘法(BMM/MatMul):大部分支持,但注意维度限制。Attention 中的 QK^T 乘需要 BMM,一些 NPU 仅支持 2D 矩阵乘,需要 reshape 适配。
-
层归一化(LayerNorm/RMSNorm):许多 NPU 支持 ReduceMean、Element-wise 乘加,可组合实现;部分 NPU 直接支持 LayerNorm 算子。
-
Softmax:高通 QNN 支持,Apple ANE 从某版本起支持。但需注意大长度序列 Softmax 可能被拆分。
-
Attention:整块的 FlashAttention 类融合操作一般不被 NPU 直接支持,需分解为基础算子。
-
激活函数(GELU/SiLU):多数 NPU 已内置支持。
-
位置编码:较容易用张量操作组合。
-
卷积:不常用但 NPU 极擅长,若模型包含卷积子层(如一些轻量混合模型)更友好。
面对不支持的算子,框架会插入 CPU/GPU 回退。例如 Core ML 将不支持的子图自动切回 CPU 或 Metal GPU;ExecuTorch 在 Delegate 不支持的算子处切回便携 CPU 实现。这会引入跨单元的拷贝开销,因此需尽量将整张计算图都委托给 NPU。可以使用厂商的性能分析工具识别回退点,然后修改模型结构或自定义 NPU 算子实现。
-
子图切分与流水线
-
将 Transformer 按层切分为 NPU 子图和 CPU 子图。例如把大矩阵乘密集的 MLP 和部分 Attention 放在 NPU,LayerNorm 和 Residual Add 等轻量操作保留在 CPU,通过双缓冲异步执行隐藏传输延迟。
-
内存与功耗优化
-
NPU 内存通常独立(或预留),需要仔细规划权重的静态分配,避免动态分配开销。
-
利用 NPU 的低位宽(INT4/INT8)降低内存占用和功耗。
-
模型参数常驻 NPU 内存,通过 mmap 等方式快速加载。
常用算子清单:NPU 需要支持的 Transformer 算子至少包含:Conv2D/MatMul, FullyConnected, ElementWise Add/Mul, Activation (ReLU/GELU/SiLU), Softmax, Reshape/Transpose, ReduceMean (用于 LayerNorm), 以及 Pad/StridedSlice 等张量操作。缺失任一核心算子都会导致较大比例 CPU 回退,严重影响加速效果。
总之,利用 NPU 需要把模型量化至 INT8,针对厂商工具链进行模型转换与算子兼容性调优,必要时重构部分网络,才能充分发挥硬件能效。
推理服务中,如何对用户输入和输出进行安全审查,而不显著增加延迟?¶
安全审查通常需要运行额外的模型或规则引擎,为了不影响主推理延迟,可利用流水线、异步及缓存技术。
-
异步审查 + 流式中断
-
输入审查:用户 prompt 到达后,立即启动主模型的 prefill 并流式生成,与此同时,异步调用一个轻量级的安全审查模型(如 Llama Guard、ShieldGemma)或关键词过滤服务。由于生成第一个 token 需要时间,只要输入审查能在首个 token 生成前完成,就完全隐藏延迟。
-
输出审查:在 token 逐个生成并推送给用户的同时,后台累计已生成文本,并定期(如每 4 个 token 或每隔 200ms)进行安全性扫描。若检测到不安全内容(如暴力、色情),即刻中止生成,并向客户端发送终止信号,同时可替换为预设安全回复。这样大部分正常输出无延迟增加,仅有少量不安全请求会被切断,用户体验可接受。
-
核心技术:利用流式传输的渐进性,让审查与生成并行,用微小的“安全窗口”风险换取零延迟。
-
预处理级联小模型
-
在 API 网关层或请求入口侧,部署一个极轻量级文本分类模型(如 DistilBERT 微调的分类器,几毫秒延迟)对输入进行快速初筛。如果明确安全,直接放行;如果疑似违规,再交给大模型深度审查或直接拒绝。90% 以上安全请求可毫秒级通过。
-
输出端同样可以级联,先用关键词表和简单逻辑判断(如正则匹配禁止词)进行毫秒级过滤,再做小模型分类。
-
并行调度到同一 GPU 的额外 capacity
-
如果主推理服务所在 GPU 还有闲置的 SM 或 MIG 切片,可将安全模型加载在同一 GPU 的独立 CUDA Stream 或小 MIG 实例上,与主推理并发执行。通过 CUDA 多流或 MPS,小模型审查几乎不占用大模型算力。当大模型在 decode 等待 KV cache 搬运时,安全模型可以执行。
-
使用投机采样思想:让安全模型“并行验证”输出 token,类似草稿模型一样与大模型并行工作,但用于检测而非预测。
-
缓存与复用
-
对系统固定提示(system prompt)和常见输出的安全结论进行缓存。例如同一系统提示的输入审查结果可以长期缓存,请求命中后直接跳过审查。
-
利用前缀的哈希值,对于完全相同或相似前缀的输入,复用之前的安全判断结果。
-
安全审查服务化与独立扩展
-
将安全审查拆分为微服务,支持独立于推理引擎的弹性扩展。通过 gRPC 异步调用,并设置超时时间(如 100ms),超时或服务不可用时可根据策略(宁可放过不可中断?或阻塞)决定降级,以免拖慢主流程。
-
延迟预算分配
-
给整体链路设定端到端延迟 SLO,如 TTFT < 200ms。若安全审查需 20ms,则主推理需在 180ms 内完成。通过严格的延迟预算保证即使在同步部分审查时也不超出 SLA。此时会将轻量模型优化到极致(INT8 量化、C++推理、GPU 预热)。
通过“异步+中断”模式,可以在几乎不增加用户感知延迟的情况下实现内容安全防护,是现代 LLM 推理服务的标准实践。