想象你是一家大型餐厅的主厨,要为二十桌客人同时上菜。默认模式下,你像一个新手:每做一道菜都翻一次菜谱、洗一次锅、把半成品端回冰箱,下一次再取出来接着做——每一步都很灵活,随时能改口味,但慢得让人抓狂。这就是 PyTorch 默认的“急切执行”(eager execution)模式。而 XLA 这位“宴会总策划”完全不同:它会把整本菜谱从头到尾读一遍,理出工序流程,把能合并的步骤合并成一锅炒,把食材按取用顺序摆到最顺手的货架,最后把整套方案交给厨房里那条专为“猛火快炒”设计的流水线灶台——TPU,一次上齐二十桌的菜。 XLA(Accelerated Linear Algebra,加速线性代数)就是这样一个“先计划、后执行”的编译器,TPU 则是专为矩阵乘法而生的定制芯片。理解它们,就是理解 AI 大规模训练与高效推理的底层引擎。这篇文章将带你以“筹备一场宴会”的视角,完整走一遍从模型到机器码的编译流程。
掌握 XLA 编译流程与 TPU 架构,是 AI 编译优化工程师、训练基础设施工程师的核心能力,也是让大模型训练成本与推理延迟大幅下降的关键杠杆。
目录
可视化演示
展示XLA编译流程核心机制:HLO计算图构建、编译优化Pass流水线、TPU硬件执行与加速效果,通过交互理解XLA与TPU协同编译原理。
本节配有交互动效(进入视口后自动加载,约 3KB)。
HLO构建:计算图抽象 PyTorch模型转为HLO计算图 XLA以HLO为编译器中间表示 Model → HLO Graph HLO图描述计算依赖关系
编译动机:从“边想边做”到“先计划后执行”
想象一位新手厨师:他每做一道菜都翻一次菜谱,每翻一次都要重新点火、洗锅,做完一道菜还要把半成品端回冰箱。PyTorch 默认的 eager 模式就是这样——每一行算子代码都立刻在硬件上执行,灵活但低效。每执行一个算子,都伴随着一次内核启动(kernel launch)开销,也就是“重新点火洗锅”的成本。
经验丰富的宴会主厨则完全相反:他在开席前把整本菜谱读完,画出工序流程,把能合并的步骤合并,开席后按计划流水作业。这正是“先编译、后执行”的静态图(static graph)思想。XLA 就是那位“宴会总策划”:它先把整个模型读进来,统一优化,生成一份总执行计划,然后把计划交给硬件高效执行。
一个包含 N 个算子的模型,在 eager 模式下要付出 N 次内核启动开销;而 XLA 只付出一次编译成本,之后每次执行都零额外开销。模型越大、执行次数越多(比如训练几百个 epoch),这笔“计划成本”就越划算。
回到宴会:一个真正高效的后厨,绝不是每次上菜才临时想怎么做,而是提前做好完整的排程。编译的本质,就是用一次认真的计划,换取无数次执行的高效——这就是 XLA 存在的全部理由。
- N 个算子$N$ 是模型中算子(如卷积、矩阵乘法、激活函数)的总数。
- 内核启动开销$t_{\text{launch}}$ 是每个算子启动硬件计算所需的固定时间,类似每次炒菜重新点火洗锅。
- 编译一次性成本$t_{\text{compile}}$ 是 XLA 提前规划的时间,只在首次编译或主动 AOT 编译时付出一次。
计算图基础:把菜谱画成工序流程图
一份菜谱要指挥整个后厨协作,必须先变成一张工序流程图:洗菜 → 切菜 → 焯水 → 爆炒 → 装盘。计算图(computational graph)就是模型的工序流程图。在 PyTorch/XLA 中,模型不会立即执行,而是通过 lazy tensor(惰性张量)机制,在算子被调用时先把它们记入一张图,等真正需要结果时才触发编译。
这张图中,节点是算子,边是张量数据。每条边代表一份“半成品食材”从一道工序流向下一道工序。比如 y = tanh(a * x + b) 这个三算子模型,就对应三个节点和两条数据边:x 先流入乘法节点,结果流入加法节点,再流入 tanh 节点。图还有一个重要性质:它是一个有向无环图(DAG),因此可以拓扑排序,确定谁先谁后、哪些工序可以并行。
有了这张流程图,宴会主厨才能统筹全局:哪道工序必须先做、哪些可以同时开火、哪条传菜路线最拥挤。对编译器而言,计算图就是它“看见全局”的眼睛——这是后续一切优化的基础。
- 节点集合$V$ 是所有算子节点的集合,$v_i$ 代表第 $i$ 个工序(算子)。
- 边集合$E$ 是所有有向边的集合,$(v_i, v_j) \in E$ 表示 $v_i$ 的输出流向 $v_j$ 的输入。
- 笛卡尔积$V \times V$ 表示节点之间的所有可能有序配对,边的子集限定了哪些“食材交接”真实存在。
HLO 表示:一张机器看得懂的标准指令单
工序流程图是给人看的,机器看不懂。宴会主厨会把流程图翻译成后厨统一的标准指令单:“在第 2 号灶台,对形状为 128×128 的牛肉块,执行大火爆炒 3 分钟”。HLO(High Level Optimizer,高层优化器)就是 XLA 的“标准指令单”——它是 XLA 的中间表示(IR),位于前端(图构建)与后端(代码生成)之间。
HLO 的每条指令都包含四要素:操作码(Opcode)、操作数(Operands)、形状(Shape)和布局(Layout)。操作码说明做什么,操作数指明食材,形状描述张量的维度,布局规定维度在内存里的排布顺序。有了这种统一格式,XLA 的全部优化 pass(优化通道)——代数化简、算子融合、布局分配——都在 HLO 层进行,与 PyTorch 无关,也与具体硬件无关。
标准指令单让整个后厨说同一种语言:无论菜谱来自 PyTorch 还是 JAX,最终都翻译成 HLO;无论目标是 CPU、GPU 还是 TPU,优化都在 HLO 层统一完成。这就是编译器分层解耦的智慧。
- 操作码$\text{Opcode}$ 表示算子种类,如 Add、Dot、Convolution。
- 操作数$\text{Operands}$ 是输入张量列表,相当于这份指令的食材清单。
- 形状$\text{Shape}$ 描述张量各维度大小,如 $[8, 128, 128]$ 表示批次 8、两个 128 维。
- 布局$\text{Layout}$ 决定各维度在内存中谁先谁后,直接影响访存效率。
算子融合:把多道工序合并成一锅炒
传统炒法下,每道工序都要把半成品装盘端回冰箱(内存),下一道工序再取出来——来回跑腿让人疲惫。算子融合(op fusion)就是宴会主厨的决定:把乘法、加法、tanh 这三道工序放在同一个灶台一口气完成,中间不装盘、不回冰箱,全部在锅铲上(寄存器与片上缓存)交接。
在 XLA 中,融合是最关键的优化 pass 之一。编译器分析 HLO 图中的数据依赖,把满足条件的多个算子合并成一个融合算子(fusion op),这个融合算子最终在后端落成一个内核(kernel)。融合不仅消除了内核启动开销(少点火 N 次),更重要的是大幅减少了 DRAM 访存流量——每道工序原本都要读一次、写一次内存,融合后整条链只读一次输入、写一次输出。
融合有不同类型:元素级连锁融合(elementwise fusion)适合激活、归一化这类逐元素算子;带归约的融合(reduction fusion)能把“算完后求和”也并入同一锅。但融合也不是越多越好——这就像一锅菜塞进太多食材会糊底,寄存器放不下就会溢出到内存,反而得不偿失。XLA 的融合决策依赖成本模型,在收益与资源之间找平衡。
- 中间张量大小$S$ 表示相邻算子之间流动的中间张量大小(字节),即“半成品的重量”。
- 原始访存流量$N$ 个算子各读一次写一次,总流量 $T_{\text{orig}} = 2NS$。
- 融合后流量整条链只读一次输入、写一次输出,$T_{\text{fused}} = 2S$。
- 流量比$\eta = 1/N$ 说明融合的算子越多,省下的内存流量越多,加速效果越显著。
布局分配:给食材安排最顺手的货架
主厨如果随手把最常用的葱放在厨房最远的货架,每次取用都要横穿厨房。布局分配(layout assignment)就是根据每道菜的使用顺序,把张量各维度在内存中的排列方式安排好,让访存路径最短。一个四维张量 [N, C, H, W](批次、通道、高、宽)在内存里展开时,既可以按 NCHW 排列,也可以按 NHWC 排列——不同的排布决定了相邻元素在内存中是否连续。
连续的内存访问能最大限度利用缓存与带宽。例如卷积算子在某些硬件上偏好 NHWC,因为通道维连续能让滤波器的取用更集中;而矩阵乘法偏好行主序连续的大块。XLA 的 layout assignment pass 会在优化末尾,根据算子特性和硬件偏好,给每个张量指定一个布局,必要时还会插入转置(transpose)算子来“重排货架”。
厨房的货架一旦摆好,取料的效率就固定了。这也是为什么同样一个模型,只改布局就能带来两位数的性能差异。除了整体布局,XLA 还会做 tiling(分块):把大张量切成适合片上缓存的小块(tile),一块一块喂给计算单元,让数据在片上多复用几次,这就是“访存局部性”的落实。
- 四维下标$n, c, h, w$ 分别是批次、通道、高度、宽度的下标,共同定位一个元素。
- 行主序排布内存连续方向是 $w$,即同一行内相邻元素紧挨着存放,访问 $w$ 维最快。
- 跨步距离$HW$ 是一个通道占用的元素数,$CHW$ 是一张图占用的元素数,它们就是跳步的“台阶高度”。
TPU 架构:为“猛火快炒”定制的流水线厨房
GPU 像一位技术全面的万能主厨,什么菜都会做;TPU 则是一座专为“猛火快炒”(矩阵乘法)设计的流水线厨房。它的核心是一口方阵大铁锅——脉动阵列(systolic array):成百上千个处理单元(PE)排成网格,每个 PE 里固定存放一个权重值,输入数据像水流一样从一个 PE 流向相邻 PE,每经过一个 PE 就完成一次乘加,最后从阵列出口汇聚成完整结果。这就是“权重驻留、数据流动”——食材不动,火力(数据)沿阵列推进。
TPU 围绕脉动阵列设计了大量片上存储(unified buffer,统一缓存),让中间结果尽量留在芯片内部,避免频繁访问外部 DRAM。数据通路也高度专门化:激活数据从片上缓存流入阵列,权重预加载进 PE,部分和(partial sum)在阵列内部逐级累加。相比之下,GPU 用数千个通用 CUDA 核心配合复杂缓存层次,什么算子都能跑,但每瓦性能不如 TPU 专精。
TPU 把“乘法累加”这个最频繁的动作做成了一条物理流水线,让 XLA 生成的高效计划真正变成每秒千万亿次的爆炒。这也是为什么我们说 TPU 不是更快的 GPU,而是一台为特定菜系量身定制的厨房——矩阵乘法是它的灵魂,其他菜品则未必擅长。
- 输出元素$C_{ij}$ 是结果矩阵第 $i$ 行第 $j$ 列的元素。
- 累加求和$A$ 的第 $i$ 行与 $B$ 的第 $j$ 列对应元素相乘后累加,共 $K$ 项。
- 脉动映射在脉动阵列中,$B$ 的权重驻留在各 PE 内,$A$ 的数据流经每个 PE 完成一次乘加,一个时钟周期推进一格。
编译管线:从模型到机器码的完整旅程
宴会的筹备不是一步到位的:前厅经理先接单记录需求,总厨统筹工序形成菜单,各灶台领班再把菜单翻译成本灶台的熟练操作。XLA 编译管线正是这条“接单 → 统筹 → 落地”的流水线。第一阶段是前端(frontend):PyTorch/XLA 通过 lazy tensor 追踪算子调用,构建计算图,再把图翻译成 HLO 指令——相当于把客人需求写成标准菜单。第二阶段是 HLO 优化器:在 HLO 层执行代数化简、算子融合、布局分配等一系列 pass,得到优化后的 HLO——这是总厨统筹排程、精简工序的环节。
第三阶段是后端(backend):针对不同硬件生成可执行代码。CPU 和 GPU 后端通过 LLVM 将 HLO 转换为 LLVM IR 再到机器码;TPU 后端则把 HLO 编译成脉动阵列的专用指令。这条管线支持两种使用方式:JIT(Just-In-Time,即时编译)在程序运行时首次执行前现场编译,灵活但有冷启动开销;AOT(Ahead-Of-Time,预先编译)在部署阶段就编译好,运行时直接加载产物,省去现场编译的等待。
一条管线、多个后端,这就是“一次编写、到处高效执行”的秘密。理解这条管线,你就知道优化该在哪个环节用力:想在推理阶段省时间,就用 AOT 把编译提前;想调试融合效果,就盯住 HLO 优化器的输出日志。
- 追踪建图$\text{trace}$ 通过运行一次模型(或 lazy tensor 收集),得到计算图 $G$。
- 前端翻译$\text{frontend}$ 把计算图转成标准 HLO 指令。
- HLO 优化$\text{opt}$ 执行融合、布局等优化通道,得到优化后的 $\text{HLO}^*$。
- 后端落地$\text{backend}$ 针对不同硬件生成可执行产物 $\text{Exec}$(CPU/GPU 走 LLVM,TPU 走专用指令)。
调优实践:让厨房火力全开的智慧
再好的厨房也有瓶颈:炉子火力再猛,传菜通道太窄也一样堵塞。调优实践的起点是 Roofline 模型(屋顶模型),它像一个“瓶颈测量器”:横轴是算术强度(每字节数据支撑多少次运算),纵轴是可达性能。模型画出一条先上升后水平的屋顶线——低于拐点时,性能被内存带宽压住;高于拐点时,被计算峰值压住。它告诉我们:瓶颈到底在“炉子”还是“传菜”。
实际调优时,先用 profiler(性能剖析器)看算子的访存与算力数据,算清算术强度,对照 Roofline 判断瓶颈。带宽受限的模型(如大量逐元素算子)优先用算子融合、减少中间张量;计算受限的模型(如大矩阵乘法)优先增大 batch、优化 tiling 和布局,让脉动阵列尽量满载。常用编译选项还包括:AOT 预编译消除启动开销、bf16 混合精度降低访存与计算压力、调整融合阈值等。
一个典型实战案例:某推荐模型含大量逐元素算子,在 TPU 上 profiler 显示算术强度只有 8 FLOPs/Bytes,远低于拐点,明显带宽受限。工程师开启更激进的算子融合并改用 AOT 编译后,DRAM 流量下降 70%,端到端推理延迟从 6ms 降到 1.5ms。调优的本质永远是“识别瓶颈、对症下药”——Roofline 就是你和任何硬件对话的通用语言。
- 峰值算力$\pi_{\text{peak}}$ 是硬件每秒最多能完成的浮点运算次数(FLOPs/s)。
- 带宽上限$\beta$ 是内存带宽(Bytes/s),$I$ 是算术强度(FLOPs/Bytes),两者相乘得到“喂得饱的数据能支撑多少算力”。
- 瓶颈判断当 $I$ 小于拐点时 $P = \beta I$,内存受限;当 $I$ 大于拐点时 $P = \pi_{\text{peak}}$,计算受限。
AI 应用场景
PyTorch/XLA 在 TPU 上训练大模型
阶段:模型训练与编译加速
解决的问题:传统 eager 训练在 TPU 上算子粒度小、调度开销大,TPU 利用率普遍不足 50%。PyTorch/XLA 通过 lazy tensor 自动建图并交给 XLA 融合优化,把几百个小算子合并成几十个大算子,真正发挥 TPU 阵列算力——相当于把“一盘一盘零散上菜”改成“流水线批量出餐”。
具体案例:在 Google Cloud TPU v4 上微调 7B 参数 LLM 时,配合 torch_xla、bf16 混合精度与 AOT 缓存编译结果(环境变量如 XLA_USE_BF16),训练吞吐提升约 1.8 倍,TPU 利用率从 42% 升至 86%。
推理服务的 AOT 编译与低延迟优化
阶段:模型部署与推理优化
解决的问题:JIT 模式下服务加载模型后首次推理要现场编译,导致冷启动慢、延迟抖动大。AOT 在部署阶段提前完成 XLA 全流程编译,把可执行产物落盘,服务启动后直接执行——相当于宴会前就把所有菜配好料、排好序,客人坐下就能上菜。
具体案例:某广告点击率预估服务把模型用 XLA AOT 编译成 TPU 可执行文件后,P99 推理延迟从 8ms 降到 1.3ms,服务重启成本从分钟级降到秒级,高峰期 TPU 利用率稳定在 90% 以上。
Python 演示
"""迷你算子融合模拟器: 对比 eager 模式与 XLA 风格融合的访存开销""" import mathimport time class FusionSimulator: """模拟 N 个算子融合前后的 DRAM 访存流量与理论加速比""" def __init__(self, op_count, tensor_bytes): self.op_count = op_count # 算子数量 self.tensor_bytes = tensor_bytes # 每个中间张量大小(字节) def eager_traffic(self): # 急切模式: 每个算子独立读输入、写输出 return 2 * self.op_count * self.tensor_bytes def fused_traffic(self): # 融合后: 整条链只读一次、写一次 return 2 * self.tensor_bytes def speedup(self): return self.eager_traffic() / self.fused_traffic() def fused_forward(x): """融合后的三算子模型: y = tanh(a * x + b), 只遍历一次数据""" a, b = 0.5, 1.0 return [math.tanh(a * xi + b) for xi in x] def eager_forward(x): """急切模式: 逐步计算, 每步都产生并读回中间张量""" a, b = 0.5, 1.0 t1 = [a * xi for xi in x] t2 = [v + b for v in t1] return [math.tanh(v) for v in t2] def main(): x = [i * 0.01 - 5.0 for i in range(10000)] sim = FusionSimulator(op_count=3, tensor_bytes=80000) print("eager 模式访存流量:", sim.eager_traffic(), "bytes") print("fused 模式访存流量:", sim.fused_traffic(), "bytes") print("理论提速: %dx" % sim.speedup()) start = time.time() y1 = eager_forward(x) eager_time = time.time() - start start = time.time() y2 = fused_forward(x) fused_time = time.time() - start assert all(abs(m - n) < 1e-9 for m, n in zip(y1, y2)) print("eager 耗时: %.5fs, fused 耗时: %.5fs" % (eager_time, fused_time)) print("结果一致, 融合版只遍历一次数据.") if __name__ == "__main__": main()
class FusionSimulator:定义一个模拟器类,封装访存流量计算,对应 XLA 成本模型中的访存估算。return 2 * self.op_count * self.tensor_bytes每个算子读一次、写一次,所以总流量是 2 × 算子数 × 张量大小。return 2 * self.tensor_bytes融合后整条链只读一次输入、写一次输出,流量与算子数无关。def fused_forward(x):用单循环完成乘法、加法、tanh 三步,等价于 XLA 生成的融合内核。def eager_forward(x):逐步产生t1、t2中间列表,模拟 eager 模式每步落内存。assert all(abs(m - n) < 1e-9 ...)断言两种方式结果一致,说明优化不改变数学语义。if __name__ == "__main__":提供可执行入口,运行后直接看到访存流量对比。
常见误区
误区我一直以为 XLA 是 Google 为了让 TPU 跑 PyTorch 而专门写的编译器,我自己用 GPU,应该完全用不上 XLA。
正解XLA 是一个多后端编译器,CPU、GPU、TPU 都有对应的后端实现。它的 HLO 优化(融合、布局等)对所有后端通用,GPU 用户同样能吃到红利。就像一套标准菜谱,既能在普通灶台上做,也能在工业厨房里做——TPU 只是它服务得最出名的一个“厨房”而已。
为何常见:XLA 和 TPU 总是成对出现在宣传材料里,PyTorch 中开启 XLA 最常见的动机也是跑 TPU,容易让人误以为两者绑定。
误区TPU 不就是 GPU 的升级版吗?反正都是算矩阵,谁算得快谁赢,那买 TPU 就好了。
正解TPU 与 GPU 是“专用 vs 通用”的区别。TPU 的脉动阵列把矩阵乘法做成物理流水线,每瓦性能和吞吐极高;代价是灵活性差——动态形状、稀疏计算、复杂控制流都不擅长。GPU 用数千个通用核心配合复杂缓存,什么算子都能跑。选硬件要看模型结构,好比“专业蒸锅蒸包子一流,但炒菜还得用炒锅”。
为何常见:两者外观相似、都用于深度学习,且 TPU 的矩阵吞吐数据更高,于是被简单类比为“更强的 GPU”。
误区只要在 PyTorch 里加上 `import torch_xla`,训练速度就会自动起飞,不用做任何额外配置。
正解XLA 的收益来自融合、布局优化和消除启动开销,但编译本身要花时间,而且对模型形状有要求。小模型、动态形状、含大量数据依赖分支的模型,编译开销可能抵消收益甚至变慢。生产环境要用 profiler 验证,配合 AOT 或编译缓存把一次性开销摊薄——就像请宴会策划要花钱,小聚会未必值得。
为何常见:宣传材料总以“编译后提速 X 倍”举例,却不会强调这是针对特定模型与硬件的理想结果。
误区既然融合能减少访存,那把整个模型融成一个超级算子,性能不就是最高的吗?
正解融合意味着单内核内完成所有工序,中间结果全部塞进寄存器和片上缓存。融合过度会导致寄存器溢出(spill)到内存,反而增加流量;此外不同硬件对融合形状各有偏好。XLA 的融合决策依赖启发式成本模型,在“省访存”与“寄存器压力”之间找平衡——就像一锅菜塞太多食材会糊底,锅的大小是硬约束。
为何常见:理解了“融合能省内存访问”后,容易按直觉推出“极致融合=极致性能”,忽略了硬件资源上限这一约束条件。
面试题
Q1. 关于 XLA 的核心目标,下列说法最准确的是?
- A.加速线性代数运算← 正确答案
- B.统一深度学习框架
- C.压缩模型存储体积
- D.简化超参数调优
答案:A。XLA 全称 Accelerated Linear Algebra,核心就是通过编译优化加速线性代数计算。它不统一框架、不压缩模型、不调超参,后三者是其他工具(如 ONNX Runtime、量化工具、AutoML)的职责。
Q2. XLA 用于描述和优化计算图的中间表示是?
- A.TorchScript 表示
- B.HLO 中间表示← 正确答案
- C.ONNX 中间表示
- D.TVM 中间表示
答案:B。HLO(High Level Optimizer)是 XLA 的中间表示,所有融合、布局优化都在这一层完成。TorchScript 是 PyTorch 的表示,ONNX 是跨框架交换格式,TVM 是另一个编译器生态,都不属于 XLA。
Q3. 算子融合带来最主要的好处是?
- A.提高浮点运算精度
- B.减少内存访问次数← 正确答案
- C.简化模型结构设计
- D.减少训练数据准备
答案:B。融合把多个算子的中间结果留在片上,免去反复读写 DRAM,核心收益是访存流量从 2NS 降到 2S。融合不改变运算精度,也不影响模型设计与数据准备。
Q4. TPU 脉动阵列中用于执行乘加运算的基本单元是?
- A.通用 GPU 核
- B.处理单元 PE← 正确答案
- C.张量核 Tensor Core
- D.中央处理器 CPU
答案:B。脉动阵列由大量处理单元(PE)组成网格,每个 PE 驻留一个权重并完成乘累加。Tensor Core 是 NVIDIA GPU 的单元,GPU 核与 CPU 都不是脉动阵列的组成。
Q5. XLA 编译器支持的后端包括哪些硬件?(多选)
- A.CPU 后端← 正确答案
- B.GPU 后端← 正确答案
- C.TPU 后端← 正确答案
- D.FPGA 后端
答案:ABC。XLA 是标准的多后端编译器,CPU、GPU、TPU 都有成熟后端(GPU 走 LLVM,TPU 走专用指令)。FPGA 不在 XLA 官方支持的后端列表中,属于其他编译工具链的领域。
Q6. 下列哪一项不属于 XLA 编译流程的阶段?
- A.前端图追踪转换
- B.HLO 优化器处理
- C.后端代码生成
- D.模型超参数搜索← 正确答案
答案:D。XLA 管线由前端建图、HLO 优化、后端生成三阶段构成。超参数搜索是训练框架层的工作,与编译无关,属于干扰项。
Q7. 根据 Roofline 模型,以下哪些说法是正确的?(多选)
- A.算力受限时融合收益小← 正确答案
- B.带宽受限时融合收益大← 正确答案
- C.拐点位置取决于硬件← 正确答案
- D.算术强度越低越有利
答案:ABC。Roofline 拐点 = 峰值算力 / 带宽,随硬件变化;低于拐点是带宽受限,融合能切走大量内存流量,收益大;高于拐点是算力受限,访存已不是瓶颈,融合收益小。D 说反了——算术强度越低越容易带宽受限,通常是不利的。
Q8. 与 JIT 编译相比,AOT 编译的最大优势是?
- A.支持动态输入形状
- B.避免运行期编译开销← 正确答案
- C.可以自动调整学习率
- D.不需要保存模型文件
答案:B。AOT 在部署阶段预编译成可执行产物,运行时直接加载,消除了 JIT 首次推理的现场编译等待与延迟抖动。它不支持动态形状,与学习率无关,并且恰恰需要保存编译产物。
Q9. 以下哪些操作能提升 TPU 的利用率?(多选)
- A.增大训练批量大小← 正确答案
- B.使用算子融合策略← 正确答案
- C.总是选用最小分块
- D.合理设置数据布局← 正确答案
答案:ABD。增大 batch 让脉动阵列更饱满,融合减少访存停顿,合理布局提升访存局部性,都能提升利用率。C 错误:分块过小会让阵列吃不饱,需要在局部性与并行度之间权衡。
Q10. 脉动阵列中“权重驻留”(weight stationary)是指?
- A.权重固定放在片上阵列← 正确答案
- B.权重与输入都放片上
- C.权重按批次传入阵列
- D.权重在内存间来回搬运
答案:A。脉动阵列将权重预加载进各 PE 并保持不动,输入激活数据像水流一样流过阵列完成乘累加——“权重不动、数据流动”。这正是它省电高效的关键设计。