想象你是一家大餐厅的主厨。今天来了六百位客人,菜单上有三道硬菜:蛋炒饭、红烧肉、还有一锅需要炖十小时的佛跳墙。你的后厨里有好几种灶:有宽大的平底锅(一次能摊八个蛋)、有专门炖大菜的深炖锅、还有一排普通小灶。你会怎么安排?聪明的你一定知道:蛋炒饭要用平底锅一次炒一大份;佛跳墙要用深炖锅慢慢炖;普通小灶留给需要灵活调整的菜品。这个“看锅做菜”的过程,就是 AI 编译器(比如 TVM)要做的事情。 在深度学习世界里,程序员写好的模型就像菜谱,而 CPU 和 GPU 就是你的灶台。CPU 的 SIMD 指令集是一口宽平底锅——一条指令同时处理多个数据;GPU 的 Tensor Core 则是专门为矩阵乘法打造的深炖锅——一次指令就能算一小块矩阵。编译器要做的,就是把每一个算子(如卷积、矩阵乘)安排到最合适的“锅”上,还要考虑食材怎么切(数据布局)、灶台怎么分配(线程调度)。这篇文章,我们就走进这家“AI 餐厅”的后厨,看看主厨是怎么做这些决策的。
理解目标硬件特性映射,是写出高性能推理引擎、掌握 TVM 算子调优的底层能力。它能让你从“会写模型”进阶到“让模型跑得飞快”,这是 AI 工程化落地中区分初级与高级工程师的关键分水岭。
可视化演示
展示CPU SIMD向量并行执行、GPU Tensor Core矩阵乘累加及AI编译器算子映射流程,交互切换理解深度学习算子到硬件的优化映射。
本节配有交互动效(进入视口后自动加载,约 3KB)。
CPU SIMD向量并行 宽向量寄存器一次处理多数据 AVX-512寄存器512位并行 SIMD 单指令多数据提升CPU并行度
1. 硬件加速原理
餐厅里做荷包蛋,新手用单孔小灶一个一个煎,老师傅用大平底锅一次煎八个。CPU 的 SIMD 就是这口大平底锅——它的寄存器很宽(像锅面很大),可以同时容纳多份数据,执行一条指令就完成八个数据的同一操作。这就是“单指令多数据流”的直觉:锅越大,一次处理的菜越多。
在 CPU 上,这种“一条指令处理多份数据”的技术叫 SIMD(Single Instruction, Multiple Data)。你写的循环 for i in range(8): c[i] = a[i] + b[i],编译器可以把它向量化为一条 SIMD 加法指令,同时完成 8 个加法。而 GPU 则走得更远:它用几千个线程并行执行同样的指令,这种模式叫 SIMT(Single Instruction, Multiple Threads,单指令多线程)。要注意,SIMD 不等于多核——多核是几个厨师各炒各的菜,SIMD 是一个厨师用大锅一次炒多份相同的菜。
衡量 SIMD 的加速效果,可以用向量化加速比公式。假设一个任务中可向量化的比例是 p,向量宽度是 w(一次处理 w 个元素):
1. 分子 1 是串行执行的总时间基线:把整个任务耗时记作单位 1,这是没有向量化时的基准
2. 分母中 (1-p) 是串行部分耗时:p 表示可向量化的比例,剩下的 1-p 只能老老实实逐条指令执行
3. 分母中 p/w 是向量化后的耗时:向量宽度 w 意味着原来处理 w 份数据的时间现在只够处理一份
4. 整体加速比是新旧时间之比:分母两项相加就是新方案的期望耗时,用旧耗时除以它就是加速倍数
大平底锅虽好,但如果菜谱里有 20% 的步骤没法一锅炒(比如每份菜需要单独调味),那就算锅再宽,加速也会打折扣。这正是编译器动手优化前,要先“看看菜谱里有多少能一锅炒的部分”的原因。
2. Tensor Core 架构
如果说 SIMD 是宽平底锅,那 Tensor Core 就是后厨里的“佛跳墙专炖锅”。它不炒散菜,只负责炖一种菜——矩阵乘法。你把两锅食材(矩阵 A 和 B)倒进去,它用一组内置的微型算盘一次性算出一小块结果 C。普通灶台要一勺一勺地搅,这口锅直接整块炖熟。
Tensor Core 是 NVIDIA 从 Volta 架构开始在 GPU 中加入的专用硬件单元。普通 CUDA core 一次做一次乘加(scalar),而一个 Tensor Core 硬件单元一次能完成一个 4×4×4 的矩阵乘法运算。调用时由 warp(32 个线程的编组)协作完成,每个线程负责结果矩阵的一小部分。因为计算完全在硬件内部完成,省去了反复搬运数据的开销,所以对矩阵乘法密集的模型(比如 Transformer)特别有效。
一次 4×4×4 矩阵乘法的运算量可以用这个公式刻画:
1. m×n×k 是矩阵乘法的乘加次数:计算 C[m,n] = A[m,k] × B[k,n],需要 m×n×k 次乘法和同样多次加法
2. 每次乘加计 2 次浮点运算:一次乘法算一次运算,一次加法又算一次运算,所以每对乘加贡献 2
3. 总运算量是 2×m×n×k:当 m=n=k=4 时,即 2×4×4×4=128 FLOPs,这就是一个 4×4 张量核单次指令的工作量
Tensor Core 还常常搭配混合精度:输入用 FP16(半精度)加速计算,累加过程用 FP32 保证精度,避免误差越积越大。这道“佛跳墙”为什么快?因为一切都在锅里面完成,不需要把半成品端出来再倒进去——这也解释了为什么 Tensor Core 对满是矩阵乘法的 Transformer 模型特别友好。
3. 内存层级影响
主厨的后院有个食材库:手边调料架(寄存器)、台面备菜区(共享内存)、后院冷库(全局内存)。取调料几乎不花时间,走一趟冷库却要半天。再会算账的主厨,如果食材搬运太慢,菜也快不起来——计算机系统也是一样。
计算机的内存层级中,寄存器最快但容量极小;GPU 的共享内存是片内高速存储,类似操作台;全局内存容量大但速度慢,类似冷库。深度学习模型动辄上 GB 参数,访存往往才是真正的瓶颈。数据布局(NCHW 还是 NHWC)会影响访存是否连续,布局不对,冷库取货就要走很多冤枉路;访存合并(相邻线程访问相邻地址,合并成一次事务)就是减少“冤枉路”的关键技术。
算术强度衡量每次访存能支撑多少次运算:
当 I 很低时(比如逐元素相加,读两个数加一次,I≈0.5),性能受限于内存带宽而不是算力。搬数据所需时间的下限是:
1. 算术强度 I 是运算量除以访存量:每搬 1 字节数据能支撑多少次浮点运算,比值越高说明数据复用越好
2. 访存时间下限等于数据量除以带宽:带宽 b 的单位是字节/秒,数据量 B 除以带宽就得到秒数
3. 整体耗时取计算时间与访存时间的较大者:灶台开火时数据没到就得等,数据到了灶台没空也白搭
所以主厨做菜前先想好“食材怎么摆、一次搬多少”。把搬运细节安排妥当,灶台才能火力全开,不然 GPU 有一半时间在“等菜”。
4. 算子映射策略
六百人的宴席,一道大菜不可能一整锅出。主厨的策略是把食材分成小份,分给几口锅同时炖——这就是分块(Tiling)。AI 编译器面对 4096×4096 的大矩阵乘,同样会切成小块,分给不同的线程块处理。
分块大小不是随便定的:块太大放不进共享内存,块太小又无法隐藏访存延迟。编译器的算子映射策略包括:循环分块(把大循环拆成小循环)、向量化宽度选择(匹配 CPU 的 SIMD 寄存器)、Tile 切分(匹配 GPU 的线程块结构)、线程绑定(决定每个线程计算哪个子块)。
假设分块后 A、B、C 三个子矩阵的大小分别是 t_m×t_k、t_k×t_n、t_m×t_n,分块方案必须满足共享内存容量约束:
1. A 分块的元素数是 t_m×t_k:要算出 C 的 t_m×t_n 块,需要读到 A 的 t_m 行、t_k 列共 t_m×t_k 个元素
2. B 分块的元素数是 t_k×t_n:同理,B 分块需要 t_k 行、t_n 列
3. C 分块的元素数是 t_m×t_n:这是结果矩阵对应的小块
4. 总字节数不超过共享内存容量:float32 每个元素占 4 字节,三块加起来必须在共享内存放得下
分块就像备菜盘——每口锅旁边放好一份刚好够用的食材,既不让台面堆满,也不让锅空等。在 CPU 上,分块要匹配 L1/L2 缓存大小;在 GPU 上,Tile 大小还要和线程块(block)里的线程数对齐。
5. 调度原语
主厨有自己的工具箱:切菜刀把大块食材切小,大平底锅负责宽炒,深炖锅负责慢炖。TVM 也有一套“厨具”——调度原语(Schedule Primitive)。原语是编译器里的基础操作,用来把计算图“摆布”成适合特定硬件的形态。
TVM 中最常用的原语包括:split(把循环切小)、fuse(把两个循环合并)、vectorize(标记向量化)、tensorize(替换成硬件张量指令)、parallel(并行化)。这些原语像乐高积木,组合出千变万化的映射方案。关键设计是“调度与实现分离”:同一种算子逻辑(compute)可以通过不同调度(schedule)映射到不同硬件,而输出结果完全一致。
向量化宽度的选择由 SIMD 寄存器位宽决定:
1. L_simd 是 SIMD 寄存器位宽:比如 AVX2 是 256 位,SSE 是 128 位,ARM NEON 是 128 位
2. B_dtype 是单个元素的位宽:float32 是 32 位,FP16 是 16 位,INT8 是 8 位
3. 相除得到一次能处理几个元素:256÷32=8,正好是 AVX2 一次处理 8 个 float32
tensorize 原语更直接:把一小段计算替换成硬件提供的专用指令(如 Tensor Core 的 mma 指令),相当于告诉后厨“这道菜直接用佛跳墙锅”。工具本身不复杂,复杂的是组合它们的经验——AutoTVM 这类自动调优工具,正是用搜索算法帮你试出最佳组合。
6. 性能优化指标
餐厅开张三个月,老板要复盘:灶台闲置率多高、上菜速度多少、食材搬运时间占比多大。这些指标决定了餐厅能赚多少钱,也决定了算子的优化空间。衡量算子映射质量的核心指标有:算力利用率(实际达到的 FLOPs ÷ 硬件峰值)、内存带宽利用率、以及延迟与吞吐。
Roofline(屋顶线)模型把计算和访存统一起来看,是经典性能分析工具。它画出一条屋顶线:当算术强度低时,性能被带宽“压”在天花板下;当算术强度超过某个转折点后,性能才被算力决定。核心公式:
1. P_peak 是硬件峰值算力:比如 A100 GPU 在 FP16 Tensor Core 下的理论峰值约 3.1×10^14 FLOP/s
2. I×B_peak 是带宽撑起的算力上限:算术强度 I 乘以峰值带宽 B_peak,表示“搬数据的最大能力”对应的算力
3. 整体取两者较小值:短板决定上限,哪边先到顶就卡在哪里
当算术强度大于转折点 P_peak / B_peak 时,任务才算计算密集,否则就是访存密集。有了这些 KPI,主厨就能精准定位问题:菜上得慢,到底是锅太小(算力不够)还是食材搬运太慢(带宽瓶颈)?优化不再是玄学,而是有数据支撑的工程决策。
7. 硬件抽象层
连锁餐厅要开分店,每家店的灶台不一样:有的店是大平底锅,有的店是深炖锅。主厨不想给每家店重写一遍菜谱,于是把“灶台能力”抽象成一张标准需求单——告诉每家店:我这道菜需要“宽煎”或“炖煮”能力,你用自己的方式实现。TVM 的硬件抽象层就是这张需求单。
TVM 用 Target 描述硬件特性(比如 llvm -mcpu=skylake 或 cuda -arch=sm_80),后端根据 Target 做指令选择。TVM 的 Intrinsic(内置函数)定义了硬件原生操作,比如 Tensor Core 的 mma.sync.aligned.m16n8k8。这样一来,同一个中间表示(IR)可以被翻译成不同硬件的代码,实现“一处编写,多端部署”。
后端代码生成时,会用一个成本模型做决策:
1. N_instr 是生成的指令条数:指令越多,执行开销越大,在 CPU 上尤其明显
2. N_mem 是访存操作次数:访存是相对昂贵的操作,尤其在 GPU 上全局内存访问动辄几百周期
3. α、β 是权重系数:不同硬件上指令与访存的相对代价不同,编译器通过标定这两项来贴合目标硬件
标准菜单让主厨的绝活能被复制到所有分店。硬件抽象层让同一个 AI 模型轻松部署到手机、电脑、服务器和车载芯片上,这正是 TVM 这类编译器的核心价值。
AI 应用场景
推理引擎部署优化
阶段:模型部署 / 推理优化
解决的问题:同一个模型要跑在多种 GPU 上,手动为每个算子适配硬件极其耗时,而且普通工程师很难懂 Tensor Core 的底层调用细节。TVM/TensorRT 这类工具自动识别矩阵乘算子,将其映射到 Tensor Core 并选择 FP16+FP32 混合精度,大幅缩短部署周期。
具体案例:将训练好的 BERT 模型通过 TensorRT 部署到 A100 上。TensorRT 自动把注意力中的矩阵乘替换为 Tensor Core 指令,并把 LayerNorm 融合成单个核函数,推理延迟从 12ms 降到 3.5ms,吞吐提升约 3 倍。
移动端 CPU 向量化优化
阶段:端侧推理优化
解决的问题:手机没有独立 GPU 或 GPU 不可用,必须在 ARM CPU 上跑模型。ARM 的 NEON SIMD 指令集相当于那口“宽平底锅”,可以把逐元素算子(ReLU、量化反量化、逐通道缩放)向量化,榨干移动端算力。
具体案例:在 Android 手机上部署人脸检测模型。用 NEON 指令把逐元素 ReLU 和 INT8 反量化算子向量化(一次处理 4 或 8 个数据),单帧延迟从 50ms 降到 15ms,电池功耗也明显下降。
自动驾驶芯片算子开发
阶段:芯片工具链 / 算子库开发
解决的问题:定制化 AI 芯片往往有专用加速单元,但通用框架(PyTorch/TensorFlow)无法自动利用。需要用编译器把自定义算子映射到特定硬件特性上,同时满足自动驾驶严格的延迟要求。
具体案例:在英伟达 Orin 上,用 TVM 为分割模型生成融合算子。把 Conv+BN+ReLU 三个算子融合成一个核函数,并通过 tensorize 映射到 Tensor Core,端到端延迟降低 40%,满足 L2+ 辅助驾驶的实时性要求。
Python 演示
def simd_width(simd_bits, dtype_bits): """根据 SIMD 寄存器位宽计算一次能处理几个元素""" return simd_bits // dtype_bits def arithmetic_intensity(op_type, shape): """估算算子的算术强度 I = FLOPs / Bytes""" if op_type == "matmul": m, n, k = shape flops = 2 * m * n * k bytes_read = (m * k + k * n) * 4 return flops / bytes_read if op_type == "elementwise": flops = shape[0] bytes_read = shape[0] * 8 return flops / bytes_read return 0.0 def roofline_time(flops, peak, band, intensity): """Roofline 模型估算耗时: 计算时间与访存时间取最大""" t_calc = flops / peak t_mem = flops / (intensity * band) return max(t_calc, t_mem) class OpMapper: """把算子映射到目标硬件的决策器""" def __init__(self, name, simd_bits, peak_flops, bandwidth, has_tc): self.name = name self.simd_bits = simd_bits self.peak_flops = peak_flops self.bandwidth = bandwidth self.has_tc = has_tc self.plan_list = [] def make_plan(self, op_type, shape): """生成映射方案: 向量化宽度、Tile 大小与是否用 TensorCore""" wide = simd_width(self.simd_bits, 32) plan = { "op": op_type, "hw": self.name, "simd_parallel": wide, "tile": (16, 16, 16) if self.has_tc and op_type == "matmul" else (1, 1, shape[2]), "use_tensor_core": self.has_tc and op_type == "matmul", } self.plan_list.append(plan) return plan def estimate_ms(self, op_type, shape): """估算在该硬件上的执行毫秒数""" if op_type == "matmul": flops = 2 * shape[0] * shape[1] * shape[2] else: flops = shape[0] intensity = arithmetic_intensity(op_type, shape) if self.has_tc and op_type == "matmul": peak = self.peak_flops else: peak = self.peak_flops * 0.1 time_s = roofline_time(flops, peak, self.bandwidth, intensity) return time_s * 1000.0 def main(): cpu = OpMapper("x86_64-avx2", 256, 1.6e12, 5e10, False) gpu = OpMapper("A100-tc", 128, 3.1e14, 2e12, True) shape = (1024, 1024, 1024) for hw in (cpu, gpu): plan = hw.make_plan("matmul", shape) ms = hw.estimate_ms("matmul", shape) print("硬件:", hw.name) print(" 每指令并行元素:", plan["simd_parallel"]) print(" Tile:", plan["tile"], "使用 TensorCore:", plan["use_tensor_core"]) print(" 预估耗时: %.3f ms" % ms) if __name__ == "__main__": main()
wide = simd_width(self.simd_bits, 32)用寄存器总位宽除以 float32 的 32 位,算出这口“宽锅”一次能炒几个元素。"tile": (16, 16, 16) if self.has_tc and op_type == "matmul" else (1, 1, shape[2])碰上有 Tensor Core 的 GPU 且算子是矩阵乘时,按 16×16×16 分块下锅;否则用朴素整块方案。intensity = arithmetic_intensity(op_type, shape)先算算术强度,判断这道菜是“计算量管够”还是“食材搬运费时”。time_s = roofline_time(flops, peak, self.bandwidth, intensity)用 Roofline 短板模型预估耗时,取计算与访存中更慢的那个。if __name__ == "__main__":一键跑起来,对比 CPU 与 GPU 的映射决策和预估性能。
常见误区
误区把循环标上向量化后,从 128 位换成 512 位寄存器,觉得速度一定能翻几倍。毕竟“锅宽了嘛”。
正解加速上限受 Amdahl 定律和访存带宽双重限制。如果可向量化比例 p 只有 50%,w 翻倍加速也到不了 2 倍;如果数据在内存里搬不动,CPU 只会“等菜”而不是“炒菜”。性能提升的瓶颈常常不在寄存器位宽,而在内存。
为何常见:纸面上看到 AVX2→AVX512 位宽翻倍,容易拿 512÷256 直接算加速,忽略了真实系统的其他瓶颈。
误区买了带 Tensor Core 的 GPU,觉得所有算子都会自动变快,包括逐元素 ReLU、Softmax、数据归一化这些“小菜”。
正解Tensor Core 只加速矩阵乘法以及能转化为矩阵乘法的算子(如卷积)。逐元素算子访存密集,即使“炖锅再厉害”,也没法减少每一份食材的搬运量,强行使用反而可能因为数据格式转换更慢。
为何常见:厂商宣传 “XX 倍性能提升” 通常基于矩阵乘 benchmark,初学者容易把特定场景的结论泛化到所有算子。
误区NCHW 和 NHWC 只是数据的排列顺序不同,性能应该一样,反正交给 TVM 自动优化就行。
正解在 GPU 上,NCHW 的卷积访存不连续,访存合并效率低;NHWC 对某些算子更友好。布局转换本身也要开销,编译器一般会保留你给定的布局并做局部优化,全局布局选择依然需要工程师的决策。
为何常见:PyTorch 默认用 NCHW,大家习以为常,其实在 TensorFlow 和移动端部署中 NHWC 才是默认,说明硬件对布局的偏好是真实存在的。
误区既然 TVM 能自动搜索调度参数,那我不用理解 SIMD 和 Tensor Core,也能把手里的模型优化得很好。
正解自动调优是在工程师定义的搜索空间里搜索,搜索空间的好坏直接决定结果上限。不懂硬件,你连 candidate 调度都写不出几个,更别说判断搜索结果是否合理。工具只是把经验固化成代码,理解原理才能驾驭工具。
为何常见:工具越来越“傻瓜化”,让人误以为底层知识不再必要。但搜索空间的设计恰恰需要懂硬件的人来定义。
误区做算子优化时,性能不达标就加大并行度或换更强的 GPU,觉得“算力不够就堆算力”。
正解Roofline 模型告诉你,当任务访存密集时,换更强的卡、加并行度收益甚微;应该优化数据复用、提高算术强度。方向和努力同样重要——先判断瓶颈在哪,再决定怎么优化。
为何常见:算力指标(TFLOPS)最显眼,带宽是后台指标,容易被忽视。但真实世界中大多数算子卡在带宽上。
面试题
Q1. CPU 的 SIMD 加速依靠什么硬件特性?
- A.多个 CPU 核并行运算
- B.宽寄存器装载多份数据← 正确答案
- C.流水线深度加倍提高
- D.缓存命中率显著提高
答案:B。SIMD 的核心是宽寄存器(如 YMM 256 位),一条指令对寄存器里的多份数据同时运算。多核并行是 MIMD 不是 SIMD;流水线和缓存是另一类优化手段,与“单指令多数据”无关。
Q2. GPU 的 Tensor Core 专门加速哪类运算?
- A.标量的乘加运算
- B.矩阵乘法与卷积← 正确答案
- C.数据的排序归并
- D.显存的高速拷贝
答案:B。Tensor Core 是 NVIDIA 为矩阵乘法设计的专用硬件单元,卷积可通过 im2col 等方式变成矩阵乘后使用它。标量运算用 CUDA core 即可,排序和拷贝不是 Tensor Core 的目标场景。
Q3. 以下哪些属于 CPU 上的 SIMD 向量化实例?
- A.AVX2 一次处理 8 个 float← 正确答案
- B.SSE 一次处理 4 个 float← 正确答案
- C.多核并行执行不同函数
- D.ARM NEON 处理 4 个 float← 正确答案
答案:ABD。AVX2 是 256 位寄存器处理 8 个 float32,SSE 是 128 位处理 4 个,NEON 是 ARM 的 SIMD 指令集。多核并行是任务级并行(MIMD),不是单指令多数据的 SIMD。
Q4. GPU 中“访存合并”描述的优化技术是哪个?
- A.相邻线程访问相邻地址合并为一次事务← 正确答案
- B.多个线程共享同一个寄存器文件
- C.将串行循环合并成向量指令
- D.用缓存预取隐藏所有访存延迟
答案:A。访存合并指 warp 内相邻线程访问连续地址,硬件把这些访问合并成少数几个内存事务,减少请求次数。C 是循环向量化,B 是寄存器共享,D 是缓存预取,都与访存合并的定义不同。
Q5. 256 位 AVX2 寄存器处理 float32 数据,一次能算几个元素?
- A.4 个元素
- B.8 个元素← 正确答案
- C.16 个元素
- D.32 个元素
答案:B。256 ÷ 32 = 8。float32 是 32 位,256 位寄存器正好装 8 个。这就是向量化宽度的基本公式:寄存器位宽除以元素位宽。
Q6. 以下哪些属于 TVM 的调度原语?
- A.split 循环切分← 正确答案
- B.vectorize 向量化← 正确答案
- C.compile 全流程编译
- D.tensorize 张量化← 正确答案
答案:ABD。split、vectorize、tensorize 都是 TVM Schedule 中用来调整循环结构与映射方式的原语。compile 是最终编译生成代码的流程,不属于调度原语。
Q7. Tensor Core 混合精度计算的典型组合是哪个?
- A.FP32 权重输入 FP16 计算
- B.FP16 输入输出 FP32 累加← 正确答案
- C.INT8 权重输入 FP32 累加
- D.FP64 输入输出 FP64 累加
答案:B。Tensor Core 常用 FP16 做矩阵乘输入,FP32 做累加,兼顾速度与精度。FP32 输入无法利用 Tensor Core 的 2 倍吞吐优势,INT8 是量化场景的另一种组合,FP64 与 Tensor Core 无关。
Q8. 某 GPU 实测 1024³ 矩阵乘耗时 2ms,峰值算力 10 TFLOPS,算力利用率约为多少?
- A.约 10%← 正确答案
- B.约 35%
- C.约 70%
- D.约 95%
答案:A。1024³ 矩阵乘 FLOPs = 2×1024³ ≈ 2.15e9。2ms 内实际算力 ≈ 1.07 TFLOPS,除以峰值 10 TFLOPS ≈ 10.7%。算力利用率 = 实际 FLOPs ÷ 峰值 ÷ 时间。
Q9. 关于 AutoTVM 自动调优,下列说法正确的是哪些?
- A.它自动搜索更优的调度参数← 正确答案
- B.它可以完全替代工程师定义搜索空间
- C.它需要使用硬件反馈评估候选方案← 正确答案
- D.它不需要任何先验硬件知识
答案:AC。AutoTVM 在工程师定义的搜索空间中用模拟退火等算法搜索参数,并用真实硬件测量或成本模型预测来评估候选方案。工程师仍需定义搜索空间,硬件知识决定了搜索空间的质量,因此 B、D 错误。
Q10. 某平台峰值算力 10 TFLOPS、带宽 2 TB/s,计算与访存平衡点的算术强度约为多少?
- A.5 次/字节← 正确答案
- B.20 次/字节
- C.50 次/字节
- D.200 次/字节
答案:A。Roofline 转折点 = 峰值算力 ÷ 峰值带宽 = 10e12 ÷ 2e12 = 5 次/字节。算术强度低于 5 时被带宽限制,高于 5 时被算力限制。这是判断任务属于“计算密集”还是“访存密集”的关键阈值。