Files
flykhan 2536c937e3 feat: 完整中文翻译 maths-cs-ai-compendium(数学·计算机科学·AI 知识大全)
翻译自英文原版 maths-cs-ai-compendium,共 20 章全部完成。

第01章 向量 | 第02章 矩阵 | 第03章 微积分
第04章 统计学 | 第05章 概率论 | 第06章 机器学习
第07章 计算语言学 | 第08章 计算机视觉 | 第09章 音频与语音
第10章 多模态学习 | 第11章 自主系统 | 第12章 图神经网络
第13章 计算与操作系统 | 第14章 数据结构与算法
第15章 生产级软件工程 | 第16章 SIMD与GPU编程
第17章 AI推理 | 第18章 ML系统设计
第19章 应用人工智能 | 第20章 前沿人工智能

翻译说明:
- 所有数学公式 $...$ / $$...$$、代码块、图片引用完整保留
- mkdocs.yml 配置中文导航 + language: zh
- README.md 已翻译为中文(兼 docs/index.md)
- docs/ 目录包含指向各章文件的 symlink
- 约 29,000 行中文内容,排除 .cache/ 构建缓存
2026-05-03 10:23:20 +08:00

201 lines
20 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 大规模基础设施
*构建服务数百万用户的系统需要的不只是单个服务器。本文件涵盖可扩展性模式、分布式系统基础、微服务、数据流水线、数据库扩展、搜索和向量系统、可观测性、可靠性工程以及CI/CD*
- 每秒服务1个请求的模型可以在笔记本电脑上运行。每秒服务100,000个请求且可用性达到99.9%需要分布式系统、自动故障转移和精心设计的数据流水线。本文件涵盖弥合这一差距的模式。
## 可扩展性
- **垂直扩展**(向上扩展):换更大的机器。更多CPU、更多内存、更大的GPU。简单但有硬性限制(最大的可用机器)和单点故障。
- **水平扩展**(向外扩展):增加更多机器。每台处理一部分流量。没有单机限制,但需要:负载均衡(文件01)、数据分区和处理分布式状态。
- **无状态服务**默认是可水平扩展的。在负载均衡器后面添加更多实例即可。在启动时加载权重并独立处理请求的模型推理服务器是无状态的——任何实例都可以处理任何请求。
- **有状态服务**(数据库、KV缓存、特征存储)更难扩展。状态必须在多台机器间分区(分片,文件01)并复制以实现容错。
- **可扩展性方程**:对于一个有$n$台服务器的系统:
- **理想情况**:吞吐量线性扩展($n$台服务器→$n\times$吞吐量)。
- **实际情况**:协调、负载均衡和数据传输的开销意味着吞吐量亚线性扩展。阿姆达尔定律(第13章)适用:串行部分(共享状态、协调)限制了加速比。
## 分布式系统
- **分布式系统**是一组协调提供服务器的机器。基本挑战:
- **网络分区**:机器不能总是通信。网线被切断、交换机故障、数据中心断电。系统必须处理部分故障。
- **时钟偏差**:机器有不同的时钟。"事件A发生在机器1的10:00:01"和"事件B发生在机器2的10:00:01"并不意味它们同时发生。**逻辑时钟**(Lamport时间戳、向量时钟)建立排序而不依赖物理时钟。
- **共识**:多台机器如何就某个值达成一致(例如,谁是领导者)?**Raft**是标准的共识算法。一组节点选举一个领导者。领导者处理所有写入。如果领导者失败,剩余节点选举新的领导者。需要多数(5个节点中的3个)才能运行,因此能容忍$\lfloor(n-1)/2\rfloor$个故障。
- **分布式锁**:确保只有一台机器执行关键操作。**Redlock**(基于Redis)跨多个Redis实例获取锁。如果多数实例授予锁,则获取成功。用于:防止重复的模型部署,确保只有一个训练作业写入检查点。
## 微服务
![微服务ML架构:API网关路由到特征服务、模型服务和日志服务,每个都有自己的数据库,通过消息队列连接](../images/microservices_architecture.svg)
- **微服务**将系统分解为小型、独立可部署的服务。每个服务拥有一个领域:
```
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ API网关 │→ │ 特征服务 │→ │ 特征数据库 │
└─────────────┘ └──────────────┘ └─────────────┘
├────────→ ┌──────────────┐ ┌─────────────┐
│ │ 模型服务 │→ │ 模型存储 │
│ └──────────────┘ └─────────────┘
└────────→ ┌──────────────┐ ┌─────────────┐
│ 日志服务 │→ │ 日志存储 │
└──────────────┘ └─────────────┘
```
- **优点**:独立部署(更新模型服务而不影响特征服务)、独立缩放(根据请求负载缩放模型服务器,根据特征存储读取率缩放特征服务器)、技术自由(模型服务用Python,特征服务用Go)。
- **缺点**:网络开销(每次服务调用都是网络往返)、复杂性(调试跨越多个服务)、数据一致性(没有跨服务的事务)。
- **服务发现**:API网关如何找到模型服务?选项:基于DNS(每个服务注册一个DNS名)、K8s服务(内置)或服务注册表(Consul、Eureka)。
- **Saga模式**:对于跨多个服务的操作(创建用户+分配资源+发送欢迎邮件),使用saga:一系列本地事务,如果任何步骤失败则执行补偿操作。
## 数据流水线
- ML系统消耗大量数据。**数据流水线**移动、转换和服务这些数据:
### 批处理
- 按固定间隔(每小时、每天)处理大量数据。
- **MapReduce**:原始的批处理范式。Map(独立转换每条记录)→ Shuffle(按键分组)→ Reduce(按组聚合)。概念上简单但实现繁琐。
- **Apache Spark**:现代批处理引擎。内存处理(对于迭代算法比MapReduce快100倍)。支持SQL、DataFrame和ML流水线。大规模特征工程的标准。
- **示例**:为推荐系统计算用户特征。输入:过去30天的10亿用户活动事件。输出:1亿用户特征向量。每天作为Spark作业运行,输出到特征存储。
### 流处理
- 实时处理到达的数据(亚秒级延迟)。
- **Apache Flink**:领先的流处理引擎。精确一次处理、事件时间处理(按事件发生时间处理,而非到达时间)、窗口化(滚动、滑动、会话窗口)。
- **Kafka Streams**:内置于Kafka的轻量级流处理。适用于简单转换(过滤、聚合),无需部署单独的集群。
- **示例**:实时欺诈检测。每笔信用卡交易是一个Kafka事件。Flink作业计算运行统计(交易频率、位置变化)并在100ms内标记异常。
### Lambda架构
- 结合批处理和流处理。**批处理层**提供准确、全面的结果(但有延迟)。**速度层**提供近似、实时的结果。**服务层**合并两者。
- 实际上,许多团队现在使用**Kappa架构**:仅流处理,将流视为事实来源。流是可重播的(Kafka保留事件),因此可以通过重播流来模拟批处理。
## ML训练基础设施
- 训练前沿模型(100B+参数)是一个大规模基础设施问题:数千个GPU运行数月,消耗兆瓦级电力,生成PB级数据,花费数千万美元。基础设施决定了训练成功还是失败。
### GPU集群
- 训练集群是由高速网络连接的GPU服务器集合。关键组件:
![GPU集群:每个节点有8个通过NVLink连接的GPU,节点通过Infiniband以胖树拓扑连接,从64扩展到16,000+个GPU](../images/gpu_cluster_topology.svg)
- **GPU服务器(节点)**:每台服务器有4-8个GPU。典型配置:8×H100 GPU、2×AMD EPYC CPU、2 TB RAM、30 TB NVMe SSD。节点内的GPU通过**NVLink**连接(H100上每个GPU 900 GB/s),比PCIe快30倍。
- **集群规模**:小型训练集群有64-256个GPU(8-32个节点)。前沿模型训练集群有4,000-32,000个GPU500-4000个节点)。Meta的Llama 3使用了16,384个H100 GPU。Google在拥有8,000+个芯片的TPU pod上训练。
- **粗略估算**:训练70B模型需要约$200万。训练400B+前沿模型需要约$5000万-$1亿。集群硬件本身在H100价格下约$5亿-$10亿($3万/GPU × 16,000 GPU = $4.8亿)。
### 网络拓扑
- GPU节点之间的网络是最关键的基础设施组件。如果GPU不能足够快地交换梯度,它们就会闲置等待通信完成。
- **InfiniBand**是GPU集群网络的标准。NVIDIA的**Quantum-2 InfiniBand**提供每个端口400 Gb/s。每个节点通常有8个InfiniBand端口(每个GPU一个),每个节点的总对分带宽为400 GB/s。
- **RDMA**(远程直接内存访问):InfiniBand支持RDMA,它直接在节点间的GPU内存之间传输数据,无需CPU参与。这将延迟从约100μs(TCP)降低到约1μs,对于高效的梯度全规约(第6章)至关重要。
- **网络拓扑很重要**:**胖树**(Clos网络)提供全对分带宽(任何GPU可以与其他任何GPU以全速通信)。更便宜的拓扑(**轨道优化**、**3D环面**)提供较少的带宽但成本更低。拓扑必须匹配并行策略:
- **数据并行**:跨所有GPU的全规约→需要高对分带宽(胖树)。
- **张量并行**:节点内通信→NVLink处理此需求(不需要网络)。
- **流水线并行**:相邻流水线阶段之间的通信→只需要特定节点对之间的带宽(轨道优化即可)。
- **以太网替代方案**:**RoCE v2**(融合以太网上的RDMA)在标准以太网基础设施上提供RDMA。比InfiniBand便宜,但延迟更高且更易拥塞。Google在某些TPU pod网络中使用RoCE。超以太网联盟正在开发用于AI工作负载的无损以太网。
### 训练存储
- 训练需要三个存储层级:
- **数据集存储**:训练语料(1-100 TB文本,或PB级多模态数据)。存储在分布式文件系统或对象存储中。必须支持高吞吐量顺序读取(数据加载器以大批量读取数据)。**Lustre**和**GPFS**是常见的HPC文件系统;云替代方案包括**FSx for Lustre**AWS)和**Filestore**GCP)。
- **检查点存储**:训练状态(模型权重+优化器状态+调度器状态)定期保存。对于使用Adam优化器的混合精度70B模型:每个检查点约560 GB(70B × 4字节 × 2用于优化器)。每小时保存一次,运行3个月=约2000个检查点=1.1 PB。实际上,只保留最新的N个检查点,旧的会被删除。必须足够快,使检查点不会显著拖慢训练。
- **日志和指标**:实验跟踪数据(损失曲线、学习率计划、梯度范数)。相对较小但必须实时写入。W&B、MLflow或TensorBoard处理此需求。
- **存储瓶颈**:一个16,000-GPU集群加载一个训练批次需要持续读取约100 GB/s的数据。如果文件系统无法维持此吞吐量,GPU将闲置等待数据。数据流水线优化(预取、缓存、使用WebDataset或Mosaic Streaming进行格式优化)至关重要。
### 作业调度
- GPU集群服务于多个团队和项目。**作业调度器**将GPU分配给训练作业:
- **SLURM**:标准的HPC作业调度器。用户提交作业,指定GPU数量、内存和时间限制。SLURM分配资源并管理队列。支持基于优先级的调度、抢占和团队间的公平份额分配。
- **带GPU调度的Kubernetes**(第18章文件02):云原生方法。K8s GPU设备插件将GPU暴露为可调度资源。**Volcano**和**Run:ai**增加了ML特定的调度功能:群体调度(一次为一个作业分配所有GPU,而不是逐个分配)、优先级队列和GPU时间共享。
- **调度挑战**
- **碎片化**:一个拥有1000个GPU的集群可能有200个空闲,但分布在50个节点上(每个节点4个空闲)。需要128个连续GPU的作业无法运行,即使有足够的总GPU数。**去碎片化**(迁移作业以合并空闲GPU)或**拓扑感知调度**(分配连接良好的GPU)可以解决此问题。
- **优先级和抢占**:紧急实验应抢占低优先级作业。但抢占一个已运行2天的训练作业会浪费计算资源。调度器必须在优先级和效率之间取得平衡。
- **公平份额**:团队应在一段时间内获得其分配的计算份额,即使一个团队提交的作业超过其份额。
### 容错
- 在数千个GPU运行数月的规模下,硬件故障不是异常——而是常态。16,000-GPU集群的平均故障间隔时间以小时计,而非月。
- **常见故障**:GPU内存错误(ECC可纠正和不可纠正)、NVLink故障(节点内GPU到GPU通信)、InfiniBand链路故障(节点到节点通信)、节点崩溃(内核恐慌、PSU故障)和存储故障(磁盘或控制器故障)。
- **检查点**是主要的防御手段。每N步保存完整的训练状态(模型、优化器、数据加载器位置)。故障时:识别故障节点,替换或移除它,从最近的检查点恢复训练。故障的代价是最后一次检查点和故障之间的计算量。
- **检查点频率权衡**:频繁检查点(每10分钟)在故障时浪费更少的计算,但会减慢训练(保存560 GB需要时间)。不频繁检查点(每2小时)更快,但故障时浪费多达2小时的计算。大多数团队每20-60分钟检查一次。
- **弹性训练**:现代框架(PyTorch Elastic、DeepSpeed)支持在不重启的情况下调整训练规模。如果500个节点中有2个节点故障,训练继续使用498个节点。故障节点被替换,训练在它们重新上线时自动纳入。
- **健康监控**:持续监控所有GPU(温度、内存错误、计算吞吐量)、网络链路(丢包、延迟)和存储(吞吐量、错误率)。异常时自动告警。一些集群运行定期GPU健康检查(一个简短的计算测试)以主动识别在故障前性能下降的硬件。
- **大规模场景**:训练Meta的Llama 316,384个H10054天)经历了约466次作业中断。有效训练时间仅为挂钟时间的约90%——10%损失于故障和恢复。实现90%(而非50%或70%)的基础设施是区分能训练前沿模型的组织和不能训练的组织的关键。
### 成本和效率
- 训练基础设施成本由GPU小时主导:
| 组件 | 占总成本百分比 |
|-----------|----------------|
| GPU计算 | 70-80% |
| 网络(InfiniBand | 10-15% |
| 存储 | 5-10% |
| 冷却和电源 | 5-10% |
- **GPU利用率**(模型FLOPs利用率,MFU)衡量GPU理论峰值性能中有多少被用于实际有用计算。H100峰值为989 TFLOPSFP8)。达到40-50% MFU算良好;50-60%算优秀。差距来自:通信开销(全规约、流水线气泡)、内存带宽限制以及检查点和数据加载期间的闲置时间。
- **提高MFU**:重叠计算和通信(第6章)、使用高效注意力(Flash Attention,第16章)、优化数据加载(防止GPU饥饿)、减少检查点开销(异步检查点,先检查到快速NVMe,然后后台复制到持久存储)。
- **自建vs租用**:在小规模(<256个GPU)下,云更便宜(无前期成本,按小时付费)。在大规模(>1000个GPU,持续使用6+个月)下,拥有硬件更便宜(3年内TCO低约2-3倍)。大多数AI公司混合使用:自有集群用于持续训练,云用于突发容量和实验。
## 数据库扩展
- **只读副本**:将读取查询路由到主数据库的副本。主库处理写入,副本处理读取。由于大多数工作负载是读取密集型的(95%+读取),这使读取吞吐量随副本数量线性扩展。
- **分区**(分片,来自文件01):将数据分割到多个数据库。每个分区是独立的,支持并行读取和写入。挑战是跨分区查询(连接来自不同分片的数据)。
- **连接池**:数据库有有限的连接容量。连接池(PostgreSQL的PgBouncer)在请求间复用连接,防止当数百个服务实例各自尝试连接时出现连接耗尽。
## 搜索和向量系统
### 文本搜索
- **倒排索引**:文本搜索的基础。对每个单词,存储包含该单词的文档列表。查询对每个查询词的列表求交集。**Elasticsearch**是标准:分布式、实时、支持全文搜索、聚合和地理空间查询。
- **BM25**:标准文本检索评分函数。根据词频、逆文档频率和文档长度归一化对文档评分。简单而有效——对于关键词密集型查询仍然能与神经方法竞争。
### 向量搜索
- **向量数据库**存储嵌入(高维向量)并支持快速**近似最近邻(ANN)**搜索。给定一个查询嵌入,找到$k$个最相似的存储嵌入。
- **FAISS**Facebook AI相似性搜索):一个用于ANN搜索的库(而非数据库)。支持多种索引类型:
- **Flat**:精确搜索,$O(n)$。用于小数据集或作为基准。
- **IVF**(倒排文件):将向量分区到簇中,仅搜索最近的簇。每个查询$O(n/k)$。
- **HNSW**(分层可导航小世界):基于图。构建分层图,从粗到细导航。极快且准确,是大多数应用的默认选择。
- **乘积量化(PQ)**:将向量压缩为紧凑编码以实现内存高效搜索。用准确度换取内存。
- **托管向量数据库**Pinecone、Weaviate、Milvus、Qdrant。它们处理FAISS不具备的扩展、复制和实时更新。
- **对于RAG**(检索增强生成):用户查询→用文本编码器嵌入→搜索向量数据库以找到相关文档→将检索到的文档前置到LLM提示中。检索质量直接决定LLM响应的质量。
## 可观测性
- **可观测性**是从系统外部输出理解系统内部状态的能力。三大支柱:
### 日志
- **结构化日志**(JSON)是可搜索和可解析的。非结构化日志("ERROR: something failed")则不是。始终记录:时间戳、服务名、请求ID(用于跨服务追踪)、严重级别和相关上下文。
- **ELK栈**Elasticsearch、Logstash、Kibana):标准日志流水线。Logstash收集和转换日志,Elasticsearch建立索引,Kibana可视化和搜索。
### 指标
- **指标**是随时间变化的数值测量:请求率、错误率、延迟百分位数、GPU利用率、队列深度。**Prometheus**从服务抓取指标;**Grafana**在仪表盘中可视化并设置告警。
- **服务的RED方法****R**ate(请求/秒)、**E**rrors(错误率)、**D**uration(延迟)。为每个服务监控这些指标。
- **资源的USE方法****U**tilisation(使用百分比)、**S**aturation(队列深度)、**E**rrors。为每个资源(CPU、GPU、内存、磁盘、网络)监控这些指标。
### 追踪
- **分布式追踪**跟踪单个请求跨多个服务的路径。用户请求命中API网关→特征服务→模型服务→后处理。一个**追踪**记录了每次跳转的时序,显示延迟花在哪里。
- **OpenTelemetry**:追踪、指标和日志的开放标准。一次代码埋点,导出到任何后端(Jaeger、Zipkin、Datadog)。
## 可靠性
- **SLO**(服务等级目标):目标可靠性。"99.9%的请求在<200ms内完成。"这给出了具体的错误预算:0.1%的请求(每月约43分钟)可以慢或失败。
- **SLI**(服务等级指标):测量指标。"过去5分钟的第99百分位延迟。"
- **SLA**(服务等级协议):有后果的合同承诺。"如果可用性低于99.95%,客户获得信用额度。"
- **错误预算**:如果你的SLO是99.9%,而你达到了99.99%,你就有进行风险变更(部署新模型、迁移数据库)的预算。如果你只有99.85%,冻结所有变更,专注于可靠性。错误预算将可靠性从抽象目标转化为可衡量的资源。
- **混沌工程**:故意注入故障(杀死服务器、添加网络延迟、破坏数据)以测试系统是否能正确处理。Netflix的Chaos Monkey随机终止生产实例。如果系统保持运行,它就是有弹性的。如果崩溃了,你在用户之前发现了一个bug。
## CI/CD
- **持续集成**:自动构建和测试每次代码变更。每次推送触发:lint、类型检查、单元测试、集成测试。任何失败,变更被拒绝。这能在bug到达生产之前捕获它们。
- **持续部署**:自动部署通过CI的变更。部署策略:
- **蓝绿部署**:运行两个相同的环境(蓝色=当前,绿色=新版本)。将流量从蓝色瞬间切换到绿色。如果绿色失败,切换回蓝色(即时回滚)。
- **金丝雀部署**:将一小部分流量(1-5%)路由到新版本。监控错误。如果指标良好,逐步增加流量。这限制了不良部署的影响范围。
- **功能标志**:部署新代码但隐藏在标志后面。为部分用户启用该标志(内部测试人员,然后是beta用户,然后是所有用户)。将部署(代码上线)与发布(用户看到功能)解耦。
- 对于ML:CI/CD包括模型特定的步骤。模型变更触发:单元测试(形状测试、梯度检查)、在保留集上评估(准确率不得下降)、影子部署(新旧模型并行运行,比较输出)和逐步推出(金丝雀从1%→100%)。