想象你是一家米其林餐厅新来的主厨,老板丢给你一个任务:研发一道招牌菜。传统师傅的做法是翻出祖传的菜谱模板,在“红烧”或“清蒸”这些固定框架里微调调料;而你不打算被旧模板束缚——你决定把研发拆成三步:先定这道菜的“骨架”(选清蒸还是爆炒,配什么食材次序),再填“参数”(切多大块、多大火、放多少盐),最后反复“试菜”改良(随机试一批配方,请评委打分,让高分配方互相杂交出更好的下一代)。这套流程,就是 AI 编译器里 Ansor 做的事。 深度学习模型的每个算子(卷积、矩阵乘法)本质上都是多层循环。调度(schedule)就是决定这些循环怎么切分、怎么并行、怎么向量化——相当于决定“菜怎么做”。可调度的组合空间有万亿种,暴力枚举不可能。Ansor 提出“三级调度”思想:草图(sketch)→ 注释(annotation)→ 随机采样与进化搜索(random + evolutionary search),把庞大的搜索空间一步步结构化,让编译器像大厨一样自动找到最优做法。 这篇内容将带你完整拆解 Ansor 的三级调度流水线、成本模型、与 AutoTVM 的对比,以及实际调优效果。读完你会理解:为什么“自动生成骨架 + 智能搜索”能取代“专家手写模板”,成为深度学习编译器的标配。
一句话价值:理解 Ansor 三级调度如何把天文数字的搜索空间压缩成可搜索的结构,是构建与使用 AI 编译自动调优工具链的底层认知,也是 AI 编译器工程师的必修课。
可视化演示
展示Q-Learning算法在5x5网格世界中的学习过程,智能体通过探索和利用策略逐步学习从起点到终点的最优路径。
本节配有交互动效(进入视口后自动加载,约 3KB)。
Q-Learning 探索学习 智能体在网格世界中通过ε-贪心策略探索,逐步更新Q值表 Q←Q+α[r+γmaxQ(s_next)-Q] 绿色为起点,金色为目标,红色为障碍
三级调度概述
研发新菜最怕什么?怕选择太多。切法、火候、调味、装盘,每一样都有几十种选择,组合起来是天文数字。传统大厨的做法是“凭经验限死选择”,而 Ansor 这位智能大厨反其道而行:它先定骨架缩小范围,再用参数展开覆盖面,最后用试菜精选最优——用三级流水线把“盲目试错”变成“结构化搜索”。
在深度学习编译器中,每个算子对应一段多层循环。所谓调度,就是决定循环被怎样变换:外层循环如何平铺(tiling)、内层如何向量化(vectorization)、哪些循环可以并行(parallel),以及语句以什么顺序执行。这些决策的任意组合构成了“调度空间”。问题是:调度空间的大小是各个维度自由度的乘积,常常超过 \(10^{30}\),直接把 100 台机器跑一年都搜不完。
Ansor 的关键洞察是:绝大多数优秀调度共享少量“高层次的程序结构”。于是它把调度空间推导拆成三级——第一级 sketch 只决定循环骨架,把空间压到几十个;第二级 annotation 为骨架填充平铺尺寸、并行/向量化标志,把空间展开到百万级;第三级 random 采样加进化搜索,在真实硬件反馈下快速逼近最优。三级合起来,等于把“大海捞针”变成“在精心设计的水池里摸针”。
这就像大厨的研发流水线:先定“清蒸还是爆炒”(骨架),再填“每味料放多少”(参数),最后反复试菜改良(搜索)。三级各司其职、环环相扣,Ansor 才能在学习一个算子时,快、准、省地找到好调度。
- 调度空间符号等号左边的 \(|\mathcal{S}|\) 表示所有完整调度组成的集合的元素个数,它衡量搜索空间的总大小。
- 对草图求和\(\mathcal{G}\) 是所有程序草图的集合,求和符号表示把每条草图对应的候选调度数量全部加起来。
- 注释集合大小\(\text{Ann}(s)\) 是草图 \(s\) 上所有合法注释的集合,\(|\text{Ann}(s)|\) 就是这条草图能衍生出的调度数量。
草图生成
如果大厨接到一道完全陌生的菜(比如分子料理),他不会直接跳进调料堆里瞎试,而是先想:这道菜的整体流程是什么?先怎么处理主料、中间经过哪些工序、最后怎么装盘?在 Ansor 里,这个“整体流程”就是草图(sketch):一段多层循环的骨架,规定了循环嵌套结构、计算拆分方式,但所有的尺寸和并行标志都留空待填。
草图不是人写的,而是 Ansor 内置的一组“草图规则”(sketch rules)自动生成的。每条规则都来自资深编译器工程师对“什么样的调度结构容易跑得快”的总结,例如:多层平铺规则(multi-level tiling)把一个大循环拆成“线程块—线程—向量”几个层次;约简轴拆分规则(split reduction axis)把累加循环拆开做并行;还有数据布局变换规则。
以矩阵乘法 C = A × B、维度 (M, N, K) 为例,一条草图规则会把计算写成六层循环 (Mo, No, Ko, Mi, Ni, Ki):外三层控制线程块,内三层控制单线程内的计算。注意,这里的尺寸 Mo、Mi 等都是“变量”,还没有具体数值。一个算子的表达式经过全部草图规则推导,通常只产生几条到几十条草图——相比万亿级的完整调度,这是几个数量级的压缩。
就像菜谱骨架决定了一道菜是“清蒸还是一鱼两吃”,草图决定了算子的“循环格局”。骨架选得对,后面怎么填都差不到哪去;骨架选得全,优秀调度就不会被排除在搜索空间外。
- 规则映射\(\phi\) 表示草图生成规则,它把计算表达式集合 \(\mathcal{E}\) 中的每个算子映射到一个草图集合。
- 草图集合\(\mathcal{G}\) 是生成的草图集合,数量很少,通常只有几条到几十条。
- 规模对比符号 \(\ll\) 读作“远小于”,说明草图空间只是完整调度空间的极小一部分,这正是压缩的威力。
注释填充
骨架定了,接下来就是“填参数”:清蒸鲈鱼要切几刀、蒸几分钟、淋多少豉油?Ansor 的注释(annotation)阶段做的正是这件事——为草图里的每个空白填上具体数值和标志:每层循环的平铺尺寸、是否对某层做并行、内层循环是否向量化、是否展开。
注释不是随便填的,必须满足“合法性”:平铺尺寸的乘积必须等于原循环长度;并行层数受硬件线程数约束;向量化宽度要匹配 SIMD 位宽。Ansor 会枚举某个草图上的全部合法注释,把每条注释“贴”到草图上,就得到一个完整可编译的调度。
一个草图能衍生出多少注释?以一维长度为 N 的循环、切分成 k 层平铺为例,答案等于 N 的所有“因子拆分方式”之和。这正是组合数学里的递推数:第一层可以从 N 的任一个因子 d 中选,剩下的 N/d 再递归地交给 k-1 层去拆。
注释就是“配料表”的每一格:格子越多,候选配方就越多,但同时也越能覆盖不同硬件口味。填完注释,搜索空间正式成型——这是第二级调度空间的全部内容。
- 一层平铺当只切 1 层时,唯一合法的切法就是“不切”,所以 \(f_1(N)=1\)。
- 拆出最外层\(d\) 是 \(N\) 的一个因子,记号 \(d \mid N\) 表示 \(d\) 整除 \(N\),对应切出的第一层尺寸。
- 递归剩余部分第一层取走 \(d\) 后,剩余长度 \(N/d\) 交给 \(k-1\) 层继续切分,于是得到递推关系 \(f_k(N) = \sum_{d \mid N} f_{k-1}(N/d)\)。
随机采样
注释空间的候选调度可能有上百万个,大厨不可能把每一道都真做一遍来试味。他的策略是先“闷头随机试一批”:从所有配方里均匀抓 50 个,真刀真枪地做出来,既尝到了味道分布,也为后续的“评委”积累了经验。
Ansor 在第三级的第一步就是随机采样(random sampling):对每个草图,从它的合法注释集合中均匀随机抽取若干条,得到一组完整调度。这组调度被编译并在真实硬件上各跑一次,记下实际执行时间——它们既是“初代种群”,又是训练成本模型的“测量数据”。
采样讲究均匀与覆盖:Ansor 将每条注释看成等概率事件,确保搜索空间的不同区域都能被探到。典型做法是每个草图采样几十到几百个点,总采样量在一千到几千的量级——相比全空间,这只是沧海一粟,但足以勾勒出“味道分布”。
随机试菜看似盲目,却是有价值的起点:它用很低的成本换来两样东西——对空间的初步感知(哪些区域耗时低),以及训练评委(成本模型)的第一批样本。没有这一步,后面的进化就无从谈起。
- 条件概率\(P(a \mid s)\) 表示在给定草图 \(s\) 的条件下,选中注释 \(a\) 的概率。
- 均匀取等随机采样时每个合法注释机会均等,所以概率是 1 除以注释总数。
- 注释集合\(a \in \text{Ann}(s)\) 指明注释 \(a\) 必须是该草图上的合法注释。
进化搜索
第一轮试菜后,大厨发现“酸甜口”的评分普遍高。接下来他不会把剩余一万个配方都做一遍,而是玩起“优生优育”:让高分配方杂交产生后代,偶尔让某个后代随机变异一味料,再用评委快速打分,把低分后代淘汰。循环十几代,种群整体水平一代比一代高。
Ansor 的进化搜索(evolutionary search)正是如此。它以随机采样得到的种群为起点,反复执行:用成本模型给种群中的每个程序打预测分,保留分数最高的前一半作为“父本”;然后对父本做变异(mutation)与交叉(crossover)生成新的完整调度,补充回种群。
变异算子很直接:把某个平铺尺寸改成它的因子、对换两层循环、把某层循环从 parallel 改成串行或加上 vectorize。交叉则把两个优秀程序的不同部分拼接成新程序。每个程序按适应度(fitness)排序,适应度定义为预测耗时的倒数。经过上百轮迭代,种群会向成本模型认为的最优区域快速收敛。
进化搜索的精髓是“用模型代替品尝”:真实试菜(硬件实测)很贵,只有极少数候选值得真做;而评委打分的成本极低,可以一轮筛掉几万个后代。大厨的改良速度因此快了几十倍。
- 适应度函数\(\text{fitness}(p)\) 衡量程序 \(p\) 的“优秀程度”,值越大越值得保留。
- 预测耗时\(\hat{t}(p)\) 是成本模型给出的预测执行时间,耗时越短适应度越高。
- 平滑项\(\epsilon\) 是一个很小的正数,防止分母为零导致除零错误。
成本模型
凭什么评委不用尝就能打分?因为他吃过几百道菜,心里有一套“菜谱特征→好吃程度”的经验:比如糖色深的往往更香、火候太猛容易糊。成本模型(cost model)就是 Ansor 的评委——它从历史实测数据中学习“程序特征→运行时间”的映射,专门用来预测没跑过的调度。
Ansor 的成本模型采用梯度提升回归树(GBDT)。输入是程序提取出的特征向量 \(f(p)\):各层循环的迭代次数、平铺尺寸的取值、访存次数、并行/向量化标志、缓存复用情况等;输出是预测执行时间 \(\hat{t}(p)\)。特征不需要人工精调,GBDT 会自动找到关键特征与非线性关系。
模型质量直接决定进化搜索的方向准不准。Ansor 的做法是“边搜边学”:随机采样阶段实测的数据喂给模型;进化搜索每跑一段时间,再挑几个候选真实测量,把新数据加进训练集,让评委越用越准。
评委越老辣,大厨的改良路线越靠谱。成本模型与进化搜索形成正反馈:搜索产生数据,数据训练模型,模型指导搜索——这正是 Ansor 能高效收敛的引擎。
- 预测值\(\hat{t}(p)\) 是成本模型对程序 \(p\) 运行时间的预测,带帽子的符号表示“估计值”。
- 特征提取\(f(p)\) 把程序结构转换成数值特征向量(循环层数、平铺尺寸、访存次数等)。
- 集成回归树\(h_m\) 是第 \(m\) 棵回归树的输出,\(\eta\) 是学习率,总预测是 \(M\) 棵树输出的加权和。
AutoTVM对比
在 Ansor 之前,TVM 已经有一位“老师傅”——AutoTVM。老师傅的做法是:每来一道新菜,都要先翻出他手写的几套模具(模板),新菜只能在模具里微调盐量。如果这道菜本身不在模具覆盖范围内,调得再久也没用。更麻烦的是,模具必须由人手工打造,每道新菜都要重新打模具。
AutoTVM 是 TVM 最早期的自动调优方案。工程师需要为每个算子手写调度模板,模板里留出可调参数(比如平铺尺寸有哪些候选),然后用模拟退火等算法在模板参数空间里搜索。它的优点是简单可靠;缺点是搜索空间完全被模板结构锁死,模板之外的好调度永远不会被发现,而且模板编写非常依赖专家经验。
Ansor 与 AutoTVM 的本质区别在于搜索空间如何构造。AutoTVM 的空间来自“手写模板井”,Ansor 的空间来自“自动草图展开”。论文实验显示,Ansor 推导出的调度空间比 AutoTVM 模板空间大数倍到数十倍,空间不仅更大,而且覆盖了更多样的循环结构。两代系统的搜索策略也不同:AutoTVM 用贝叶斯优化/模拟退火,Ansor 用成本模型引导的进化搜索。
用模具做点心 vs 自动捏造型再试口味:前者稳定但天花板低,后者前期工程量大但泛化能力强。Ansor 的胜出,本质是“从经验驱动到数据驱动”的范式跃迁。
- Ansor 空间\(|\mathcal{S}_{\text{ansor}}|\) 是 Ansor 自动推导出的调度空间大小,包含所有草图展开的合法注释。
- 模板空间\(|\mathcal{S}_{\text{template}}|\) 是 AutoTVM 手写模板能表达的调度空间大小,受模板结构限制。
- 数量级差距比值远大于 1,说明自动推导的搜索空间比模板空间大若干个数量级。
效果与实战
新大厨终于上菜了。同样的食材,出菜更快、味道更稳,而且全程不需要老师傅在一旁指点。Ansor 交出的成绩单:在 NVIDIA GPU 上,端到端模型推理比 TVM 默认实现快约 3.8 倍,比 AutoTVM 调优结果再快 2.6 倍;在 ARM CPU、树莓派等平台上也有 2~10 倍的提升。
这些数字来自 Ansor 论文的实验:覆盖 ResNet、MobileNet、BERT 等多种模型,以及卷积、矩阵乘法、注意力等常见算子。加速比定义为调优前的默认耗时除以 Ansor 搜索后的耗时。默认耗时是 TVM 的默认调度,Ansor 耗时是自动搜索出的最优调度实测时间。
实际落地也很简单。在 TVM 生态中,通过 Relay 的 auto_scheduler(Ansor)接口,只需两步:先 “tune“——给定目标硬件和每算子的时间预算,Ansor 自动执行三级调度搜索;再 ”apply”——把搜索到的最优调度打包进编译产物。工程师不需要手写任何模板,剩下的交给流水线。
从“老师傅手工调参”到“新大厨自动流水线”,Ansor 把算子优化的门槛从“编译器专家”降到了“调用一个接口”。三级调度思想后来也被 MetaSchedule 等新一代调度器继承,成为 AI 编译自动调优的事实标准。
- 默认耗时\(T_{\text{default}}\) 是无调优(或默认 schedule)下算子的执行时间。
- 调优后耗时\(T_{\text{ansor}}\) 是 Ansor 找到的最优调度的执行时间。
- 加速比两者之比就是加速倍数,大于 1 表示调优带来提升。
AI 应用场景
自研 NPU 的算子库自动生成
阶段:后端代码生成与算子调优
解决的问题:芯片公司为 NPU 开发算子库时,传统方法是工程师手写汇编或手调类 CUDA 的 kernel,一个算子动辄数周,且只能覆盖常用形状。Ansor 的三级调度自动推导搜索空间,用成本模型引导进化搜索,几天内就能产出接近手写性能的算子实现。
具体案例:某 AI 芯片团队在 TVM 中接入 Ansor,对 40 余个算子(conv、matmul、softmax、layernorm)自动调优,单算子调优时间控制在 5~20 分钟,最终性能达到手写算子的 90% 以上,人力成本大幅下降。
端侧模型的高效部署
阶段:推理优化与部署
解决的问题:手机端 NPU/CPU 与服务器 GPU 的硬件特性差异巨大,同一算子在两处的最优调度完全不同。手工为每一款端侧芯片调优不现实,Ansor 针对目标硬件自动执行三级调度,一键获得适配调度。
具体案例:某视觉模型团队要在多款 Android 手机上部署 YOLOv5,使用 Ansor 分别针对高通和联发科平台自动调优,端到端推理速度相比 TVM 默认提升 1.8~3.2 倍,全程未写一行调度代码。
大模型 Attention 算子优化
阶段:计算图与算子协同优化
解决的问题:Transformer 的 attention、MoE 等新算子迭代快、没有成熟模板。工程师用 Ansor 自动探索类似 flash-attention 的调度结构变体,在保持语义不变的前提下显著提升访存效率。
具体案例:某训练框架团队优化自研 LLM 的 attention 核,用 Ansor 在 A100 上自动搜索,得到比基线手写 kernel 快 1.4 倍的调度,且自动适配不同 head 维度。
Python 演示
# -*- coding: utf-8 -*-"""Ansor three-stage scheduling simplified demo."""import randomfrom math import log def fake_cost_model(scheme, N=1024): """Simulate hardware latency, regular tilings win.""" tile = scheme['tile'] cost = 0.0 for t in tile: cost += log(t + 2) if scheme['parallel']: cost -= 0.2 if scheme['vectorize']: cost -= 0.2 if max(tile) <= N // 4: cost -= 0.3 return round(cost + 1.0, 4) def enumerate_annotations(N): """Stage 2: enumerate all legal annotations.""" anns = [] for t1 in range(1, N + 1): if N % t1 != 0: continue anns.append({'tile': [t1], 'parallel': False, 'vectorize': False}) for t2 in range(1, N // t1 + 1): if (N // t1) % t2 != 0: continue anns.append({'tile': [t1, t2], 'parallel': True, 'vectorize': True}) return anns def sketch_generation(): """Stage 1: derive a few sketches (only one here).""" return [{'name': 'sketch_matmul', 'loop_dims': [1024]}] def random_sampling(anns, num=50): rng = random.Random(7) return rng.sample(anns, min(num, len(anns))) def evolve(pop, anns, generations=12): rng = random.Random(11) for _ in range(generations): pop = sorted(pop, key=fake_cost_model) keep = pop[:len(pop) // 2] pop = keep + rng.sample(anns, len(pop) - len(keep)) return pop[0] def main(): N = 1024 sketches = sketch_generation() anns = enumerate_annotations(N) print('Stage1 sketch count =', len(sketches)) print('Stage2 annotation count =', len(anns)) init = random_sampling(anns, 60) print('Stage3 random sample =', len(init), 'candidates') best = evolve(init, anns) print('Best schedule:', best) print('Predicted cost:', fake_cost_model(best)) if __name__ == '__main__': main()
def enumerate_annotations(N):第二级注释填充:把一维 N 拆成 1~2 层平铺并枚举合法尺寸组合。if N % t1 != 0: continue平铺尺寸必须整除 N,不合法的注释直接跳过。anns.append({'tile': [t1, t2], 'parallel': True, 'vectorize': True})记下一个合法注释:双层平铺且开启并行与向量化。def sketch_generation():第一级草图生成:这里简化为只有一种骨架。def random_sampling(anns, num=50):第三级第一步:均匀随机采样出初始种群。pop = sorted(pop, key=fake_cost_model)用成本模型预测值给种群排序,耗时短的排前面。keep = pop[:len(pop) // 2]保留预测最优的前一半作为“父本”。best = evolve(init, anns)执行多代进化搜索,返回最终最优调度。
常见误区
误区有初学者以为 sketch、annotation、random 是三个独立的工具,可以只用一个,甚至跳过第一级直接随机搜。
正解三级是环环相扣的流水线:没有 sketch,annotation 就没有骨架可填;没有 annotation,随机采样就没有合法空间可采。就像做菜不能跳过备菜直接下锅——框架决定上限,参数决定可行性。跳过任何一级,搜索要么空间太小错过最优,要么空间太大无法收敛。
为何常见:因为论文里分了三章讲,读者容易当成三个并列功能,忽略了它们是同一流水线上的先后工序。
误区有同学对比 AutoTVM 后觉得:Ansor 的 sketch 不就是 AutoTVM 的 template 换个名字?还是专家手工设计。
正解完全不同。AutoTVM 模板由工程师为每个算子手写,且模板内的循环结构写死;Ansor 的草图由一组通用规则自动生成,覆盖各种形状,无需人工参与。模板是“模具”,草图的“骨架”——前者是死的,后者是自动推导的。模具只能做出模具允许的形状,骨架却能展开出远超模具的调度空间。
为何常见:因为两者都是“调度空间的结构性约束”,从表面形式看很像,容易混淆本质区别。
误区有的同学认为第三级就是随机撒几千个点然后挑个最好的,跟抛硬币差不多,毫无技术含量。
正解随机采样只是起点,用来获得初始种群和训练数据。真正的主力是成本模型引导的进化搜索:变异、交叉、按预测分数保留最优。随机撒点 + 进化改良 + 模型打分三件套配合,才能高效逼近最优。随机只是“开门”,进化才是“走路”。
为何常见:只记住了名字里的 random,忽略了后面还有 evolutionary search 和 cost model 两个重头戏。
误区有同学在实战中把调优时间设到几天几夜,以为时间越长性能越强,结果收益甚微。
正解进化搜索和成本模型是渐进收敛的:前期提升快,后期收益递减,甚至因测量噪声而抖动。Ansor 的实践是给一个合理的时间预算(比如每算子几分钟到几十分钟),跑完就取当前最优,不必无限挂机。好钢要用在刀刃上,把时间分给多个算子通常比死磕一个算子更划算。
为何常见:直觉上“搜得更久 = 更优”,忽略了搜索的收敛规律和硬件测量噪声的影响。
误区有的同学以为自动调度只能用在 NVIDIA GPU 上,因为论文实验图表几乎都是 GPU,其他硬件没法用。
正解Ansor 是平台无关的调度框架,论文也在 ARM CPU、树莓派等平台上做了实验,同样有 2~10 倍加速。不同平台只是成本模型的行为不同,三级调度流程完全一致。只要目标硬件能编译执行 TVM 程序,Ansor 就能为其自动调优。
为何常见:论文实验图表以 GPU 居多,形成“Ansor 是 GPU 专用工具”的刻板印象。
面试题
Q1. Ansor 三级调度的正确顺序是?
- A.注释、草图、随机采样
- B.草图、注释、随机采样← 正确答案
- C.随机采样、草图、注释
- D.进化、注释、草图
答案:B。Ansor 先用草图规则生成程序骨架,再在骨架上填充注释(平铺、并行等参数),最后对完整注释空间做随机采样与进化搜索。顺序颠倒会导致骨架未定就无参数可填、参数未定就无处可采。
Q2. 程序草图(sketch)的核心作用是?
- A.直接输出最优调度
- B.定义循环计算骨架← 正确答案
- C.替代成本模型评估
- D.负责生成最终机器码
答案:B。草图只是定义多层循环的结构骨架,尺寸和并行标志都留空,因此它既不是最终调度,也不做评估或代码生成。它唯一的作用是压缩搜索空间的结构维度,把万亿级空间收敛到几十条骨架。
Q3. 注释(annotation)阶段需要确定的参数有?
- A.平铺尺寸大小← 正确答案
- B.是否并行执行← 正确答案
- C.展开与向量化← 正确答案
- D.算子融合方式
答案:ABC。注释负责填平铺尺寸、并行/串行、向量化/展开等循环级参数;算子融合属于计算图优化范畴,发生在调度搜索之前,不属于注释阶段。就像配料表只管分量火候,不管菜品是否拼盘。
Q4. 随机采样阶段的首要目的是?
- A.直接得到最优结果
- B.初始化种群和训练集← 正确答案
- C.生成程序草图集合
- D.降低硬件测量开销
答案:B。随机采样均匀抽出完整调度,一方面构成进化搜索的初代种群,另一方面实测结果成为成本模型的训练数据。采样本身通常不直接产出最优调度,但它是整个搜索流程的“第一桶金”。
Q5. 成本模型在 Ansor 中的角色是?
- A.计算模型参数量
- B.预测未测调度的耗时← 正确答案
- C.自动生成程序草图
- D.替代编译器后端工作
答案:B。成本模型用历史实测数据训练,输入程序特征、输出预测运行时间,从而在进化搜索中快速筛掉差候选。它不生成草图,也不算参数量,更不替代后端。它的角色是“评委”而不是“厨师”。
Q6. 与 AutoTVM 相比,Ansor 最本质的区别是?
- A.支持更多的硬件平台
- B.自动推导搜索空间← 正确答案
- C.使用 Python 实现
- D.只优化卷积运算
答案:B。AutoTVM 依赖工程师为每个算子手写模板,Ansor 用草图规则自动生成骨架并推导完整搜索空间。硬件支持和实现语言都不是本质差异。一个是“模具厂”需要人打模,一个是“自动捏造型再试口味”。
Q7. 进化搜索中的变异操作可能包括?
- A.修改平铺尺寸大小← 正确答案
- B.交换循环的执行顺序← 正确答案
- C.调整向量化与展开← 正确答案
- D.修改算子的数学定义
答案:ABC。变异在调度层面做小改动:换平铺尺寸、换循环次序、增删并行或向量化标志。算子本身的数学含义(如把矩阵乘法改成加法)不属于调度变异,那是改菜谱配方而不是调火候。
Q8. 一维循环长度 N=32,切分成 2 层平铺(顺序相关),合法注释数约为?
- A.共有 3 种
- B.共有 6 种← 正确答案
- C.共有 32 种
- D.只有 1 种
答案:B。根据递推公式 \(f_2(32)=\sum_{d \mid 32} f_1(32/d)=d(32)\)。32 的因子有 1、2、4、8、16、32 共 6 个,因此两两成对的平铺方案是 6 种。(1,32)(2,16)(4,8)(8,4)(16,2)(32,1)。
Q9. 成本模型的训练数据直接来源是?
- A.公开的公共数据集
- B.真实硬件实测耗时← 正确答案
- C.专家人工标注结果
- D.理论推导的计算量
答案:B。Ansor 把随机采样得到的调度编译后在真实硬件上运行,记录实际耗时作为标签。公开数据集、人工标注或理论复杂度都无法反映真实硬件的运行时间,必须“真刀真枪”实测才能训练出可靠的评委。
Q10. 关于 Ansor 优化效果的正确说法有?
- A.GPU 上端到端快约 3.8 倍← 正确答案
- B.ARM CPU 上也能明显加速← 正确答案
- C.调优越久收益一定线性增长
- D.三级调度结构化搜索空间← 正确答案
答案:ABD。论文显示 Ansor 在 GPU 上比默认 TVM 快约 3.8 倍,在 ARM 等平台也有明显加速;搜索是收敛的,收益随时间递减,不存在线性增长。三级调度正是通过“骨架→注释→采样”的结构化设计实现高效搜索。