BREAK LAYER 研究阅读室

Agent怎样决定下一步:从具体观察到实验,再到修改判断

按问题跳读 · 每节自带背景 · 11节先交代证据:哪些“为什么”能从记录中知道案例一:加硬件没有解决问题,agent怎样发现应该改程序分工案例二:预测模型选错了,为什么还保留它,又怎样修改它案例三:遇到“存储放不下”,怎样判断是硬件限制还是当前排布限制案例四:阶段里有指数运算,为什么功率问题却来自内存案例五:融合明明省了搬运,为什么试两次后还要退回原方案案例六:把原本串行的两段并行,为什么还会互相拖慢案例七:整道投影还没做完,有些后续计算已经可以开始案例八:准备工作只做一次,也值得检查能否和第一次计算合并案例九:评测工具出错、版本改变,怎样避免把研究记录写乱下次怎样保存一段真正有用的agent研究过程

一名agent可以尝试几千个参数,却仍然不知道程序为什么慢。这份复盘关心另一件事:它怎样从报告、代码和失败中找到一个足够具体的问题,再用一次实验判断值不值得继续。

这里的任务是让Transformer模型在一套可配置的教学机器上运行。agent同时选择硬件资源和程序分工。程序必须算对、面积不超过24平方毫米、任意连续1000周期的平均功率不超过20瓦,然后才比较耗时。下文的周期与功率都来自模拟器,未做真实芯片测量。

我们用“方案三”指代一套附带搜索记录的提交,不讨论它的排名。另一条对照是你自己的Astra更新路径。每节都是一个可以独立阅读的案例:先给背景,再交代agent当时看到什么、怎样验证、结果让它改变了什么。 数字用来分清实验状态,不能把不同阶段的数值拼成一次改动的收益。

先交代证据:哪些“为什么”能从记录中知道

五套成品中,本次只有方案三提供了项目源码、实验摘要和5份对话快照。我们提取了225条agent对外消息,选出43条技术相关说明;225条消息不代表225次实验。你的Astra方案保留157条实验记录及一段对外进度说明,也没有覆盖全部原生对话。

因此,下文分别写清三种内容:

内容 可以怎样理解 本文怎样呈现
当时报告的发现 agent当时明确说看见什么,并据此安排下一步 给出记录号;它仍可能是尚未验证的诊断
代码与数据解释 从最终代码或保存结果说明一个改动怎样起作用 写明“机制解释”;不补造agent未说过的想法
我们提炼的做法 读完案例后,建议下一次研究怎样保存和使用证据 写明是复盘建议,未经流程对照实验验证

为了便于从中间阅读,每节都会重述必要术语。全篇反复出现的两道题是:P1一次处理一段已有输入,D1连续生成8个新位置。 D1后一步输入要等前一步完成才释放,但每一步使用相同权重。SM是硬件计算单元,WG是交给它的一份任务组,RF是该组直接用于计算的小存储,HBM是较大的外部内存。

案例一:加硬件没有解决问题,agent怎样发现应该改程序分工

背景:机器有多个计算单元,程序却只安排一组干活

P1要处理一段输入,每个位置都要乘同一份模型权重。SM是能并行干活的计算单元;WG是程序交给它的任务。只创建一组任务,就算机器还有空闲SM,也不会自动把这份工作拆过去。

在记录14中,agent明确报告:此前只调硬件约得到1661分,P1主要由单个工作组串行执行。它提出按输入位置分工,让不同工作组同时算不同的行,并在每层键和值写完后同步,防止后续计算读到未完成的数据。

这是第一轮判断:先使程序真正用上已有并行资源。记录没有把原因泛称为“硬件不够”,而是指出了可检查的程序事实——只有一个工作组在执行主要任务。

用上并行后,为什么又改成按输出列分工

按输入行拆任务有一个代价:多组会读取相同权重。可以用一个说明例子理解:若两组分别处理前半段和后半段输入,而每组都需要同一矩阵,那么这份权重可能被搬两次。划分任务时省下了等待,却可能增加数据搬运。

记录102指出了这个重复读取问题。agent随后改为按输出列分工:每组持有自己负责的权重列,供多行输入连续使用。当时这个版本把权重保存在片上共享暂存中;不能把后来的最终寄存器布局倒填到这一阶段。

记录104先报告独立数值和时序检查通过,同时保留完整P1尚在评测的状态。随后它进一步把两段输入放到同一套计算安排里,增加权重复用;记录108确认完整评分通过,P1为985,681周期。

这次判断留下什么经验

agent连续改变了两次问题:先问“有没有足够多的独立任务”,再问“这些任务是否重复搬相同数据”。第一次有效的并行方法暴露了第二个成本。人类复盘时,应画出每组读哪些权重、算哪些输出;只记“增加工作组”会漏掉这段转向。

这几条记录跨越多个版本,不能把全部性能差异归为按行改按列这一项。能确认的是:串行执行和重复读取分别触发了两次有明确对象的改动。

案例二:预测模型选错了,为什么还保留它,又怎样修改它

背景:预测一次便宜,模拟整个程序昂贵

在这场软硬件联合设计中,一个候选包含机器配置和矩阵分块方式。完整模拟要检查搬运、等待、数值和功率,成本比简单算账高。agent使用COPT求解工具,在一个简化模型里挑候选。这个“代理模型”用估计工作量和流量预测耗时;它并不完整模拟所有请求的排队。

记录96报告了一个直接反例:模型选中一次计算32列的分块,运行模拟时却不如64列。32和64指一个小矩阵块覆盖多少输出列,块更宽可能增加复用,也会占用更多小存储。这个反例说明,模型的候选排序存在缺口。

当时agent没有把模型输出当成最终成绩:它把模拟中更好的分块与其他改动组合,再跑完整程序。记录104也区分了局部测试已通过和整套评分还未完成。

后来找到一个可以补进模型的具体漏项

D1逐步生成新位置。它的一道前馈计算叫W1:把128维向量变成512维。每个工作组开始矩阵乘法前,还需要准备和归一化输入。若同一个计算单元上的W1工作分散给两个组,两组可能各做一遍相同准备。

记录164明确发现这个重复归一化机会。于是分配模型开始计入“启用一组任务就会产生的输入准备成本”,并尝试把同一计算单元的W1任务集中到一组,同时仍检查每组的小存储是否够用。记录165确认完整评分和额外随机输入检查通过,D1降到42,467周期。

用一个说明例子理解这个模型更新:两种分工都做同样数量的矩阵乘法,旧模型可能觉得差不多;如果一种要准备两遍输入,另一种只准备一遍,新模型就应把这笔差额写进去。代码中的active变量表示某个阶段是否启用了某组任务,它让这笔成本可以被计数。分配模型源码。

怎样解释求解器报告的“最优”

最终保存的分配文件有160份任务、32个任务槽,简化目标值为2143,下界也为2143。意思是在它允许的任务归属和约束下,已经闭合这个小问题的目标差距。它仍有限制:为了先算出查询向量,一些任务归属已被固定,W2也有固定分工。2143不是D1的真实周期,更不代表所有可能程序都搜完了。

复盘建议是保留两种记录:模型预测候选好在哪里,完整模拟又在哪一段推翻预测。如果能指出具体漏掉的成本,就修模型;如果目标程序结构根本不能用现有变量表示,就改程序生成方式。你的Astra方案从独立权重分配转向跨两道矩阵乘法的融合,属于后一种情况。

案例三:遇到“存储放不下”,怎样判断是硬件限制还是当前排布限制

背景:总容量够,不保证一条指令能使用它

计算指令读取的小存储叫RF,每个工作组共有64 KiB。它还被划成物理分区,指令操作数需要满足分区边界。一个说明例子是:总共还有8 KiB空闲,却散在几个分区里,一块要求连续地址的8 KiB操作数仍可能放不下。

方案三原来的编译器在增加向量通道数时报告容量问题。向量通道是同时处理多个数字的硬件资源;改变通道配置也会影响合法的指令形状与存储分区。agent没有直接把这个方向判为硬件不可行。记录168提出先重新分块,把跨边界的指令拆开,再检查数值等价与实际收益。

为什么第一次改对了,还要继续改布局

记录169中,修改后的D1和单个W1矩阵操作都变快,但完整P1触发了搬运调度检查异常。这里要区分三件事:局部计算正确、局部更快、完整程序可以评测。前两件成立,并没有自动给出第三件。

下一步它让输入、权重和尚未累加完成的输出直接对齐物理分区,减少先产生不合适形状、再被迫切碎搬运的情况。单个W1操作由32,162周期,经29,024,进一步到26,326;这是这一组局部实验的结果。记录169–170。

消费者变了,生产者也必须跟着改

后续二维分块实验中,W2负责将前馈网络的宽向量压回原宽度。相同局部矩阵计算,在普通行排列下为37,007周期,改为沿求和方向连续存储后为20,090周期。记录180。这里“沿求和方向”指一次点积需要依次读取的那些元素,把它们放近,有机会减少零碎搬运。

但放回完整P1时又出问题:前面的层归一化仍按旧方式跨分区写数据,被拆成许多小传输。层归一化是对一个向量计算均值、方差并调整数值尺度的操作。agent在记录183定位到这处写回,改为先在RF里整理成连续块,再写外部内存。到记录185,完整P1才通过,耗时293,205周期。

这次调查的价值在于追到两个端点:下一道计算希望怎样读,上一道计算就应怎样写。单看一个矩阵块大小,会漏掉两道操作之间的格式转换。记录中的调度异常也不能全部归咎于布局:评分器后来确实更新过相关检查,最后一节会说明如何保留这种不确定性。

案例四:阶段里有指数运算,为什么功率问题却来自内存

背景:知道哪道计算超功率,还不足以知道该减少什么

P1一次处理整段输入,其中注意力用softmax把相关分数变成权重。softmax需要指数计算,机器上的SFU单元负责指数等特殊函数;HBM则是外部大内存。整个程序只要有一个连续1000周期窗口超过20瓦,就不合格。

agent把原来逐行执行的softmax改为分阶段调度,P1缩短到274,926周期,却达到20.452瓦。记录191当时提出缩小并行处理的行组,尝试错开活动。之后把组缩到4行或8行仍未消除峰值,它继续检查启动时刻和资源配置。记录193。

这两次失败没有证明所有调度办法无效;它们说明已测试的改动没有消除当前限制,下一步需要更细的诊断。

决定性的证据是最高窗口里各资源在做什么

记录198给出了不同于算子名称的线索:最高功率窗口内,8个HBM通道连续满载,SFU完全空闲。既然负责指数的单元当时没有活动,就缺少证据把这个窗口的峰值归因于指数计算。

agent转向减少注意力反复读取的K/V。K是历史位置的键,用于与当前查询比较;V是这些位置携带的信息,用于加权合成结果。它把重复使用的K/V留在任务组的小存储RF,并按物理存储边界分块。新的完整P1单场景为257,395周期、19.694瓦,随后与D1组合通过完整评分。记录201、记录202。

从“发生在哪”追到“当时谁在忙”

可迁移的检查顺序是:先找到最热时间窗口,再看这段时间哪些资源有活动,接着回到相关读写和指令,最后挑一项能改变这些活动的实验。只根据“在注意力附近”猜测,定位仍然太粗。

资源满载、SFU空闲是agent当时报告的诊断;本复盘没有重新运行全部能量事件分析。后续K/V驻留结果支持这一方向,但因还同时调整了分块,不能把全部收益精确拆给一个因素。你的Astra路径也出现了同类转折:放慢查询/键/值计算的广播没有压峰,删除后续集中搬运后才进入预算。

案例五:融合明明省了搬运,为什么试两次后还要退回原方案

背景:省下一次写读,也可能增加另一种通信

Transformer的前馈网络连续做三件事:W1把向量变宽,GELU对每个元素做变换,W2把向量压回原宽度。普通分工会把中间宽向量写到外部内存,再由下一组读回。融合让同一组连续处理其中一段,中间数值留在小存储里。

问题是每组只处理一段中间通道,因此它算出的最终输出还只是一份贡献,叫“部分和”。所有组的贡献要再汇总。融合减少中间向量搬运,同时引入部分和的读写与相加;在执行前无法只凭名字判断净收益。

记录187在提出实验时已明确写出这个代价:让第二次矩阵乘法读取留在RF的激活结果,同时显式汇总部分结果,需要测试额外成本。

第一次失败后,没有只留下一个“更慢”的数字

首版数值正确,但联合操作从40,846周期变为59,443周期。agent检查请求方式,报告多个工作组同时读相同输出列,使外部内存请求集中到少数通道,于是测试错开各组读列的顺序。记录188。

错开后降到48,013周期,说明新安排缓解了部分问题,却仍慢于40,846的原方案。更大分块的两个变体也未改善。它将这些保留为失败实验,继续用已通过额外输入检查的原版本,转向同步范围、预装载批次和其他分工。记录189。

这轮局部对照 周期 对下一步的意义
原方案 40,846 必须超过的实际参照
第一次融合 59,443 算对但明显退步,需要查新增成本
错开列读取顺序 48,013 部分改善,仍不足以采用

它否定的是哪一个命题

记录支持的结论是:这份布局和调度下,已测试的融合版本没有净收益。它不支持“前馈融合总是无效”。你的Astra最终采用了融合,但使用另一种生产、汇总与装载安排。

人类下次遇到融合,可以先列清楚被删掉哪次搬运、新增哪份部分和、权重是否被重复读取、谁必须等谁,再设计一个局部对照。失败数据如果保留了这些条件,才能帮助下一次选择;只留下“融合失败”会误导后来的搜索。

案例六:把原本串行的两段并行,为什么还会互相拖慢

背景:归一化结果没完成,投影真的只能等吗

D1逐步生成新位置。常规计算顺序是:先对当前输入向量求均值和方差,做层归一化,再乘权重矩阵,得到注意力或前馈需要的向量。每步输入不同,因此统计量需要现算;但归一化中的缩放系数和偏置参数已经固定。

记录197提出利用代数重排,把可预先计算的常量准备好,让部分矩阵乘法与统计同时进行,最后再按当前均值、方差组合结果。它也指出两个待验证成本:常量准备是否太贵,以及改变计算顺序后浮点误差能否通过检查。

一个简化公式说明为什么有并行机会

设输入为x,其均值为μ,标准差因子为σ(实际含防止除零的极小稳定项);固定参数为逐元素缩放γ、偏置β,投影权重是W。这里⊙表示逐元素相乘,后面的乘W表示矩阵乘法。忽略书写细节的核心恒等式是:

归一化后投影 = [(x ⊙ γ)W − μ(γW)] / σ + βW

γW和βW只依赖固定参数,可以提前算;(x ⊙ γ)W只依赖当前输入,不需要先等均值、方差。两条支路都完成后再组合。这个式子解释并行机会,实际实现仍需保留稳定的方差计算和评分要求的浮点误差检查。归一化与投影重排代码。

数学上独立,不等于硬件上不争资源

首版通过功能检查,但D1只降到33,825周期。阶段跟踪发现:统计集中在一个控制组上执行,与矩阵投影争用RF端口,也就是争用读取小存储的通道。记录200。原先的前后依赖被减轻了,资源竞争却仍然存在。

agent因此把统计拆给多个组。每组算局部均值及围绕局部均值的平方偏差,再合并成完整方差,避免用容易损失精度的粗糙替代。八组版本到33,340周期,之后组合评分通过。记录201–202。

这个案例提供两次不同层次的判断:先检查数学依赖能否重排;再检查并行执行时是否抢同一硬件资源。只画一张“可以同时算”的图,不能回答实际是否缩短耗时。

案例七:整道投影还没做完,有些后续计算已经可以开始

背景:历史注意力和当前位置需要的数据不同

D1每步生成一个新位置。注意力先把这个位置的输入映射成Q、K、V:Q是拿来查询历史的向量,K是这个位置的键,V是这个位置提供的信息。历史位置的K/V早已存在。

计算“当前Q与历史K/V的关系”,需要新的Q和已有历史,但不需要先等当前位置的新K/V。当前位置自身对注意力的贡献可以稍后算,再与历史部分合并。如果程序把Q/K/V作为一个整体完成事件,历史部分就被迫等了不需要的数据。

agent怎样将这个机会转为程序改动

在记录202中,agent提出让新位置与历史部分的注意力分开推进;到记录205,它报告让Query(Q)优先完成、历史注意力提前启动后,D1降到31,258周期,功能与功率检查通过。

随后它继续测试K/V直接写到接口规定的最终地址,省去先写临时区再复制的中间读写,并调整统计组的安排。最终这一阶段完整D1为30,953周期,额外随机输入检查通过。记录208。这些是后续组合收益,不能全部归给“Q先完成”。

机制可以这样读:旧顺序是“整组Q/K/V做完 → 所有注意力开始”;新顺序是“Q先完成 → 历史部分先算,同时继续得到当前K/V → 合并两部分”。合并必须统一softmax的最大值与指数缩放,不能直接平均两个已经归一化的输出。

值得保留的是检查依赖的粒度

agent改变了完成事件的边界。让某一道矩阵乘法再快一点,只是在原顺序里优化;允许下游拿到够用的数据就先动,改变了等待本身。下次复盘任何流水程序,都可以检查:这个消费者具体需要哪几个结果?它现在是否在等待一个比实际需要更大的“全部完成”?

案例八:准备工作只做一次,也值得检查能否和第一次计算合并

背景:小输入没有占满矩阵计算阵列

D1每次只有一个新位置,可视为一行输入;矩阵计算硬件能同时处理多行,因此可能有空闲行。前述归一化重排还需要固定参数的投影结果。常规程序先单独算这些常量,再开始第一行动态输入,前面就多出一段准备时间。

记录212明确报告发现这段独立常量计算,计划把它与首个输入的投影合成一次矩阵运算,并把常量结果保存给后续7步使用。

机制上,保存的实现将首个输入和两行固定参数组织成三行矩阵:一行服务当前输入,另外两行生成可复用的常量。三行各算各的投影,同时占用原本空闲的行。实现中的首步合并计算。这不需要预知未来输入,也没有把后续8步强行并成一批。

怎样判断这类小改动是否值得保留

合并后D1由30,953降到30,464周期,数值与功率通过;之后整套评分也通过。记录213–214。评估对象是包含准备时间的完整D1,因此没有把开销移到评分之外。

接着agent又分别检查两个小机会:对GELU激活的多项式提取公因子,减少一次向量运算;一次取出整个偏置向量,让后续独立计算早点发出。相邻的“把缩放提前”候选略慢,被放弃。每项都先跑局部检查,再检查完整组合,最终提交报告中的D1为30,368周期。记录214–216。

这一节的经验是具体的:初始化结果只需在第一次使用前准备好,未必需要独立串行完成。找到它实际的截止时刻和可共用的空闲资源,就可能减少等待。但少一条指令不自动意味着更快,提前缩放的反例说明仍需测完整执行。

案例九:评测工具出错、版本改变,怎样避免把研究记录写乱

背景:一个异常退出的程序没有可比较的耗时

这轮搜索多次触发DMA调度断言。DMA是搬运引擎,断言是评测程序内部发现状态不符合预期后的停止。这样的记录不同于“数值错误”“超功率”或“合法但更慢”:它没有完成评测,不能直接判断优化机制好坏。

方案三有些更并行的候选因此中断。agent保留原来的合格程序,继续测试能完成评测的代表,而没有把异常候选的局部速度算成完整进步。记录169、记录201。

版本变化使一批失败需要重新分类

最终提交时,接口因本地报告与服务器评分器版本不一致拒收。记录218。agent核对后报告工作负载和基准未变,官方改了DMA冲突检查;它保留旧报告,启动新版本复评,并提出重查先前因相关断言中止的候选。记录219–220。

这里不能直接宣布所有旧异常都是评分器错误。能够确定的是,检查实现变了,原来的“未完成评测”需要附带版本重新理解。本次对话快照结束时复评仍在运行;最终有效提交由后来保存的服务器报告确认,不能用快照里的等待状态代替最终报告。

另一种需要分开的记录:求解输出与后处理成果

更早的搜索还尝试过把选择问题写成二次0/1优化模型,交给另一套求解设备。记录显示返回设计的面积约169.74平方毫米,远超24的上限,小存储块也超容量。之后的有效方案来自普通CPU上的合法性修复和继续调参。记录75、记录80。

因此不能把修复后的性能记为原始求解设备已经给出的有效性能,也不能根据这些记录宣称设备带来优势。无论求解工具多复杂,第一项检查仍是它的输出能否编译成合法、正确、可评测的程序。

下次怎样保存一段真正有用的agent研究过程

下面是根据上述案例提出的复盘格式,还没有通过对照实验验证它一定能提高搜索效率。目标是让后来的人能接着判断,而非只复现一组参数。

先以“融合失败”写一份完整示例:

起点: 前馈网络的两次矩阵乘法分开执行,局部对照为40,846周期。中间结果需要经过外部内存。
准备检验的想法: 让同一组连续计算,省掉中间结果往返;风险是新增部分和汇总。
第一次结果: 数值正确,但59,443周期,退步。
新增证据: 当时诊断指出,多组同时读相同列,外存通道请求集中。
第二次试验: 错开各组的读列顺序,检查这个集中是否可缓解。
结果与决定: 48,013周期,仍慢于原方案;保留原合格版本,停止继续扩展这一批变体。
结论的范围: 否定当前已测布局的净收益;不否定所有融合实现。

再从两条路径提炼选择下一步的规则:

已经看到的证据 下一次值得检查的对象 哪种结论还不能下
多个计算单元空闲,程序只有少数任务 工作能否在保持正确合并的前提下继续拆分 加更多计算单元就一定更快
同一数据被多组或多步反复读取 哪组持有数据、能保留多久、活跃容量是否足够 放进小存储后全部开销就消失
局部更快,放回完整程序却失败 上下游格式、同步、数值和最热功率窗口 局部收益可以直接加到总成绩
改了一个阶段,最高功率不动 干预有没有改变当前最高窗口的活动 该阶段永远与功率无关
预测排序与模拟排序相反 漏掉的启动、重复准备、通信或等待成本 换一个求解器就能自动补上机制
数据已够下游开始,却仍在等待 “全部完成”事件是否过大 可以直接删除所有同步

最后,一份可继续研究的实验记录至少要能回答:为什么挑这个实验,它改变了什么,其余条件是什么,数值和预算过没过,结果支持了多大范围的结论,接下来为何采用、回退或换方向。保存代码与硬件指纹、评测版本、随机输入种子和失败类别,才能在环境变化后重新判断。

两条过程最值得留下的共同点是:agent会根据新证据改变可修改的对象。从计算资源数量,到数据的存放与复用,再到任务边界和具体发出请求的时刻,每次转向都有可检查的理由。缺少这些理由的最终参数,无法教会下一名研究者从哪里开始。

读你的Astra完整过程 · 核对43条当时的对外说明 · 查看五套最终程序的构造