85.30 GFLOPS Single-Core FP32 Matrix Multiplication on AMD Zen 3: A Systematic Study of Cache Blocking, Register Blocking, FMA Chaining, and On-the-Fly Packing
本文针对 AMD Zen 3 微架构进行了一项系统性的优化研究,通过评估 28 种不同的缓存/寄存器分块、FMA 链化以及即时打包配置,实现了单核 FP32 矩阵乘法 85.30 GFLOPS 的性能,并最终确定了一个达到理论峰值性能 63.5% 的冠军设计,同时引入了一个用于未来优化的预测模型。
原始论文采用 CC BY 4.0 许可(https://creativecommons.org/licenses/by/4.0/)。 这是对下方论文的AI生成解释。它不是由作者撰写或认可的。如需技术准确性,请参阅原始论文。 阅读完整免责声明
想象一下,你正试图把一大堆沙子(数据)从一个巨大的仓库的一侧移动到另一侧,但你必须使用一个微小且超快的机械臂(处理器)来完成。目标是尽可能快地将这些沙子与一种特殊的配方进行混合(矩阵乘法)。这篇论文是研究员卢卡斯(Lucas)的详细日志,记录了他如何让这个机械臂在一种特定的计算机芯片——AMD Zen 3上运行得尽可能快。
宏大目标:多快才算快?
这个机械臂的理论最高速度是 134.4 GFLOPS(即每秒 1344 亿次数学运算)。你可以把它想象成高速公路上的限速。卢卡斯想要看看,在不更换新车的情况下,仅通过调校引擎,能让这个速度接近这个限速值多少。
在测试了 28 种不同的驾驶策略后,他发现了一个“冠军”配置(称为 MX24),其速度达到了 85.30 GFLOPS。这大约是最大速度的 63.5%。虽然没能达到完美的 100%,但这比起点处只有 1.51 GFLOPS 的笨拙方法有了巨大的飞跃。事实上,他的最佳方法比基础的、未经优化的版本快了 57 倍。
获胜策略:“4 行、链式-4”之舞
为了获得这种速度,卢卡斯必须弄清楚如何组织沙子以及机械臂的动作。以下是他发现的关键招式:
1. “即时”打包技巧
想象一下,沙子存储在一个网格中,你必须走斜线才能抓取下一粒沙。这既慢又累。卢卡斯发现,在机械臂需要沙子之前,先将一小块沙子复制成一条整齐的直线(这被称为即时打包/on-the-fly packing),这就是神奇的招数。这就像有一个助手提前跑过去,把砖块堆成完美的一排,这样机械臂就可以连续抓取而不会绊倒。这击败了那种直接按原样抓取的旧方法,甚至比预先重新排列整个仓库的效果还要好。
2. “4 行”堆叠
机械臂有有限数量的手(寄存器)来抓取沙子进行作业。卢卡斯尝试过抓取 2 行、4 行和 8 行沙子。
- 2 行: 太少了。机械臂不得不频繁停下来去抓取新沙子。
- 8 行: 太多了!机械臂的手太满了,导致它不得不不断地把沙子掉在地上(内存)然后再捡起来。这简直是一场灾难。
- 4 行: 黄金分割点。尽管机械臂不得不放下一些沙子再重新捡起来(这个过程称为“溢出/spilling”),但增加的工作量是值得的,因为它可以同时处理更多的沙子。仅仅这一项改变,就让机械臂的速度比 2 行模式快了 59%。
3. “链式-4”节奏
机械臂完成一次数学运算(周期/cycles)需要 4 秒,然后才能对同一块沙子开始下一次运算。如果机械臂只做一个动作然后等待,它会闲置 3 秒。
卢卡斯发现,如果机械臂手里拿着 4 堆不同的沙子并循环往复地工作(链式-4/Chain-4),它就能保持持续运动。当一堆沙子正在“烹饪”时,它会转而处理其他几堆。这完美契合了机械臂 4 秒的“烹饪时间”,让引擎始终保持全速运转。
什么行不通(“不要做”清单)
有时候,你认为行得通的想法实际上会让情况变得更糟。卢卡斯测试了一些流行的想法,发现它们对于这个特定的机器人来说表现糟糕:
- “预取”错误: 人们通常会告诉机器人“向前看”,在需要之前先抓取下一粒沙子。卢卡斯尝试了这种方法,但机器人的内置眼睛已经足够敏锐,能看清模式,因此额外的“向前看”指令反而成了阻碍。这让机器人的速度下降了约 8%。
- “非临时性”倾倒: 有一种技巧是告诉机器人直接把沙子倒在地上,而不先放入收集箱。如果你只是在倒垃圾,这招很管用。但在这里,机器人必须“混合”沙子,这意味着它稍后还得把沙子捡起来。直接倾倒导致机器人自己绊倒了自己,使其速度骤降至可怜的 1.24 GFLOPS。
- “8 行”过载: 正如前面提到的,尝试同时拿 8 行沙子会导致机器人掉落太多沙子,以至于它花在捡沙子上的时间比移动沙子的时间还多。
我们有多确定?
这篇论文对这些数字非常有信心,因为它们是测量出来的,而不是靠猜。卢卡斯为每种策略运行了 15 次代码,剔除了最快和最慢的几次运行(以避免奇怪的计算错误),并对剩下的运行结果取了平均值。他还通过一个简单的、缓慢的版本来校验数学运算,以确保快速版本没有“作弊”。
他甚至建立了一个数学上的**“预过滤”模型**——类似于一种“水晶球”——可以在实际运行策略之前预测其速度。这个水晶球表现得相当不错,对于大多数策略,其预测值与真实速度的误差在 11.3% 以内。它的预测倾向于保守,预测最佳策略为 78.1 GFLOPS,但实际运行时,它达到了 85.30 GFLOPS。
总结
这篇论文证明了,你不需要成为一个能写“汇编语言”(机器人的母语)的巫师也能获得惊人的速度。通过使用标准的工具(C++ intrinsics)并仔细调校“舞步”(分块、链式处理和打包),你可以让你的计算机运行到其理论最大速度的 63.5%。
核心教训是:不要靠猜。 对一种机器人(或计算机芯片)有效的招式,可能会让另一种机器人崩溃。卢卡斯测试了 28 种不同的组合才找到了最合适的方案,这表明有时那些“显而易见”的技巧(比如向前看或直接倾倒)其实是错误的路径。
您所在领域的论文太多了?
获取与您研究关键词匹配的最新论文每日摘要——附技术摘要,使用您的语言。