附加讲 A1 · LLM 应用栈与模型服务框架 · LLM App Stack and Model Serving

Large Language Model Systems · 附录 A1。个人学习讲义与配套实验,按主题整理并持续修订。

课程源码 ZIP ↓

个人整理的学习笔记,非官方讲义;课程来源与整理说明见课程介绍。配套示例未逐一运行验证。

本篇目录

对应 Maps to:CMU 11-868 / 11-968 Large Language Model Systems(Spring 2026,Lei Li)课表末尾列出、本学期未排课的主题 App Stack and Model Serving(slides:llmsys-30-serving.pdf,Lei Li,49 页)。 阅读材料:a16z, Emerging Architectures for LLM Applications(2023);NVIDIA Triton Inference Server 文档;Hugging Face Text Generation Inference 文档;LightLLM、MLC LLM 的项目文档;Yu et al. (2022) Orca(OSDI)。 依据说明:slides 两部分。LLM 应用的架构:a16z 的应用栈三段——数据预处理与嵌入(数据管道、嵌入模型、向量数据库)、提示构造与检索(编排框架 LangChain、LlamaIndex)、提示执行与推理(LLM API、托管、LLM 缓存、校验、日志、应用托管);以及用 AI 智能体自动完成任务(AutoGPT)。LLM 服务框架:两个 “Triton”(NVIDIA 的推理服务器 vs OpenAI 的内核语言)、Triton 推理服务器的特点与动态批处理、Triton + LightSeq / TensorRT-LLM / FasterTransformer、Text Generation Inference(TGI)、OpenLLM、MLC LLM、LightLLM(异步的分词 / 推理 / 去分词、Token Attention、高效路由器)。slides 的代码页是”用 docker 启动服务器、发请求”的截图,没有可提取的文字。本讲义的 LLM 缓存实验、动态批处理与路由器的模拟、Token Attention 的对照、本地部署的估算,都是本讲义自己设计的,不代表课堂上讲了什么;时间来自第 26 讲的”纸面 GPU”模型。 配套代码 Code:code/appendixA1/(4 个脚本 + appserve.py;复用第 19 讲的模型与第 22、24、26 讲的模拟器;都在 3 秒以内) 预计阅读时间:2 小时(含运行代码)


0. 本讲导航 · How to read this lecture

0.1 学习目标 Learning goals

  1. 画出一个 LLM 应用的”栈”:从数据管道、嵌入、向量数据库、编排,到 LLM 调用、缓存、校验、日志,说出每一层解决什么问题。
  2. 解释语义缓存为什么省钱又危险,校验层能拦下什么、拦不下什么。
  3. 用”等多久 vs 批多大”解释 Triton 的动态批处理,并说明为什么它不适合 LLM 生成(需要迭代级批处理)。
  4. 说出 TGI、OpenLLM、MLC LLM、LightLLM 各自的定位;解释 LightLLM 的 Token Attention 与”未来显存峰值”路由器。
  5. 估算一个模型在手机、笔记本、显卡上能不能跑、能跑多快。

0.2 先修与本讲范围

默认你已经会本讲只给直觉
连续批处理(第 22 讲)、PagedAttention 与抢占(第 24 讲)检索与向量数据库的内部(附加讲 A3)
量化(第 19、20 讲);解码受带宽限制(第 26 讲)智能体框架、提示工程

0.3 本讲地图

§1  LLM 应用栈:三段、十几个组件                                         (slides)
§2  应用层的 LLM 缓存与校验                                               ← 代码 01
§3  通用的模型服务器:NVIDIA Triton 与动态批处理                           ← 代码 02
§4  专门的 LLM 服务框架:TGI、OpenLLM、LightLLM                           ← 代码 03
§5  本地部署:MLC LLM                                                      ← 代码 04
§6  怎样选
§7 小结   §8 常见误区   §9 练习   §10 延伸阅读   §11 下一讲预告

1. LLM 应用栈 · The LLM app stack

前面 27 讲都在讲”模型怎样跑得快”。可一个真实的 LLM 应用,模型只是其中一个组件。slides 用 a16z 2023 年的那张图把应用拆成三段:

① 数据预处理与嵌入(离线)

  • 数据管道:加载器、解析器、预处理(Databricks、Airflow、Unstructured)——把 PDF、网页、数据库变成干净的文本块;
  • 嵌入模型:把文本块变成向量(OpenAI 便宜好用、Cohere 专注嵌入、Hugging Face 的开源模型、自己训的 BERT);
  • 向量数据库:为向量的存储与相似度查询优化(Pinecone 全托管、Chroma 本地、Faiss 是 Meta 的库、Weaviate 开源)。

② 提示构造与检索(每个请求)

  • 编排框架(LangChain 通用、LlamaIndex 专注检索):把提示链式地组织起来、调用外部 API、从向量数据库取上下文、在多次 LLM 调用之间保持记忆,最后产出一个或一串提示。

③ 提示执行与推理(每个请求)

  • LLM API:专有的(OpenAI、Anthropic)或开放的(Hugging Face、Replicate);slides 提醒:公共的聊天服务在生产环境里时延可能不稳定;
  • LLM 托管:通用云(AWS、GCP、Azure)或”有主见的云”(Databricks、Anyscale、Mosaic);
  • LLM 缓存(Redis、SQLite、GPTCache)、校验(Guardrails、Rebuff、Guidance)、日志(Weights & Biases、MLflow、PromptLayer)、应用托管(Vercel、Steamship、Anyscale、Modal)。

slides 最后提到 AutoGPT:让一个基于 LLM 的智能体自己决定下一步做什么,把结果再喂回提示,迭代地逼近目标。今天的智能体框架是这条路线的延续——对系统而言,它意味着一个用户请求会变成几十次相互依赖的 LLM 调用(第 22 讲 SGLang 的”LLM 程序”、第 26 讲 Dynamo 的 KV 感知路由都是为此设计的)。

这一讲沿着这张图挑几个可以量化的组件:缓存与校验(§2)、模型服务框架(§3–§5)。检索与向量数据库留给附加讲 A3。


2. 应用层的 LLM 缓存与校验 · LLM cache and validation

2.1 两种缓存

同一个问题被反复问——热门的客服问题、反复调用的工具——直接返回上次的答案,就省掉一次 LLM 调用。

  • 精确缓存:问题字符串完全相同才命中(Redis、SQLite 当键值存储)。永远不会答错,但”同一个意思的不同问法”命中不了。
  • 语义缓存(GPTCache 一类):把问题嵌入成向量,与某个缓存过的问题足够相似(余弦相似度 ≥ 阈值)就返回它的答案。能命中改写,也会把”看起来像、其实不同”的问题当成一样。

注意它和前面几讲的 KV 缓存不同:KV 缓存省的是预填充,答案仍由模型逐 token 生成、完全正确;应用层缓存省的是整个调用,靠”同样的问题应该有同样的答案”这个假设。

2.2 实验

01 号脚本用第 19 讲的城市 LLaMA 同时当”LLM”和”嵌入模型”:问题是城市语言里一句话的前半句(“in boston it is often”),答案是 LLM 贪心给出的下一个词。2000 个问题、40 种意图(4 种句型 × 10 个城市,按 Zipf 分布出现),其中句型 T3 有大量同义改写(“the chefs from boston who cook at night love the” 和 “the artists from boston who sing every day love the” 问的是同一件事)。

缓存命中率答错(占全部问题)LLM 调用
不缓存0%0%2000
精确匹配77.7%0%446
语义匹配,阈值 0.9996.1%0%78
语义匹配,阈值 0.9597.0%5.7%60
语义匹配,阈值 0.9098.7%30.0%27
语义匹配 0.90 + 校验98.0%19.4%39

同一意图的改写在嵌入空间里挤在一起(相似度平均 0.93),所以阈值 0.99 时语义缓存把命中率从 78% 提到 96%、仍然不答错。阈值再低,命中率几乎不涨,错答却迅速增加:答案不同的两个问题里,最像的一对是 “portland has very nice”(答 food)和 “seattle has very nice”(答 views),相似度 0.985——嵌入几乎一样,只差一个城市名。

2.3 校验能拦下什么

校验层(guardrail)检查输出是否”合法”:格式、安全、事实约束。脚本用城市语言的真实分布当校验器(这个词能不能接在这个前半句后面):它拦下了 15 次不合法的答案(例如缓存给 “the teachers from denver who cook on weekends love the” 返回了 “coffee”——denver 没有咖啡),错答从 30% 降到 19%。但”合法却不对”的答案(给 seattle 返回了 portland 的 “food”,这在 seattle 也合法)它拦不住。

教训:语义缓存是用正确性换成本,阈值要按业务能容忍的错误率来定;校验只能拦下一部分错误;日志要能还原每一次调用(哪个缓存条目、哪个阈值、哪个模型版本),出了错才能查。

⏱ 01 号脚本第 2 部分还量了每一层的时间:命中缓存只要嵌入 + 查询(约 0.5 ms),不命中还要加上 LLM 调用(约 4.4 ms,生成 8 个 token)。真实系统里差距大得多——嵌入模型只有几亿参数、一次前向;LLM 有几百亿参数、生成几百个 token。


3. 通用的模型服务器:NVIDIA Triton · Triton Inference Server

3.1 两个 Triton

slides 先澄清一个常见的混淆:NVIDIA Triton 是推理服务器(部署模型、接请求、批处理);OpenAI Triton 是写 GPU 内核的语言与编译器(第 13 讲 Pallas 的”同类”、FlashAttention 的很多实现用它写)。本节讲前者。

Triton 推理服务器是一个通用的模型服务器:支持多种框架(TensorFlow、PyTorch、ONNX、TensorRT……);支持多种查询(实时、批量、流式);能部署在公有云、数据中心、边缘设备上。它管理一个”模型仓库”(每个模型一个目录、若干版本、一份配置),每个模型可以开多个实例(instance group),每个实例前面有一个调度器。

3.2 动态批处理

GPU 喜欢大批:02 号脚本第 1 部分,一个 BERT-base 大小的编码器(每个请求 128 个 token),A100 上批大小 1 一批 1.23 ms,批 32 一批 5.31 ms——平均到每个请求从 1.23 降到 0.17 ms,吞吐上限从 813 提高到 6,023 请求 / 秒。可请求是一个一个到的,要攒成批就得让先到的等一等。

Triton 的动态批处理器有两个主要旋钮:最大批(max_batch_size)和最长排队时间(max_queue_delay)。模型空闲时,队列里够最大批就立刻发;不够就最多等到最早的请求已经等了 max_queue_delay,然后把队列里的全发出去。

02 号脚本第 2 部分(单个模型实例,泊松到达):满足 P99 ≤ 10 ms 时能承受的最大到达率——

设置最大到达率
不批处理642 请求 / 秒
最大批 32,不等待5,387
最大批 32,最多等 2 ms5,373
最大批 32,最多等 8 ms294

两个发现:(1) 即使不等待,“模型一空就把排着的全拿走”也是一种批处理——负载越高批越大,P99 不变的前提下能承受的到达率高 8 倍;(2) 最长排队时间是”用时延换批大小”:低负载时让每个请求白等(8 ms 时连每秒几百个请求都满足不了 P99 ≤ 10 ms),高负载时批本来就够大,它几乎不起作用。只有”固定开销很大、到达又稀疏”时才值得开,而且要小于 SLO 留出的余量。

3.3 它为什么不够用于 LLM

Triton 的动态批处理是请求级的:一批进去、一批出来。LLM 一个请求要生成几十到几百个 token,长度各不相同——请求级的批要等最长的那个生成完(第 22 讲的静态批处理)。02 号脚本第 3 部分(LLaMA-3-8B,每秒 40 个请求):请求级批处理平均批只有 6.0、吞吐 1,176 token/秒、平均 TTFT 22.9 秒;迭代级批处理平均批 19.6、吞吐 3,685、TTFT 0.12 秒。

所以 slides 说”Triton + LightSeq / TensorRT-LLM”:Triton 负责接收请求、管理模型、提供 HTTP / gRPC 接口;真正的批处理与 KV 管理交给后端引擎——TensorRT-LLM 的”飞行中批处理”(in-flight batching)就是 ORCA 的迭代级调度。通用的模型服务器与专门的 LLM 引擎在这里分了工。


4. 专门的 LLM 服务框架 · LLM serving frameworks

4.1 Text Generation Inference(TGI)

Hugging Face 的 TGI(slides 第 27–29 页):

  • 针对推理优化的 Transformer 实现:FlashAttention(第 21 讲)、PagedAttention(第 24 讲);原生支持 Hugging Face 上的模型;
  • 面向生产:能监控服务器负载、用 OpenTelemetry 做分布式追踪、导出 Prometheus 指标;
  • 丰富的推理选项:精度调整、量化;
  • 架构:一个 Rust 写的路由器(接请求、做连续批处理、流式返回 token)+ 若干个张量并行的模型分片(gRPC 通信)。

4.2 OpenLLM

BentoML 的 OpenLLM(slides 第 30–31 页)的重点不在内核,而在”组合”:把 LLM 与其他模型、服务(LangChain、LlamaIndex、Hugging Face)组合成应用;支持自带模型、微调;开源、迭代快。它代表了”服务框架往应用栈上层延伸”的方向。

4.3 LightLLM

LightLLM(slides 第 36–48 页)是一个轻量的、纯 Python + Triton 内核的推理框架,有三个值得一讲的设计。

异步的分词、推理、去分词。推理服务器每一步除了 GPU 的前向,还有 CPU 的活:调度、准备输入、去分词、把 token 流式发给用户。LightLLM 把分词、路由 + 推理、去分词拆成三个进程,CPU 的工作与 GPU 的计算重叠。03 号脚本第 3 部分的模型(每个请求每步 25 μs 的 CPU 开销是假设的量级):H100 上批 256 时,重叠比串行快 35%——GPU 越快、批越大,CPU 开销占的比例越大。第 24 讲 vLLM 的异步调度、第 22 讲 SGLang 的零开销调度器是同一个问题的不同解法。

Token Attention。KV 缓存按 token 分配——相当于块大小为 1 的 PagedAttention。03 号脚本第 1 部分(OPT-13B,A100-40GB,KV 约 15,000 个 token,每秒 8 个请求;第 24 讲的模拟器):

分配方式显存利用率平均批吞吐抢占
按最大长度预留20%6.81.070
分页,块 1698.5%28.83.51152
按 token≈ 100%29.73.48606

块 16 的内部碎片本来就小(每个请求最多浪费 15 个 token),按 token 分配只让批多一点;而在 vLLM 式的贪心接纳下,塞进去的请求越多,生成途中显存耗尽、不得不抢占的次数也越多——吞吐没升,抢占多了 4 倍。还有工程代价:块表长了 16 倍、注意力内核要逐 token 查表。这正是 LightLLM 要把 Token Attention 和下面的路由器配在一起的原因。

高效路由器(Efficient Router)。决定”现在能不能再接纳一个请求”。三种思路:

  • 按”提示 + 最大输出”预留(Orca、FasterTransformer):永不抢占,但每个请求都按 max_new_tokens 占位,太保守;
  • 贪心(vLLM):现在放得下就接,生成途中不够了再抢占(重算或换出);
  • LightLLM:估计”接纳之后,如果每个请求都生成到它的上界,显存的峰值是多少”,峰值放得下才接。

峰值怎么算?请求 i 现在占 cur_i 个 token、最多再生成 rem_i 个;t 步之后,rem_i ≥ t 的请求占 cur_i + t,其余已经结束、释放。峰值只可能出现在某个请求结束的前一刻,所以只要在 t = rem_i 这些点上算 usage(t) = Σ_{rem_i ≥ t}(cur_i + t)(appserve.future_peak)。它算的是峰值而不是总和——请求是陆续结束的——所以比”按最大输出预留”大方得多,又永远不需要抢占。

03 号脚本第 2 部分(LLaMA-3-8B,A100;提示中位数约 400、实际输出中位数约 200、max_new = 1024):

KV 容量输出上界策略吞吐 token/秒平均批抢占P99 时延
16Kmax_new按最大输出预留7709.70157 秒
16Kmax_new贪心 + 抢占1,22918.3211(重算 115K token)64 秒
16Kmax_newLightLLM99913.2098 秒
16K实际 × 2LightLLM1,13915.5076 秒
32Kmax_new贪心 + 抢占1,83530.34521.5 秒
32K实际 × 2LightLLM1,79028.7020.7 秒

在这个纸面模型里,显存很紧时”贪心 + 抢占”反而吞吐更高、P99 更低——重算一次预填充太便宜;容量宽松、长度估计更准时两者接近,LightLLM 一个 token 都不重算。路由器的价值在于可预测:没有抢占,就没有被反复踢出队列的请求;它的效率取决于对输出长度估计得多准——“预测输出长度”因此成了一个研究方向。真实系统里抢占更贵(长上下文的重算、换出到 CPU 的带宽),天平会更偏向不抢占的做法。


5. 本地部署:MLC LLM · Running LLMs on local devices

MLC LLM(slides 第 32–35 页)的目标是让模型在消费级设备上原生运行:用机器学习编译器(TVM)把同一个模型编译到各种平台——C++ 命令行、浏览器里的 JavaScript(WebGPU)、iOS 的 Swift、Android 的 Kotlin。本地 LLM 的好处:隐私(数据不出设备)、离线可用、没有服务费、时延可控。

本地部署的系统目标和云端相反:只有一个用户,没有”批”来摊薄读权重的成本,解码几乎完全受内存带宽限制(第 26 讲)。04 号脚本的上限估计(token/秒 ≈ 70% 的带宽 / 权重字节数):

设备3B,4 位8B,FP168B,4 位70B,4 位(约 40 GB)
手机(约 51 GB/s,8 GB)20放不下8放不下
轻薄本(M2,100 GB/s,16 GB)39放不下16放不下
高端笔记本(M4 Pro,273 GB/s,48 GB)1061242放不下
游戏显卡(RTX 4090,1 TB/s,24 GB)39244157放不下

位数减到约 1/3.5,速度就快约 3.5 倍,能放下的模型也大 3.5 倍——所以本地部署几乎总是 4 位量化(第 19、20 讲的 GPTQ、AWQ 一类)。70B 级别的模型即使 4 位也要约 40 GB,一张游戏显卡放不下:要么多卡,要么像附加讲 A2 的 KTransformers 那样把大部分权重放进 CPU 内存。


6. 怎样选 · Choosing a framework

需求合适的选择理由
一个服务里有多种模型(检测、分类、嵌入、LLM),要统一的部署、监控、版本管理Triton(+ TensorRT-LLM 作为 LLM 后端)通用的模型服务器、模型仓库、多后端
高吞吐的 LLM 在线服务vLLM、SGLang、TensorRT-LLM、TGI迭代级批处理、分页 KV、前缀缓存、各种并行
结构化的多次调用、共享前缀很多(智能体、少样本)SGLangRadixAttention、前端语言(第 22 讲)
研究新的调度或 KV 管理算法LightLLM(纯 Python + Triton 内核,代码少)或 vLLM好改
大规模、多节点、预填充 / 解码分离Dynamo、llm-d(第 26 讲)+ LMCache(第 27 讲)编排、路由、分层 KV
手机、浏览器、离线MLC LLM、llama.cpp编译到各种后端、低位量化

这些框架还在快速演化:今天的 TGI、vLLM、SGLang 已经互相吸收了对方的大部分技术。比框架名字更重要的是它们背后的几个反复出现的问题——批怎样组、KV 怎样管、CPU 开销怎样藏、显存会不会在半路耗尽。


7. 小结 · Summary

  1. LLM 应用是一个栈:数据管道 → 嵌入 → 向量数据库 → 编排 → LLM(API 或自托管)→ 缓存、校验、日志。模型之外的每一层都有成本,也都有失败的方式。
  2. 语义缓存用正确性换成本:同义改写能命中,“只差一个词”的不同问题也会命中;校验只能拦下不合法的输出。
  3. Triton 是通用的模型服务器,动态批处理在”等多久”与”批多大”之间取舍;LLM 生成需要迭代级批处理,交给 TensorRT-LLM 等后端。
  4. LightLLM:异步流水线藏起 CPU 开销;Token Attention 把 KV 分配粒度降到 1;路由器按”未来显存峰值”接纳请求、永不抢占,效率取决于输出长度估计得多准。
  5. 本地部署受内存带宽与容量限制,4 位量化是常态;MLC LLM 用编译器覆盖五花八门的硬件。

8. 常见误区 · Common pitfalls

  1. “语义缓存的阈值越低越好,命中越多越省钱。” 命中率涨得很少,错答涨得很快(阈值 0.95 → 0.90:错答 5.7% → 30%)。
  2. “有了校验就不怕缓存答错。” 校验只检查合法性,“合法却答非所问”的输出拦不住。
  3. “动态批处理的排队时间设得越长,吞吐越高。” 高负载时批本来就满,排队时间不起作用;低负载时它只会增加时延。
  4. “Triton 的动态批处理也能用来服务 LLM。” 它是请求级的;LLM 需要迭代级批处理,由后端引擎负责。
  5. “KV 分配的粒度越细越好。” 块 16 的内部碎片本来就小;粒度更细带来更多的表项、更不规则的访存,在贪心接纳下还会更频繁地抢占。
  6. “不抢占的调度一定更慢。” 取决于对输出长度的估计与抢占的代价;可预测性本身就有价值。
  7. “本地设备算力够就能跑大模型。” 单用户解码受带宽限制,而且模型首先得放得下。

9. 练习 · Exercises

  1. 列出 a16z 应用栈里每个请求都会经过的组件,并标出哪些会产生 LLM 调用、哪些可能让答案出错。
  2. 一个语义缓存在阈值 0.95 时命中 97%、错答 5.7%;不缓存时每次 LLM 调用花 0.002 美元、“答错一次”的业务代价是 0.05 美元。每 1000 个问题,缓存省下多少钱、损失多少?值得吗?
  3. 编码器一批的时间是 1.2 ms + 0.13 ms × 批大小。不批处理时的最大吞吐是多少?最大批 32 时呢?
  4. 为什么在高负载下,Triton 的 max_queue_delay 几乎不影响时延和吞吐?
  5. 三个正在生成的请求:(cur, rem) = (500, 100)、(300, 400)、(800, 50)。用 future_peak 的方法算显存峰值。
  6. 上题再来一个 (prompt = 400, max_new = 300) 的新请求,KV 容量 2600 个 token。LightLLM 的路由器会接纳它吗?“按最大输出预留”呢?
  7. LightLLM 的路由器什么时候会比”贪心 + 抢占”吞吐更低?什么时候会更好?
  8. 一部内存带宽 60 GB/s 的手机跑 4 位量化的 7B 模型(每个参数 4.5 位),解码上限约多少 token/秒(有效带宽取 70%)?
  9. 为什么服务框架要把分词 / 去分词放到单独的进程,而不是线程?(提示:Python)

参考答案

  1. 每个请求:编排(构造提示)→ 嵌入查询 → 向量数据库检索 → LLM 缓存查询 →(未命中)LLM 调用 → 校验 → 日志。产生 LLM 调用的:LLM 调用本身(智能体与链式编排可能多次调用);可能出错的:检索(取错文档)、语义缓存(返回别的问题的答案)、LLM(幻觉)、校验(误报 / 漏报)。
  2. 省:970 次命中 × 0.002 = 1.94 美元;损失:57 次错答 × 0.05 = 2.85 美元——不值得;换成阈值 0.99(96.1% 命中、0 错答)则省 1.92 美元、无损失。阈值要按错误的代价来定。
  3. 不批处理:1 / 1.33 ms ≈ 752 请求 / 秒;批 32:32 / (1.2 + 4.16) ms ≈ 5,970 请求 / 秒。
  4. 高负载时,模型一空闲,队列里就已经攒够了(或接近)最大批,立刻发出;排队时间这个”最多等多久”的上限根本用不到。
  5. 起点:500 + 300 + 800 = 1600。t = 50:三个都在,500+50 + 300+50 + 800+50 = 1750;t = 100:(800, 50) 已结束,500+100 + 300+100 = 1000;t = 400:只剩第二个,300 + 400 = 700。峰值 1750。
  6. 加上 (400, 300):t = 50:1750 + 450 = 2200;t = 100:1000 + 500 = 1500;t = 300:300+300 + 400+300 = 1300;t = 400:700。峰值 2200 ≤ 2600,接纳。按最大输出预留:(500+100) + (300+400) + (800+50) + (400+300) = 2850 > 2600,不接纳。
  7. 更低:显存很紧、输出上界远大于实际长度、抢占(重算)很便宜时——它为”可能用到但实际用不到”的显存留了位置。更好:长度估计准、抢占很贵(长上下文、换出带宽有限)、时延要求稳定时。
  8. 7e9 × 4.5 / 8 ≈ 3.9 GB;0.7 × 60 / 3.9 ≈ 10.7 token/秒。
  9. CPython 有全局解释器锁(GIL),同一进程里的 Python 线程不能同时执行 Python 代码;分词、去分词是 Python(或通过 Python 调用)的 CPU 工作,放在同一个进程里会和调度、准备输入抢 GIL。拆成进程才能真正并行,代价是进程间通信。

10. 延伸阅读 · Further reading

  • a16z, Emerging Architectures for LLM Applications(2023);Chip Huyen, Building LLM Applications for Production(2023)。
  • NVIDIA Triton Inference Server 与 TensorRT-LLM 文档(动态批处理、in-flight batching)。
  • Hugging Face Text Generation Inference;BentoML OpenLLM;MLC LLM(mlc.ai);LightLLM(github.com/ModelTC/lightllm)。
  • GPTCache(语义缓存);Guardrails AI(校验)。
  • Yu et al. (2022) Orca(迭代级调度);输出长度预测与调度:如 Zheng et al. (2023) Response Length Perception and Sequence Scheduling。

11. 下一讲预告 · Next

本讲的最后看到:70B 的模型 4 位量化后也放不进一张游戏显卡。附加讲 A2 讲异构硬件上的 LLM 服务:不同的硬件擅长不同的维度——算力、显存带宽、内存容量、价格。Mooncake(Kimi 的服务平台)把预填充、解码、KV 缓存分别放在最合适的硬件上;KTransformers 把 MoE 的专家放到 CPU 内存里,让一张 GPU 加一台服务器就能跑 6710 亿参数的 DeepSeek-V3。

← 返回课程目录