跳转至

部署方案

大模型服务化部署通常采用什么架构?如何实现负载均衡和弹性伸缩?

大模型(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 类模型需仔细适配融合。

技术路线:

  1. 模型压缩:从大模型出发,通过蒸馏、结构化剪枝、低秩分解得到参数量 < 1B 的小模型(如 TinyLLaMA、Phi 系列)。或直接从开源预训练小模型开始。

  2. 量化:应用 4-bit 或 8-bit 的整数量化(INT4/INT8),常见方案为 GPTQ、AWQ 或 GGUF 的 K-quants。重点是采用块状量化和混合精度,尽量减少在移动端 CPU 上的精度损失。也可使用带有整数激活的量化方案以完全避开浮点运算。

  3. 框架编译与优化:将量化后的模型导出为对应移动框架的格式(如 .gguf.pte),使用厂商提供的编译器/转换工具进行运算符融合、内存规划优化。

  4. 移动端运行时集成:

  5. Android:使用 JNI 调用 C/C++ 推理库(如 llama.cpp 的 Android 编译),或集成 ExecuTorch 运行时。可充分利用 NEON SIMD 加速。
  6. iOS:利用 Core ML 将模型转换为 .mlmodelc 并利用 ANE(Apple Neural Engine)加速;或直接使用 Metal Performance Shaders 后端(如 llama.cpp 的 Metal 支持),在 GPU 上运行量化计算。

  7. 性能与内存优化:对移动端内存极度敏感,需要:

  8. 使用 mmap 直接映射模型文件,延迟加载,避免全部读入内存。
  9. 优化 KV cache 占用,可结合滑动窗口注意力或 PagedAttention 的块管理思想,限制最大缓存长度。
  10. 限制并发请求,单线程推理,防止 APP 卡顿。

  11. 应用层优化:流式输出、预测即输入,对延迟敏感的 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 架构差异影响。

具体配置步骤:

  1. 暴露自定义指标:在推理框架中,将实时队列长度上报到 Prometheus。vLLM 等可直接暴露 /metrics 接口,包含 vllm:num_requests_waiting 或类似的等待请求数指标。

  2. 安装 Prometheus Adapter:配置 CustomMetric API,将 Prometheus 中的 num_requests_waiting 映射为 K8s 自定义指标。

  3. 创建 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 个请求
  1. 结合 GPU 利用率:可添加 GPU 利用率作为上限指标,防止单纯队列信号导致扩容过猛。例如当 GPU 利用率连续 5 分钟超过 80% 再配合队列长度触发。

高级策略:

  • 使用 KEDA 基于事件伸缩:除了 Prometheus,KEDA 可对接 Redis、Kafka 等消息队列,更适合异步离线批处理推理的伸缩。

  • 冷却策略:推理服务扩容后模型加载耗时较长(数十秒到数分钟),需设置较长的缩容冷却时间(如 300 秒)避免 Pod 反复启动。

  • 预热机制:新 Pod 启动后需要预热模型、预热 CUDA context,可通过 init container 或框架的 warmup 请求,并在就绪探针确认可服务后再被加入负载均衡。

综上,队列长度为核心,GPU 利用率为辅助,能让伸缩更贴合服务质量目标。


如果要同时提供高吞吐离线推理和低延迟在线服务,如何设计统一的推理平台?

设计统一平台需在资源隔离、调度策略、请求路由上做出区分,保证两种负载互不干扰。

  1. 物理/逻辑资源池隔离

  2. 通过 K8s 节点池划分:给在线服务分配带有高优保障的 GPU 节点(如按需实例),设置污点与容忍度,确保在线 Pod 独占或优先使用;离线任务可使用廉价 Spot 节点、或在线节点的低优资源池。

  3. 在线实例常驻运行,始终保持预热;离线实例可弹性伸缩甚至缩零。

  4. 调度层优先级与抢占

  5. 在请求入口处打上优先级标签(如 latency-critical vs throughput)。调度器维护多个队列。

  6. 在线请求可抢占离线请求的资源:利用 PagedAttention 的 swap 机制,将离线请求的 KV cache 块换出到 CPU 内存,让出显存给在线请求,处理完后再换回。

  7. 若使用统一实例混合服务,引擎内部需支持优先级队列,保证在线请求优先被编入 batch,离线请求填充剩余算力。

  8. 分离 Prefill 与 Decode 的调度

  9. 离线批处理常涉及巨量 prompt 的 prefill,这会导致迭代时间尖刺。可将 Prefill 与 Decode 拆分到不同实例组,在线 decode 实例只处理 decode 和短 prefill,离线 prefill 由专用实例完成。调度器根据请求阶段智能路由。

  10. 或采用 chunked prefill,把长 prefill 切分,在 decode 批次中插空执行,降低对在线响应的干扰。

  11. 统一模型仓库与配置

  12. 平台维护同一份模型权重,通过 model registry 加载。在线和离线实例启动时,可从同一分布式存储(如 S3、PVC)加载模型。

  13. 使用相同的推理引擎和运行时版本,方便监控、运维和更新。

  14. 超额订阅与成本优化

  15. 在线服务保障严格 SLA,可超额部署少量离线实例。当在线负载低时,离线实例启动,充分利用空闲 GPU。通过 K8s HPA 和 KEDA 根据离线队列长度自动伸缩,将成本降至最低。

  16. 隔离与观测

  17. 对不同类型服务打上独立 label,分别监控 P50/P99 延迟、吞吐、排队时间。设定 SLO,对在线服务设置预警阈值,离线服务只需关注成功率和完成时间。

通过“隔离资源 + 优先级调度 + 混合池”的方案,单一平台可以同时承载高吞吐离线与低延迟在线推理,实现硬件利用率最大化。


如何实现推理服务的“金丝雀发布”,逐步将流量切换到新模型版本?

金丝雀发布的核心是将少量真实流量导入新版本,验证其稳定性和质量后逐步扩大占比,同时可随时回滚。

步骤详解:

  1. 部署新旧两个 Deployment
  2. 旧版本:llm-v1,保持现有流量。
  3. 新版本:llm-v2,使用新模型镜像、权重或适配器。初始设置 replicas 为较小数量(如 1 个 Pod),待正常启动。

  4. 借助 Service Mesh 或 Ingress 实施流量分割

  5. 使用 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 的主要步骤如下:

  1. 模型量化与格式转换

  2. 将 Transformer 量化为 INT8 或 FP16。NPU 通常对 INT8 有最佳效能,所以常用训练后量化(PTQ)或量化感知训练(QAT)得到 INT8 模型。

  3. 导出为 NPU 厂商支持的中间格式。例如:

  4. 高通 Hexagon NPU:使用 SNPE(Snapdragon Neural Processing Engine)或 QNN(Qualcomm Neural Network),将 ONNX/TensorFlow 模型转换为 .dlc 或 QNN 格式。
  5. 苹果 ANE(Neural Engine):通过 Core ML Tools 将 PyTorch/TF 模型转为 .mlmodelc,并启用 computeUnits= .all 来使用 ANE。
  6. 联发科 APU:NeuroPilot SDK 转换 ONNX 模型。
  7. 通用路径:使用 ExecuTorch 并选择相应委托(Delegate),如高通的 QNN Delegate,Apple 的 Core ML Delegate,以及 Android 的 NNAPI Delegate。

  8. 算子支持与降级策略

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 算子实现。

  1. 子图切分与流水线

  2. 将 Transformer 按层切分为 NPU 子图和 CPU 子图。例如把大矩阵乘密集的 MLP 和部分 Attention 放在 NPU,LayerNorm 和 Residual Add 等轻量操作保留在 CPU,通过双缓冲异步执行隐藏传输延迟。

  3. 内存与功耗优化

  4. NPU 内存通常独立(或预留),需要仔细规划权重的静态分配,避免动态分配开销。

  5. 利用 NPU 的低位宽(INT4/INT8)降低内存占用和功耗。

  6. 模型参数常驻 NPU 内存,通过 mmap 等方式快速加载。

常用算子清单:NPU 需要支持的 Transformer 算子至少包含:Conv2D/MatMul, FullyConnected, ElementWise Add/Mul, Activation (ReLU/GELU/SiLU), Softmax, Reshape/Transpose, ReduceMean (用于 LayerNorm), 以及 Pad/StridedSlice 等张量操作。缺失任一核心算子都会导致较大比例 CPU 回退,严重影响加速效果。

总之,利用 NPU 需要把模型量化至 INT8,针对厂商工具链进行模型转换与算子兼容性调优,必要时重构部分网络,才能充分发挥硬件能效。


推理服务中,如何对用户输入和输出进行安全审查,而不显著增加延迟?

安全审查通常需要运行额外的模型或规则引擎,为了不影响主推理延迟,可利用流水线、异步及缓存技术。

  1. 异步审查 + 流式中断

  2. 输入审查:用户 prompt 到达后,立即启动主模型的 prefill 并流式生成,与此同时,异步调用一个轻量级的安全审查模型(如 Llama Guard、ShieldGemma)或关键词过滤服务。由于生成第一个 token 需要时间,只要输入审查能在首个 token 生成前完成,就完全隐藏延迟。

  3. 输出审查:在 token 逐个生成并推送给用户的同时,后台累计已生成文本,并定期(如每 4 个 token 或每隔 200ms)进行安全性扫描。若检测到不安全内容(如暴力、色情),即刻中止生成,并向客户端发送终止信号,同时可替换为预设安全回复。这样大部分正常输出无延迟增加,仅有少量不安全请求会被切断,用户体验可接受。

  4. 核心技术:利用流式传输的渐进性,让审查与生成并行,用微小的“安全窗口”风险换取零延迟。

  5. 预处理级联小模型

  6. 在 API 网关层或请求入口侧,部署一个极轻量级文本分类模型(如 DistilBERT 微调的分类器,几毫秒延迟)对输入进行快速初筛。如果明确安全,直接放行;如果疑似违规,再交给大模型深度审查或直接拒绝。90% 以上安全请求可毫秒级通过。

  7. 输出端同样可以级联,先用关键词表和简单逻辑判断(如正则匹配禁止词)进行毫秒级过滤,再做小模型分类。

  8. 并行调度到同一 GPU 的额外 capacity

  9. 如果主推理服务所在 GPU 还有闲置的 SM 或 MIG 切片,可将安全模型加载在同一 GPU 的独立 CUDA Stream 或小 MIG 实例上,与主推理并发执行。通过 CUDA 多流或 MPS,小模型审查几乎不占用大模型算力。当大模型在 decode 等待 KV cache 搬运时,安全模型可以执行。

  10. 使用投机采样思想:让安全模型“并行验证”输出 token,类似草稿模型一样与大模型并行工作,但用于检测而非预测。

  11. 缓存与复用

  12. 对系统固定提示(system prompt)和常见输出的安全结论进行缓存。例如同一系统提示的输入审查结果可以长期缓存,请求命中后直接跳过审查。

  13. 利用前缀的哈希值,对于完全相同或相似前缀的输入,复用之前的安全判断结果。

  14. 安全审查服务化与独立扩展

  15. 将安全审查拆分为微服务,支持独立于推理引擎的弹性扩展。通过 gRPC 异步调用,并设置超时时间(如 100ms),超时或服务不可用时可根据策略(宁可放过不可中断?或阻塞)决定降级,以免拖慢主流程。

  16. 延迟预算分配

  17. 给整体链路设定端到端延迟 SLO,如 TTFT < 200ms。若安全审查需 20ms,则主推理需在 180ms 内完成。通过严格的延迟预算保证即使在同步部分审查时也不超出 SLA。此时会将轻量模型优化到极致(INT8 量化、C++推理、GPU 预热)。

通过“异步+中断”模式,可以在几乎不增加用户感知延迟的情况下实现内容安全防护,是现代 LLM 推理服务的标准实践。