<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://samsz04.github.io/feed.xml" rel="self" type="application/atom+xml"/><link href="https://samsz04.github.io/" rel="alternate" type="text/html" hreflang="en"/><updated>2026-08-05T11:09:55+08:00</updated><id>https://samsz04.github.io/feed.xml</id><title type="html">blank</title><subtitle>Personal website of Zhan Shi, featuring research interests in efficient LLM inference, TPU systems, and Telecom AI. </subtitle><entry><title type="html">从计算粒度与数据流，看 FPGA、CGRA 与脉动阵列</title><link href="https://samsz04.github.io/2026/07/14/fpga-cgra-systolic-array-report/" rel="alternate" type="text/html" title="从计算粒度与数据流，看 FPGA、CGRA 与脉动阵列"/><published>2026-07-14T18:50:00+08:00</published><updated>2026-07-14T18:50:00+08:00</updated><id>https://samsz04.github.io/2026/07/14/fpga-cgra-systolic-array-report</id><content type="html" xml:base="https://samsz04.github.io/2026/07/14/fpga-cgra-systolic-array-report/"><![CDATA[<blockquote> <p>以深度学习硬件加速为背景，理解计算粒度、数据流与可重构性之间的取舍</p> </blockquote> <p>两张架构图摆在一起时，粗粒度可重构阵列（Coarse-Grained Reconfigurable Array, CGRA）和脉动阵列（Systolic Array）很容易被看成同一种机器。</p> <table> <tr> <td width="50%" align="center" valign="middle"> <img src="/assets/img/posts/fpga-cgra-systolic-array-report/intro-cgra-architecture.png" alt="CGRA 架构：配置存储、局部存储与规则 PE 网格" width="100%"/> <br/><strong>(a) CGRA</strong> </td> <td width="50%" align="center" valign="middle"> <img src="/assets/img/posts/fpga-cgra-systolic-array-report/intro-systolic-array.webp" alt="脉动阵列架构：输入、权重和输出缓冲区包围规则 PE 网格" width="100%"/> <br/><strong>(b) Systolic Array</strong> </td> </tr> </table> <p><em>图 1：CGRA 与脉动阵列的外观对照。两者都有规则排列的处理单元（Processing Element, PE）、相邻节点之间的连线以及阵列外部的存储系统，也都可以加速卷积和矩阵乘法；真正的差异隐藏在 PE 功能、互连可配置性和数据传播方式之中。</em></p> <p>但相似的网格之下，隐藏着两套不同的执行逻辑。</p> <p>CGRA 关心的是：<strong>一个计算图能否被重新映射到不同的处理单元和通信路径上。</strong> 脉动阵列关心的是：<strong>数据能否按照预先设计的节拍和方向，连续穿过一组规则连接的处理单元。</strong> 前者把“可重构性”放在中心，后者把“规则的数据传播”推向极致。</p> <p>这一区别也提供了理解现场可编程门阵列（Field-Programmable Gate Array, FPGA）、CGRA 与 AI 专用加速器的入口。Jiawei Luo 在 2024 年发表的论文 <em>A comparative study of FPGA and CGRA technologies in hardware acceleration for deep learning</em>，正是从计算粒度和数据流出发，对 FPGA 与 CGRA 进行了综述式比较。论文认为，在它选取的案例中，FPGA 往往表现出更高的吞吐量，而 CGRA 在能效和面积上更有优势。<sup><a href="#ref-1">[1]</a></sup></p> <p>这个结论抓住了两类架构的典型取舍，却不能脱离论文的比较条件单独成立。要理解原因，需要先从深度学习加速器真正消耗时间与能量的地方说起。</p> <h2 id="深度学习加速器首先是一台数据搬运机器">深度学习加速器首先是一台数据搬运机器</h2> <p>卷积神经网络中的大量计算最终都会落到乘加操作上。每个处理单元接收输入激活 $a$ 和权重 $w$，将乘积累加到部分和 $p$：</p> \[p_{t+1}=p_t+a\times w\] <p>如果只看算式，设计加速器似乎只是不断增加乘法器和加法器。但在真实芯片中，计算单元必须先拿到正确的权重和激活，计算后的部分和还要被保存、传递或继续归约。数据可能来自 PE 内部的寄存器，也可能来自片上 SRAM，甚至来自片外 DRAM。距离越远，访问延迟和能耗通常越高。</p> <p>于是，硬件加速的核心问题从“能并行放下多少乘法器”变成了“怎样让数据少走路”。</p> <p>这也是 Luo 的论文先讨论 dataflow，再讨论 FPGA 和 CGRA 的原因。Dataflow 决定了计算在时间和空间中的安排方式：哪个数据留在本地，哪个数据沿阵列传播，部分和在哪里累积，以及一份数据能被多少个 PE 复用。</p> <h2 id="dataflow让最昂贵的数据少走几步">Dataflow：让最昂贵的数据少走几步</h2> <p>卷积加速器中常见的 Weight Stationary、Output Stationary 与 Row Stationary，并不是三种芯片，而是三种数据驻留策略。</p> <p><img src="/assets/img/posts/fpga-cgra-systolic-array-report/cnn-dataflow-ws-os-nlr-rs.png" alt="卷积计算中的四种数据流：权重驻留、输出驻留、无局部复用与行驻留" class="img-fluid"/></p> <p><em>图 2：四种卷积数据流中的数据移动。红色表示权重，蓝色表示输入激活，绿色虚线表示部分和。WS 与 OS 分别把权重和输出留在 PE 附近；NLR 几乎不利用 PE 内部复用；RS 则尝试同时挖掘多类数据的局部复用。图片来自 Luo 论文 Figure 1。<sup><a href="#ref-1">[1]</a></sup></em></p> <p>这张图值得关注的不是四组连线的形状，而是每种颜色跨越存储层次的次数。某类数据一旦能够在 PE 内停留或在相邻 PE 之间复用，就不必为每次乘加重新访问全局缓冲区；dataflow 的价值，正是用空间上的局部通信替代代价更高的远距离搬运。</p> <table> <thead> <tr> <th>数据流</th> <th>主要驻留对象</th> <th>数据组织方式</th> <th>主要收益</th> </tr> </thead> <tbody> <tr> <td>Weight Stationary（WS）</td> <td>权重</td> <td>权重留在 PE 附近，激活和部分和流动</td> <td>减少权重的重复读取</td> </tr> <tr> <td>Output Stationary（OS）</td> <td>输出部分和</td> <td>部分和留在本地，激活与权重不断到达</td> <td>减少中间结果的读写与传递</td> </tr> <tr> <td>Row Stationary（RS）</td> <td>行级相关数据</td> <td>在局部同时复用权重、激活与部分和</td> <td>综合降低多类数据移动</td> </tr> <tr> <td>No Local Reuse（NLR）</td> <td>不强调驻留</td> <td>数据频繁经过外部或共享存储</td> <td>减少 PE 内寄存器需求，但通信量较高</td> </tr> </tbody> </table> <p>这里的“Stationary”不是绝对静止，而是指一类数据在一段计算期间被保留在 PE 或邻近存储中，多次参与运算。</p> <p>更重要的是，dataflow 与硬件平台并不一一对应。FPGA 可以实现 WS、OS，也可以搭建脉动式数据通路；CGRA 可以在不同 kernel 之间改变数据流；专用 ASIC 同样可能支持多种驻留策略。硬件之间真正的差别，在于改变这些计算和通信关系时，需要付出多少资源、能量与编译成本。</p> <h2 id="fpga把电路本身变成可编辑对象">FPGA：把电路本身变成可编辑对象</h2> <p>FPGA 的基本资源包括查找表（LUT）、触发器、片上存储、DSP 单元和可编程互连。配置比特决定每个逻辑块实现什么布尔功能，也决定不同资源之间怎样连接。</p> <p>“细粒度可编程”描述的正是这种能力。设计者可以控制数据通路的位宽、流水线深度、存储分块、地址生成和控制逻辑，甚至能针对某种模型使用非标准数值格式。一个 8-bit 乘加器、一个特殊激活函数或一条完全定制的流式管线，都可以直接由底层资源组合出来。</p> <p>灵活性也带来明显成本。为了让任意逻辑和连线都能被重新配置，FPGA 必须保留大量配置 SRAM、多路选择器和通用路由资源。同一个字级乘加运算，在 FPGA 上往往需要穿过比专用电路更复杂的可编程结构。芯片面积和功耗中，有相当一部分用于“保持一切皆可改变”，而不是直接完成目标计算。</p> <p><img src="/assets/img/posts/fpga-cgra-systolic-array-report/fpga-cgra-reconfiguration-granularity.jpg" alt="FPGA 与 CGRA 的重构粒度对比：LUT 映射布尔逻辑，ALU 映射字级运算" class="img-fluid"/></p> <p><em>图 3：细粒度与粗粒度重构的概念对比。左侧 FPGA 将布尔函数分解并映射到 LUT；右侧 CGRA 将数据流图中的字级运算映射到已经具备算术功能的 ALU。图片引自 Ansaloni 的博士论文 Figure 1.1。<sup><a href="#ref-7">[7]</a></sup></em></p> <p>图中的差异可以概括为“被配置对象的粒度不同”：FPGA 的可编辑对象接近逻辑门和位级连线，CGRA 的可编辑对象则接近完整算子及其数据依赖。这不是说 FPGA 只能处理布尔逻辑，也不是说所有 CGRA 都使用 32-bit ALU；它强调的是，两者为获得灵活性所保留的硬件层级不同。</p> <p>Luo 的论文选取了三个 FPGA 案例：</p> <ul> <li><strong>nn-X</strong> 采用 ARM 主处理器与 FPGA 协处理器的组合，把固定权重缓存在片上，让激活在定制计算单元之间流动，体现了 WS 思路。论文表格报告其吞吐量为 227 GOPS，功耗为 8 W。</li> <li><strong>Memory-Centric Accelerator</strong> 把优化重点放在存储层次和复用缓冲区上，使用 tiling 与循环变换降低外部带宽需求。论文转述的结果是，相同 FPGA 资源下性能提高 11 倍，或在相同性能下将资源使用量降低到原来的约十三分之一。</li> <li><strong>Caffeine</strong> 使用 systolic-like PE 组织卷积和全连接层，通过 input-major 与 weight-major 映射增加数据复用。论文表格给出的吞吐量为 354 GOPS，功耗为 26 W。</li> </ul> <p>Caffeine 揭示了一条容易被混淆的边界：<strong>FPGA 和脉动阵列不是互斥选项。</strong> FPGA 描述的是底层硬件怎样被实现和配置，脉动阵列描述的是计算单元如何连接、数据如何传播。一块 FPGA 完全可以被配置成脉动阵列。</p> <h2 id="cgra把算子与通信路径变成可编辑对象">CGRA：把算子与通信路径变成可编辑对象</h2> <p>CGRA 同样具有可重构性，但它不再从布尔逻辑和位级布线开始。典型 CGRA 由一组处理单元（PE）、配置存储、可编程互连以及局部或全局存储组成。每个 PE 通常已经能够执行加法、乘法、MAC、比较或逻辑运算。</p> <p><img src="/assets/img/posts/fpga-cgra-systolic-array-report/cgra-array-and-processing-element.webp" alt="4×4 CGRA 阵列及单个处理单元的内部结构" class="img-fluid"/></p> <p><em>图 4：一个简化的 4×4 CGRA 及 PE 内部结构。阵列周围的数据缓冲区和上下文存储分别保存操作数与配置；PE 内的输入选择器、ALU 和寄存器共同决定“数据从哪里来、执行什么运算、结果到哪里去”。图片引自 Damsgaard、Ometov 与 Nurmi 的 Figure 1。<sup><a href="#ref-8">[8]</a></sup></em></p> <p>如果把 FPGA 比作一套可以自由搭建墙体、电路和管线的建筑材料，CGRA 更像一座已经放置好机器和通道的工厂。重新配置时，不必从逻辑门开始搭建乘法器，而是决定每台机器执行哪种运算，以及中间结果沿哪条通道抵达下一台机器。</p> <p>CGRA 的编译器会把程序中的数据流图映射到物理阵列。这个过程至少包含四个相互制约的问题：操作放在哪个 PE 上，操作在哪个周期执行，中间值经过哪条路由，以及输入和结果放在哪一级存储。空间资源不足时，同一个 PE 还可以在不同周期执行不同操作，形成时间复用。</p> <p><img src="/assets/img/posts/fpga-cgra-systolic-array-report/cgra-dfg-to-pe-array-mapping.png" alt="数据流图向 CGRA 处理单元阵列与多 Bank 局部存储的映射" class="img-fluid"/></p> <p><em>图 5：从程序数据流图到 CGRA 的空间映射。上方节点表示循环中的操作及依赖；下方把这些操作放置到 PE 阵列，并将数据安排到多 Bank 局部存储。深色节点对应 load/store 等访存操作，虚线表示它们与存储系统之间的关联。图片引自 Kim 等人的 CGRA 映射研究。<sup><a href="#ref-9">[9]</a></sup></em></p> <p>这幅图把“可重构”从抽象概念变成了一个编译问题：数据流图的节点变成某个 PE 在某个周期执行的操作，边变成阵列中的传输路径，而数组元素还要被分配到不会发生同时访问冲突的存储 Bank。图中的双缓冲让 DMA 可以在一组数据参与计算时搬运下一组数据，从而把外部访存与阵列执行重叠起来。映射质量因此不仅取决于 PE 是否够用，也取决于路由拥塞、存储 Bank 冲突和数据预取能否同时得到满足。</p> <p>这种字级或算子级重构省去了 FPGA 大量细粒度配置开销，因此 CGRA 通常被视为专用 ASIC 与 FPGA 之间的折中：它试图接近专用电路的性能和能效，同时保留软件可编程性。Podobas、Sano 与 Matsuoka 的 CGRA 综述也把“性能与可编程性之间的平衡”视为这一架构家族的核心特征。<sup><a href="#ref-2">[2]</a></sup></p> <p>Luo 的论文讨论了几种不同形态的粗粒度空间加速器：</p> <table> <thead> <tr> <th>设计</th> <th>主要结构</th> <th>数据流与可重构特征</th> <th>原论文强调的结果</th> </tr> </thead> <tbody> <tr> <td>NP-CGRA</td> <td>面向 MobileNet 的 MAC PE 与高带宽本地存储总线</td> <td>OS；分别适配深度卷积与逐点卷积</td> <td>DWC/PWC 的面积-时延积相对传统 CGRA 改善 8×/18×</td> </tr> <tr> <td>SDT-CGRA</td> <td>RC 计算矩阵与 SBU 流缓冲矩阵</td> <td>静态配置计算功能，动态调度数据流</td> <td>77.4 GOPS、1.526 W、50.78 GOPS/W</td> </tr> <tr> <td>MAERI</td> <td>可配置乘法开关、加法归约树和重构互连</td> <td>支持不同大小的虚拟神经元与多种 dataflow</td> <td>相对固定互连基线，PE 利用率提高 8%–459%<sup><a href="#ref-3">[3]</a></sup></td> </tr> <tr> <td>Eyeriss v2</td> <td>层次化 mesh NoC 与稀疏数据处理</td> <td>RS+；按层适配复用量和带宽需求</td> <td>原工作强调紧凑、稀疏模型上的资源利用率与能效<sup><a href="#ref-4">[4]</a></sup></td> </tr> </tbody> </table> <p>不过，这张表也暴露出 CGRA 分类的弹性。MAERI 和 Eyeriss v2 确实具备粗粒度 PE、空间映射和可配置通信，但许多文献会把它们称为 spatial DNN accelerator 或专用 ASIC，而不是一般意义上的 CGRA。原论文采用了较宽的定义，把“具有粗粒度可重构特征的空间加速器”都放入 CGRA 一侧。这个选择适合讨论架构趋势，却不是唯一的分类标准。</p> <h2 id="原论文的数字应该怎样读">原论文的数字应该怎样读</h2> <p>论文把不同设计的吞吐量、功耗、能效与面积汇总在同一张表中，并据此认为 FPGA 整体上拥有较高吞吐量，CGRA 则拥有更好的能效和面积表现。下面保留其中主要数据：</p> <table> <thead> <tr> <th>架构</th> <th>平台或工艺</th> <th style="text-align: right">吞吐量</th> <th style="text-align: right">功耗</th> <th style="text-align: right">论文列出的能效</th> </tr> </thead> <tbody> <tr> <td>nn-X</td> <td>Xilinx ZC706</td> <td style="text-align: right">227 GOPS</td> <td style="text-align: right">8 W</td> <td style="text-align: right">25 GOPS/W</td> </tr> <tr> <td>Memory-Centric</td> <td>Virtex-6 ML605</td> <td style="text-align: right">17 GOPS</td> <td style="text-align: right">N/A</td> <td style="text-align: right">N/A</td> </tr> <tr> <td>Caffeine</td> <td>Virtex-7 690T</td> <td style="text-align: right">354 GOPS</td> <td style="text-align: right">26 W</td> <td style="text-align: right">13.6 GOPS/W</td> </tr> <tr> <td>Angel-Eye</td> <td>Zynq XC7Z045</td> <td style="text-align: right">137 GOPS</td> <td style="text-align: right">9.63 W</td> <td style="text-align: right">14.2 GOPS/W</td> </tr> <tr> <td>FP-DNN</td> <td>Stratix-V</td> <td style="text-align: right">364.4 GOPS</td> <td style="text-align: right">25 W</td> <td style="text-align: right">14.57 GOPS/W</td> </tr> <tr> <td>NP-CGRA</td> <td>TSMC 28 nm</td> <td style="text-align: right">64 GOPS</td> <td style="text-align: right">N/A</td> <td style="text-align: right">N/A</td> </tr> <tr> <td>SDT-CGRA</td> <td>SMIC 55 nm</td> <td style="text-align: right">77.4 GOPS</td> <td style="text-align: right">1.526 W</td> <td style="text-align: right">50.78 GOPS/W</td> </tr> <tr> <td>MAERI</td> <td>TSMC 28 nm</td> <td style="text-align: right">N/A</td> <td style="text-align: right">0.3 W</td> <td style="text-align: right">N/A</td> </tr> <tr> <td>Eyeriss v2</td> <td>TSMC 65 nm</td> <td style="text-align: right">153.6 GOPS</td> <td style="text-align: right">1.65 W</td> <td style="text-align: right">253.2 GOPS/W</td> </tr> <tr> <td>DNPU</td> <td>65 nm CMOS</td> <td style="text-align: right">1.2 TOPS</td> <td style="text-align: right">0.279 W</td> <td style="text-align: right">3.9 TOPS/W</td> </tr> <tr> <td>ISSCC19-7.4</td> <td>65 nm CMOS</td> <td style="text-align: right">206 GOPS</td> <td style="text-align: right">0.0024–0.196 W</td> <td style="text-align: right">2.16 TOPS/W</td> </tr> </tbody> </table> <p>这组数字适合观察“样本中的架构倾向”，不适合形成跨平台排名。表中的 FPGA 开发板和 28/55/65 nm ASIC 来自不同年份，采用不同的模型、数值精度、稀疏策略、batch size 和测量范围。即使都使用 GOPS，一次 MAC 究竟计为一次还是两次操作，也可能没有统一。</p> <p>面积结论尤其需要谨慎。论文表中的五个 FPGA 案例都没有给出平方毫米面积，CGRA 一侧却使用实际芯片面积。由此可以说明部分 CGRA/ASIC 实现很紧凑，却无法仅凭这张表完成 FPGA 与 CGRA 的面积对照。</p> <p>表内还有几处数值无法直接相互推导。Eyeriss v2 一行给出的 153.6 GOPS 除以 1.65 W，约为 93.1 GOPS/W，与能效列的 253.2 GOPS/W 不一致；nn-X 的 227 GOPS 除以 8 W 约为 28.4 GOPS/W，而不是 25；DNPU 的两列相除约为 4.30 TOPS/W，与表中的 3.9 TOPS/W 也存在差异。它们可能来自不同运行点、精度或稀疏口径，也可能是转录问题，但论文没有提供足够说明。</p> <p>因此，原论文的结论更适合改写成下面这句话：</p> <blockquote> <p>在所选案例中，细粒度重构展现了高度定制并行数据通路的能力；粗粒度或专用空间加速器则通过更直接的算术单元和互连设计，表现出较高能效潜力。</p> </blockquote> <p>这是一种设计空间判断，而不是一条“FPGA 必然更快、CGRA 必然更省电”的定律。表中吞吐量达到 1.2 TOPS 的 DNPU，本身就是对简单概括的提醒。</p> <h2 id="两张相似的网格语义完全不同">两张相似的网格，语义完全不同</h2> <p>理解完 FPGA 与 CGRA，再回看脉动阵列，就能发现“长得像”并不等于“执行方式相同”。</p> <p><img src="/assets/img/posts/fpga-cgra-systolic-array-report/systolic_array.png" alt="权重驻留脉动阵列：激活横向传播，部分和纵向累加" class="img-fluid"/></p> <p><em>图 6：一种权重驻留脉动阵列。权重预加载到 PE，输入激活向右传播，部分和向下传播。</em></p> <p>图 4 中的箭头首先表示<strong>可选的数据路径</strong>：配置决定 PE 执行何种操作，也决定数据可以从哪个邻居到达、又发往哪里。图 6 中的箭头则表示<strong>计算协议本身</strong>：激活每拍向右移动，部分和每拍向下移动，每个 PE 用本地权重完成一次乘加。</p> <p>二者的共同点来自空间计算范式。它们都把计算展开到物理空间，让中间结果直接在相邻 PE 之间传递，从而避开中央寄存器文件或频繁的远端存储访问。差异在于，CGRA 为改变计算图和路由保留了配置能力，脉动阵列则通过规则化传播减少控制和通信开销。</p> <table> <thead> <tr> <th>维度</th> <th>典型 CGRA</th> <th>典型脉动阵列</th> </tr> </thead> <tbody> <tr> <td>设计目标</td> <td>在效率与可重构性之间平衡</td> <td>让规则依赖计算持续、高密度地推进</td> </tr> <tr> <td>PE 功能</td> <td>多功能 ALU/MAC，可包含寄存器和谓词支持</td> <td>高度同构，常以 MAC 或简单算子为主</td> </tr> <tr> <td>互连</td> <td>可编程，可支持多方向、多跳、广播或归约</td> <td>多为固定邻接连接和规则传播方向</td> </tr> <tr> <td>控制</td> <td>配置上下文与静态时空调度，部分设计支持动态机制</td> <td>全局节拍下规则推进，控制隐含在数据到达时序中</td> </tr> <tr> <td>映射问题</td> <td>数据流图的放置、调度、路由与存储映射</td> <td>规则循环依赖到空间坐标和时间拍的投影</td> </tr> <tr> <td>适合负载</td> <td>多种 DSP/DNN kernel、需要切换映射的循环</td> <td>GEMM、卷积与规则 stencil 等仿射依赖计算</td> </tr> <tr> <td>主要代价</td> <td>配置存储、灵活互连和复杂编译器</td> <td>非规则形状、分支或动态稀疏下的低利用率</td> </tr> </tbody> </table> <p>这张对照表描述的是典型倾向，不是定义清单。CGRA 不一定采用图 4 的双向最近邻网络，也不一定逐周期动态重构；脉动阵列不一定采用图 6 的权重驻留，也不一定由 ASIC 实现。把一张示意图中的属性扩大成整个架构类别的必要条件，会让比较失真。</p> <h2 id="脉动不是一种芯片材质而是一种执行秩序">脉动不是一种芯片材质，而是一种执行秩序</h2> <p>对于矩阵乘法 $C=A\times B$，每个输出元素为：</p> \[C_{ij}=\sum_k A_{ik}B_{kj}\] <p>在一种经典二维脉动映射中，$A$ 的元素沿行传播，$B$ 的元素沿列传播。输入经过适当的时间错位后，$A_{ik}$ 和 $B_{kj}$ 会在第 $k$ 个相关节拍同时抵达 PE$(i,j)$，完成一次乘加，然后继续向邻居移动。</p> <p>阵列填满后，每个周期都可能有大量 PE 同时进行有效计算。没有复杂的全局寻址，也不需要每个 PE 独立获取和解码指令。这种规则性使脉动阵列特别适合密集矩阵乘法。Google 第一代数据中心 TPU 的核心矩阵乘单元包含 65,536 个 8-bit MAC，正是专用矩阵计算组织的代表。<sup><a href="#ref-5">[5]</a></sup></p> <p>规则性也会形成边界。阵列启动和排空需要额外周期，矩阵尺寸无法整除阵列维度时需要 padding，小矩阵或极端长宽比会留下空闲 PE。面对动态稀疏、条件分支和不规则访存时，峰值 TOPS 更难转化为实际吞吐。</p> <p>这说明脉动阵列不是 CGRA 的严格子类，也不能被简单理解成“功能更少的 CGRA”。更准确的关系是：</p> <ul> <li>CGRA 是一种以粗粒度 PE 和可重构映射为核心的架构类别；</li> <li>脉动阵列是一种规则的时空执行与通信组织；</li> <li>CGRA 可以配置出脉动式数据流，但它的配置空间远大于这一种模式；</li> <li>FPGA 或 ASIC 也可以成为脉动阵列的实现载体。</li> </ul> <p>换句话说，<strong>CGRA 描述“机器允许改变什么”，脉动阵列描述“计算按什么秩序发生”。</strong></p> <h2 id="从刚性阵列到可重构数据流">从刚性阵列到可重构数据流</h2> <p>真实工作负载很少永远保持同一种形状。即使一个神经网络主要由卷积和矩阵乘组成，不同层的通道数、特征图大小、复用机会和稀疏率也可能相差很大。固定 dataflow 在某些层上高效，在另一些层上却会因带宽不足或 PE 空闲而失去优势。</p> <p>这推动了专用阵列和 CGRA 在设计上的靠近。</p> <p>MAERI 通过可配置的分发与归约网络，让同一组乘法器支持不同大小的虚拟神经元和多种数据流。Eyeriss v2 的层次化 mesh 则根据层形状调整带宽和数据复用，并直接处理压缩的稀疏权重与激活。它们未必符合所有人对 CGRA 的严格定义，却共享同一个方向：保留空间计算的局部通信优势，同时降低固定数据流面对多样化模型时的利用率损失。<sup><a href="#ref-3">[3]</a></sup><sup><a href="#ref-4">[4]</a></sup></p> <p>编译器也在利用两类架构的交集。HiMap 在应用循环与物理 CGRA 之间引入“虚拟脉动阵列”作为中间抽象，先提取规则的迭代依赖，再把少量重复模式映射到 CGRA 子区域。论文报告称，这种层次化方法能在大型阵列上显著降低编译时间，并改善映射性能与能效。<sup><a href="#ref-6">[6]</a></sup></p> <p>这个例子很有代表性：脉动结构不仅是一种硬件实现，也可以成为理解和编译规则计算的数学工具。CGRA 则提供了更宽的物理底座，使同一套硬件有机会在规则计算与其他数据流之间切换。</p> <h2 id="规则性灵活性与效率之间没有免费午餐">规则性、灵活性与效率之间没有免费午餐</h2> <p>把 FPGA、CGRA 与脉动阵列放在同一张设计图上，可以看到一条连续光谱。</p> <p><img src="/assets/img/posts/fpga-cgra-systolic-array-report/architecture-design-space-efficiency-flexibility-performance.jpg" alt="ASIC、CGRA、FPGA、GPU、DSP 与 CPU 在能效、灵活性和性能维度上的概念位置" class="img-fluid"/></p> <p><em>图 7：不同计算架构在能效、可编程灵活性与性能维度上的定性位置。本文讨论的专用脉动阵列通常以 ASIC 实现，因此可以落在图中的 ASIC 区域；CGRA 与 FPGA 则分别代表粗粒度和细粒度可重构计算。椭圆的位置和范围仅表达典型趋势，不是统一工作负载、工艺和精度下的基准测试结果。图片为知乎转载版本，原始制图来源与数据口径未能确认。</em></p> <p>这张示意图提供了一个直观的设计空间视角：通用处理器依靠软件和指令集获得较高灵活性，专用 ASIC 则通过固定更多结构追求性能与能效；FPGA 和 CGRA 位于两者之间，而 CGRA 通常希望用字级算术单元换取比 FPGA 更低的配置和互连开销。相关 CGRA 综述也将“接近硬件的性能与能效，同时保留软件可编程性”概括为这类架构的核心目标。<sup><a href="#ref-10">[10]</a></sup></p> <p>FPGA 把位级逻辑和布线都开放给设计者，能表达最特殊的数据路径，却为这种自由承担最高的配置与路由成本。CGRA 预先定义字级算术单元，只开放操作、连接和时序映射，在效率与通用性之间取中间位置。专用脉动阵列进一步固定 PE 和数据传播规则，用更窄的适用范围换取更高计算密度、更简单的控制和更可预测的执行。</p> <blockquote> <p><strong>更高灵活性</strong>　←　FPGA（位级逻辑与布线可编程）　→　CGRA（算子与互连可重构）　→　专用脉动阵列（规则 PE 与数据传播）　→　<strong>更高专用效率与可预测性</strong></p> </blockquote> <p>这条光谱不是硬件排行榜。算法是否规则、张量形状是否稳定、是否需要特殊位宽、外部带宽是否充足、编译器能否找到高质量映射，都会改变最终答案。更现实的系统通常也不是三选一，而是让脉动或向量单元承担密集线性代数，让标量核处理控制与非线性操作，再用可配置互连、局部存储和 DMA 把不同计算区域组织起来。</p> <p>因此，评价一台 AI 加速器不能只看阵列，也不能只看峰值 TOPS。计算、存储、互连、数值格式、编译器和实际模型共同决定了芯片最终能兑现多少理论性能。</p> <h2 id="结语真正的分界在于固定什么">结语：真正的分界在于“固定什么”</h2> <p>Luo 的论文提供了一个有用的入口：FPGA 的细粒度可编程性扩大了定制空间，CGRA 的粗粒度 PE 和互连减少了实现算术与通信的冗余。在论文收集的案例中，前者表现出较高吞吐潜力，后者表现出较好的能效倾向。</p> <p>它的定量比较仍有明显限制。不同工艺、精度、模型和测量口径不能组成严格的横向基准，宽口径的 CGRA 分类也会影响结论。但这些问题并不会削弱文章最有价值的启示：硬件加速器的差异，最终来自设计者选择把哪些结构固定下来，又把哪些自由度留给配置和软件。</p> <p>CGRA 与脉动阵列之所以相似，是因为它们都属于空间计算；它们之所以不同，是因为前者保留重新安排计算和路径的能力，后者依靠严格的传播秩序消除控制开销。</p> <p>网格只是表象。真正定义一台机器的，是数据在网格中遵循的规则。</p> <h2 id="参考资料">参考资料</h2> <p><span id="ref-1"></span><strong>[1]</strong> J. Luo, “A comparative study of FPGA and CGRA technologies in hardware acceleration for deep learning,” <em>Applied and Computational Engineering</em>, vol. 51, pp. 168–180, 2024. <a href="https://doi.org/10.54254/2755-2721/51/20241212">DOI: 10.54254/2755-2721/51/20241212</a></p> <p><span id="ref-2"></span><strong>[2]</strong> A. Podobas, K. Sano, and S. Matsuoka, “A Survey on Coarse-Grained Reconfigurable Architectures From a Performance Perspective,” <em>IEEE Access</em>, 2020. <a href="https://doi.org/10.1109/ACCESS.2020.3012084">DOI: 10.1109/ACCESS.2020.3012084</a>, <a href="https://arxiv.org/abs/2004.04509">arXiv:2004.04509</a></p> <p><span id="ref-3"></span><strong>[3]</strong> H. Kwon, A. Samajdar, and T. Krishna, “MAERI: Enabling Flexible Dataflow Mapping over DNN Accelerators via Reconfigurable Interconnects,” <em>ASPLOS</em>, 2018. <a href="https://doi.org/10.1145/3173162.3173176">DOI: 10.1145/3173162.3173176</a></p> <p><span id="ref-4"></span><strong>[4]</strong> Y.-H. Chen, T.-J. Yang, J. Emer, and V. Sze, “Eyeriss v2: A Flexible Accelerator for Emerging Deep Neural Networks on Mobile Devices,” <em>IEEE JETCAS</em>, 2019. <a href="https://eyeriss.mit.edu/">Eyeriss 项目页</a>, <a href="https://arxiv.org/abs/1807.07928">arXiv:1807.07928</a></p> <p><span id="ref-5"></span><strong>[5]</strong> N. P. Jouppi et al., “In-Datacenter Performance Analysis of a Tensor Processing Unit,” <em>ISCA</em>, 2017. <a href="https://research.google/pubs/in-datacenter-performance-analysis-of-a-tensor-processing-unit/">Google Research</a></p> <p><span id="ref-6"></span><strong>[6]</strong> D. Wijerathne, Z. Li, A. Pathania, T. Mitra, and L. Thiele, “HiMap: Fast and Scalable High-Quality Mapping on CGRA via Hierarchical Abstraction,” <em>IEEE TCAD</em>, 2021. <a href="https://staff.fnwi.uva.nl/a.pathania/publication/tcad-21a/">论文信息与作者页面</a></p> <p><span id="ref-7"></span><strong>[7]</strong> G. Ansaloni, <em>Architectural Exploration and Scheduling Methods for Coarse Grained Reconfigurable Arrays</em>, doctoral thesis, Università della Svizzera italiana, 2011. <a href="https://sonar.ch/global/documents/318222">机构知识库记录</a></p> <p><span id="ref-8"></span><strong>[8]</strong> H. J. Damsgaard, A. Ometov, and J. Nurmi, “Generating CGRA Processing Element Hardware with CGRAgen,” <em>26th Euromicro Conference on Digital System Design</em>, 2023. <a href="https://doi.org/10.1109/DSD60849.2023.00011">DOI: 10.1109/DSD60849.2023.00011</a>, <a href="https://trepo.tuni.fi/handle/10024/208833">机构知识库记录</a></p> <p><span id="ref-9"></span><strong>[9]</strong> Y. Kim, J. Lee, A. Shrivastava, and Y. Paek, “Operation and Data Mapping for CGRAs with Multi-bank Memory,” <em>ACM SIGPLAN Notices</em>, vol. 45, no. 4, pp. 17–25, 2010. <a href="https://doi.org/10.1145/1755951.1755892">DOI: 10.1145/1755951.1755892</a></p> <p><span id="ref-10"></span><strong>[10]</strong> L. Liu, J. Zhu, Z. Li, Y. Lu, Y. Deng, J. Han, S. Yin, and S. Wei, “A Survey of Coarse-Grained Reconfigurable Architecture and Design: Taxonomy, Challenges, and Applications,” <em>ACM Computing Surveys</em>, vol. 52, no. 6, Article 118, 2019. <a href="https://doi.org/10.1145/3357375">DOI: 10.1145/3357375</a></p>]]></content><author><name></name></author><category term="AI"/><category term="FPGA"/><category term="CGRA"/><category term="Systolic Array"/><category term="AI Accelerator"/><category term="Computer Architecture"/><summary type="html"><![CDATA[以深度学习硬件加速为背景，理解计算粒度、数据流与可重构性之间的取舍。]]></summary></entry><entry><title type="html">Transformer位置编码(3)——从RoPE到YaRN外推</title><link href="https://samsz04.github.io/2025/11/11/Transformer3/" rel="alternate" type="text/html" title="Transformer位置编码(3)——从RoPE到YaRN外推"/><published>2025-11-11T10:57:35+08:00</published><updated>2025-11-11T10:57:35+08:00</updated><id>https://samsz04.github.io/2025/11/11/Transformer3</id><content type="html" xml:base="https://samsz04.github.io/2025/11/11/Transformer3/"><![CDATA[<h2 id="第一部分问题的根源rope-的上下文天花板">第一部分：问题的根源——RoPE 的“上下文天花板”</h2> <h3 id="11-引言">1.1 引言</h3> <blockquote> <p>建议先去阅读一下这篇大佬的文章：<a href="https://www.cnblogs.com/rossiXYZ/p/18808744">探秘Transformer系列之（23）— 长度外推 - 罗西的思考 - 博客园</a>，里面讲解的很清晰！本篇意在用更少的篇幅尝试讲清楚<strong>YaRN</strong>这一解决方案！</p> </blockquote> <p>大型语言模型 (LLM) 的能力在很大程度上与其能够处理的上下文窗口大小相关。扩展上下文窗口对于解锁更复杂的应用至关重要，例如处理长文档摘要、执行“大海捞针”式的知识库问答 (RAG)，或在大型代码库中进行辅助编程 。然而，大多数开源的 LLM（例如 Llama 2 系列）在设计上都受限于其预训练阶段设定的上下文窗口（例如 4096 个 token），这构成了它们能力的“天花板”。</p> <p><img src="/assets/img/posts/Transformer3/image1.jpg" alt="" class="img-fluid"/></p> <h3 id="12-rope-回顾可参考笔者上期内容transformer位置编码2rope">1.2 RoPE 回顾（可参考笔者上期内容：<a href="https://samsz04.github.io/2025/11/04/Transformer-position-embedding2/">Transformer位置编码(2)——RoPE</a>）</h3> <p>为了理解 YaRN，必须首先回顾它所要改进的基础：旋转位置编码 (RoPE) 。</p> <p>RoPE 的核心思想是，注意力分数应该只取决于 token 之间的相对距离 。它通过对查询 $q$ 和键 $k$ 向量应用一个与绝对位置 $m$ 相关的旋转矩阵 $R_m$ 来实现这一点 。</p> <p>给定位置 $ m $ 处的 $ q $ 向量和位置 $ n $ 处的 $ k $ 向量，它们的位置编码版本 $ q<em>m $ 和 $ k_n $ 之间的内积 $ q_m^T k_n $ 最终只依赖于相对位置 $ (m-n) $ 。这种旋转是通过复数乘法或等效的 2x2 旋转矩阵实现的，其旋转角度 $ \theta</em>{m,d} $ 由绝对位置 $ m $ 和维度索引 $ d $ 共同决定：</p> \[\theta_{m,d} = m \cdot \theta_d = m \cdot b^{-2d/D}\] <p>其中 $ b $ 是一个固定的基数（例如 10000），$ D $ 是特征维度。</p> <p><img src="/assets/img/posts/Transformer3/image2.jpg" alt="" class="img-fluid"/></p> <h3 id="13-解构-rope-的外推失败-extrapolation-failure">1.3 解构 RoPE 的“外推失败” (Extrapolation Failure)</h3> <p>RoPE 的优雅设计在预训练窗口（例如 $ L=4096 $）内表现出色，但一旦序列长度 $ m $ 超过 $ L $，模型的性能（以困惑度 PPL 为衡量标准）会立即出现“悬崖式下跌” (cliff-like drop)。</p> <p>这种失败的根源在于其位置编码方法的“有限外推能力”。这被视为一个“预测阶段的分布外 (Out-Of-Distribution, OOD) 问题”。研究发现，即使使用了 RoPE 这样的相对编码，Transformer 模型仍然会“过拟合” (overfit) 它们在训练期间看到的特定位置嵌入。此外，训练动态也加剧了这一问题：处于序列后部（rear positions）的位置嵌入在训练中被更新的频率远低于前部位置，导致它们在更长上下文中的泛化能力很差。</p> <p><img src="/assets/img/posts/Transformer3/image3.webp" alt="" class="img-fluid"/></p> <h3 id="14-深度洞察为什么相对的-rope-会绝对地失败">1.4 深度洞察：为什么“相对”的 RoPE 会“绝对”地失败？</h3> <p>RoPE 的失败常常被误解。尽管其<em>目标</em>是相对的，但其<em>实现</em>是绝对的（依赖于绝对位置 $ m $）。失败的核心原因在于<strong>低频维度在外推时产生了 OOD 旋转角</strong>。</p> <p>这个失败过程可以分解如下：</p> <ol> <li><strong>频率差异：</strong> RoPE 的不同维度 $ d $ 具有不同的旋转“速度” $\theta_d$。</li> <li><strong>高频维度 (High-frequency, $ d $ 较小)：</strong> $ \theta<em>d $ 很大，旋转很快。在训练窗口内，这些维度可能已经旋转了数十甚至上百圈（即 $ \theta</em>{m,d} \gg 2\pi $）。当 $ m &gt; 4095 $ 时，例如 $ m=4097 $，其角度只是“再多转一点”，模型在训练中已经见过无数次相似的角度值（例如 $ \theta_{m,d} \mod 2\pi $），因此可以很好地处理外推。</li> <li><strong>低频维度 (Low-frequency, $ d $ 较大)：</strong> $ \theta_d $ 极小，旋转极慢。</li> <li><strong>失败点：</strong> 对于某些用于编码长距离关系的低频维度，其在 $ m=4095 $ 时的总旋转角度可能仍小于 $ 2\pi $ 。当模型在推理时遇到 $ m = 8000 $ 的 token 时，这个维度的旋转角<strong>首次</strong>超过了 $ 2\pi $。</li> <li><strong>OOD 灾难：</strong> 模型在预训练期间从未见过该维度产生大于 $ 2\pi $ 的旋转角。它无法将这个 OOD 信号解释为有效的位置信息。这导致了不稳定的注意力分数，进而导致注意力机制的崩溃，特别是在评估长距离依赖关系时。</li> </ol> <p>因此，所有上下文扩展技术的核心挑战是：如何处理这些在 $ m &gt; L $ 时“失控”的低频维度。</p> <h2 id="第二部分上下文扩展的演进之路-the-lineage">第二部分：上下文扩展的演进之路 (The Lineage)</h2> <p>首先，参考<a href="https://zhuanlan.zhihu.com/p/15311461897">从ROPE到Yarn, 一条通用公式速通长文本大模型中的位置编码</a>和论文<a href="https://arxiv.org/abs/2309.00071">YaRN: Efficient Context Window Extension of Large Language Models</a>中的内容，Yarn的作者认为编码函数是一个关于输入向量x、位置m 和θ 的函数，无论是ROPE还是它的所有变种，本质上都可以被以下公式所统一：</p> \[f'_W(x_m, m, \theta_d) = f_W(x_m, g(m), h(\theta_d))\] <p>其中：</p> <ul> <li>$ f′ $ 是调整后的查询（query）和键（key）向量。</li> <li>$ f $ 是原始的查询和键向量计算函数。</li> <li>$ x_m $ 是输入序列中位置m的嵌入向量。</li> <li>$ m $ 是序列中的位置索引。</li> <li>$ θ_d $ 是RoPE中的旋转角度参数，即频率参数。</li> <li>$ g(m) $ 是一个可调函数，用于根据比例因子$ s $调整位置索引$ m $，描述位置的变换逻辑。</li> <li>$ h(θ_d) $是一个可调函数，用于根据比例因子$ s $调整RoPE的旋转角度参数 $ θ_d $ ，描述频率的变换逻辑。</li> </ul> <h3 id="21-解决方案一位置插值-pi挤压策略">2.1 解决方案一：位置插值 (PI)——“挤压”策略</h3> <p>第一个被广泛采用的解决方案是位置插值 (Position Interpolation, PI)。</p> <ul> <li> <p><strong>核心思想：</strong> PI 的思想非常简单：不要进行外推 (Extrapolation)，转而进行内插 (Interpolation)。</p> </li> <li> <p><strong>机理：</strong> 它将需要处理的更长序列 $ L’ $（例如 32k）的 <em>位置索引</em> $ m’ $（范围 $ [0, L’-1] $）<strong><em>线性缩放</em></strong>（或称“挤压”）到模型预训练的原始范围 $ L $（例如 4k）之内（范围 $ [0, L-1] $）。</p> </li> <li> <p><strong>数学公式：</strong> 定义缩放因子 $ s = L’ / L $。PI 修改了 RoPE 的位置函数 $ g(m) $：</p> \[g(m) = m / s\] \[h(\theta_d) = \theta_d\] <p>原始的旋转角度 $ \theta<em>{m,d} = m \cdot \theta_d $ 被替换为 $ \theta</em>{m,d}’ = (m/s) \cdot \theta_d $。</p> <p><img src="/assets/img/posts/Transformer3/image4.jpg" alt=""/></p> </li> <li> <p><strong>应用：</strong> LLaMA-2-7B-32K 和 Meta 自己的 Llama 2 Long 都采用了 PI 作为其上下文扩展策略。</p> </li> <li> <p><strong>优势：</strong> PI 完美地解决了 OOD 问题。通过 PI，模型<em>永远</em>不会遇到超出其训练范围 $ [0, L-1] $ 的位置索引。此外，它非常高效：仅需少量微调（例如 1000 步）即可将 LLaMA 的上下文从 4k 扩展到 32k ，这远比从头预训练高效得多。</p> </li> </ul> <h3 id="22-pi-的代价高频信息的损失">2.2 PI 的代价：高频信息的损失</h3> <p>然而，PI 并非没有代价。它的主要缺陷在于它<em>统一</em>缩放了所有维度。PI 牺牲了位置的“分辨率”来换取“范围”。</p> <p><img src="/assets/img/posts/Transformer3/image5.jpg" alt="" class="img-fluid"/></p> <p>这个代价的产生过程如下：</p> <ol> <li>PI 将 $ m $ 替换为 $ m/s $。</li> <li>考虑两个相邻的 token（例如位置 $ m $ 和 $ m+1 $）。在 PI 处理后，它们在位置空间中的“有效距离”从 $ 1 $ 变成了 $ (m+1)/s - m/s = 1/s $。</li> <li>当 $ s $ 很大时（例如 $ s=16 $，即 4k -&gt; 64k），这个有效距离 $ 1/s $ 变得非常小。</li> <li>RoPE 的高频维度（High-frequency dimensions）存在的意义恰恰是区分<em>近距离</em> token 的相对顺序。</li> <li>当 PI 将它们的有效距离压缩到 $ 1/s $ 时，这些高频维度产生的旋转角度差异也变得微乎其微，导致模型难以区分它们的顺序。</li> <li>这就是“高频信息损失” (loss of high frequency) 或“近距离 token 混淆” (confusion about positional order of close-by tokens) 的根本原因。</li> <li><strong>后果：</strong> 经过 PI 微调的模型，虽然获得了长上下文能力，但在<em>短</em>上下文任务上的表现却会下降。</li> </ol> <p><img src="/assets/img/posts/Transformer3/image6.jpg" alt="" class="img-fluid"/></p> <h3 id="23-解决方案二ntk-aware-缩放非线性修复">2.3 解决方案二：”NTK-aware” 缩放——“非线性”修复</h3> <p>“NTK-aware” 缩放的提出正是为了解决 PI 丢失高频信息的问题。该方法受到了神经切线核 (Neural Tangent Kernel, NTK) 理论的启发，NTK 理论表明高频分量对于深度神经网络的学习至关重要。</p> <p><img src="/assets/img/posts/Transformer3/image7.jpg" alt="" class="img-fluid"/></p> <ul> <li> <p><strong>核心思想：</strong> 与其缩放位置 $ m $，不如缩放 RoPE 的<em>基频 (base)</em> $ b $ 。</p> </li> <li> <p><strong>机理：</strong> 这种缩放是<em>非线性</em>的。它旨在“分散插值压力”：对低频维度进行大幅度缩放（类似于 PI），但对高频维度<em>只进行轻微</em>缩放，从而保留它们。</p> </li> <li> <p><strong>数学公式：</strong></p> \[g(m) = m\] \[h(\theta_d) = b'^{-2d/D} \quad (\text{即修改 } \theta_d)\] \[\text{其中新基数 } b' = b \cdot s^{\frac{|D|}{|D| - 2}}\] </li> <li> <p><strong>优势：</strong> 在<em>不进行任何微调</em>的情况下（这种用法被称为 “Dynamic NTK”），”NTK-aware” 缩放在长序列上的 PPL 表现优于 PI。它成功地保留了高频信息。</p> </li> <li> <p><strong>拟合曲线：</strong> NTK-aware Interpolation方法其实是将外推的程度定义成一个与组别 $ d $ 有关的函数 $ γ(d) $ 。</p> <ul> <li>$ d = 0 $ 为最高频分量，我们希望完全外推，此时 $ γ(d)= 1.0 $ 。</li> <li>$ d = D/2 -1 $ 为最低频分量，我们希望完全内插，此时 $ γ(d) = L/L’ $ 。</li> </ul> <p>这个函数可以用一条以分组 $ d $ 为变量的经过点$ (0,1) $与点$ (𝐷/2−1,L/L′) $的单调递减的曲线。具体曲线形式有多种，论文中使用指数函数来拟合这条曲线，得到$ γ(d)=s^\frac{-2d}{D - 2}，s = L’/L $。</p> </li> </ul> <p>我们也可以从<strong>时钟</strong>的角度来理解。RoPE 的行为就像一个时钟，每一个 $ \theta $ 值就控制着一块圆盘的转动速度，一共有 $ d/2 $ 个圆盘。</p> <p><img src="/assets/img/posts/Transformer3/image8.jpg" alt="" class="img-fluid"/></p> <p>我们假设前三个转盘是秒针，分针和时针。12小时时钟基本上是一个维度为 3、底数为 60 的 RoPE。秒针，分针和时针是不同的频率在旋转。（频率从高到低）每秒钟，分针转动 1/60 分钟，每分钟，时针转动 1/60。现在RoPE时钟一天最大能表达：60 _ 60 _ 12=43200s。如果希望时钟表达的时间变长，假如想表达4天，则需要将时钟减慢4倍，那么有如下两种方法：</p> <ul> <li>PI：将每秒，分钟，时钟的频率平等的缩小4倍（周期变长），可以实现这个目标。不幸的是，现在很难区分每一秒，因为现在秒针几乎每秒都不会移动。因此，如果有人给你两个不同的时间，仅相差一秒，你将无法从远处区分它们。</li> <li>NTK-Aware RoPE：我们应该对频率高的秒钟，不做缩放，而会将分钟减慢 1.5 倍，将小时减慢 2 倍，即可以在一小时内容纳 90 分钟，在半天内容纳 24 小时。现在时钟可以表达：60 _ (60 _ 1.5)_(2 _ 12)=129600.0。我们只关注整体的时间：那么不需要精确测量时针，所以与秒相比，将小时缩放得更多是至关重要的。我们不想失去秒针的精度，但我们可以承受分针甚至时针的精度损失。</li> </ul> <h3 id="24-ntk-aware-的新困境微调失败">2.4 “NTK-aware” 的新困境：微调失败</h3> <p>“NTK-aware” 似乎是一个更好的解决方案，但它在实践中暴露了一个致命缺陷：尽管它在零调优（zero-shot）长下文上表现不错，但<em>在微调后</em>的性能却<em>劣于</em> PI 。</p> <p>其失败的深层原因在于 “NTK-aware” <em>不是</em>一个纯粹的“插值”方案：</p> <ol> <li>PI 保证了所有 $ m/s $ 都在 $ [0, L-1] $ 的<em>分布内</em> (in-distribution)。这为微调提供了一个稳定（尽管分辨率低）的目标。</li> <li>“NTK-aware” 通过改变基频 $ b $ 来<em>扭曲</em>整个频率空间。</li> <li>这种扭曲虽然保留了高频，但也导致<em>某些</em>维度的旋转角度被<em>外推</em>到了“越界” (out-of-bound) 值。即实际上，在RoPE的训练过程中存在一些足够低频的分量，这些低频分量对应的波长 $ λ_d $ 长到即使是训练过程中最长的序列，也没有办法让这些分量经过一个完整周期。对于这些分量，我们显然不应该对他们进行任何的外推。否则可能会引入一些从未见过的旋转角度，这些旋转角度对应的正余弦值在训练过程中模型也从未见过，会导致模型的效果下降。</li> <li>因此，模型在微调时，面对的是一个<em>不稳定</em>的位置编码目标（部分维度在分布内，部分维度在分布外）。这比 PI 提供的<em>完全在分布内</em>的模糊目标更难学习。</li> </ol> <p>此时，研究人员面临一个挑战：如何设计一种方法，既能像 “NTK-aware” 一样<strong>保留高频信息</strong>，又能像 PI 一样<strong>保证所有维度都在分布内</strong>（纯插值），以便于稳定微调？</p> <p>这就是 YaRN 登场的契机。</p> <h2 id="第三部分yarn-的核心机制-i--ntk-by-parts-精细化插值">第三部分：YaRN 的核心机制 (I) —— “NTK-by-parts” 精细化插值</h2> <p>YaRN (Yet another RoPE extensioN method) 认识到，PI 和 NTK-aware 的失败在于它们试图用“一刀切”的方案处理所有 RoPE 维度。</p> <h3 id="31-yarn-的核心洞察分而治之-by-parts">3.1 YaRN 的核心洞察：分而治之 (By-Parts)</h3> <p>YaRN 的革命性思想是：<strong>根本不应该插值高频维度，而应该只插值低频维度</strong> 。</p> <ul> <li><strong>机理分析：</strong> <ul> <li><strong>高频（短波长）维度：</strong> 它们用于编码<em>局部</em>相对位置（例如相邻词的顺序）。插值它们会破坏这种能力（这是 PI 的错误）。</li> <li><strong>低频（长波长）维度：</strong> 它们用于编码<em>全局</em>相对位置（例如段落间的关系）。外推它们会产生 OOD 错误（这是 RoPE 的原始错误）。</li> </ul> </li> <li><strong>YaRN 的策略：</strong> <ol> <li>对高频维度：保留原始 $ \theta_d $。</li> <li>对低频维度：应用 PI ($ \theta_d / s $)。</li> <li>在两者之间：平滑过渡。</li> </ol> </li> </ul> <h3 id="32-数学解构-1ramp-function--gamma-">3.2 数学解构 (1)：Ramp Function ($ \gamma $)</h3> <p>为了实现这种“分而治之”的策略，”NTK-by-parts”（YaRN 使用的插值方法）引入了一个“斜坡函数” (ramp function) $ \gamma(r) $ 。</p> <ul> <li> <p><strong>关键变量：</strong>该函数不直接依赖于维度 $ d $，而是依赖于一个物理意义更强的比率 $ r(d) $ ：</p> \[r(d) = L / \lambda_d\] <p>其中 $ L $ 是原始上下文长度（例如 4096），$ \lambda_d $ 是第 $ d $ 维的波长。$ r(d) $ 的直观含义是：<strong>“在原始上下文窗口中，第 $d$ 维旋转了多少圈”</strong></p> </li> <li> <p><strong>斜坡函数 $ \gamma(r) $ 定义：</strong> 该函数引入了两个超参数 $ \alpha $ 和 $ \beta $ 来定义插值的边界。对于 Llama 模型，实验发现 $ \alpha=1 $ 和 $ \beta=32 $ 是很好的取值。 \(\gamma(r) = \begin{cases} 0, &amp; r &lt; \alpha \quad (\text{例如 } r &lt; 1), \\[6pt] 1, &amp; r &gt; \beta \quad (\text{例如 } r &gt; 32), \\[6pt] \dfrac{r - \alpha}{\beta - \alpha}, &amp; \text{其他情况.} \end{cases}\)</p> </li> </ul> <h3 id="33-数学解构-2-htheta_d--混合函数">3.3 数学解构 (2)：$ h(\theta_d) $ 混合函数</h3> <p>YaRN (NTK-by-parts) 的频率修改函数 $ h(\theta_d) $ 被定义为 PI 频率 ($\theta_d / s$) 和原始 RoPE 频率 ($\theta_d$) 的加权平均，权重由 $\gamma(r)$ 控制：</p> \[h(\theta_d) = \left( 1 - \gamma(r) \right) \frac{\theta_d}{s} + \gamma(r) \theta_d\] <h3 id="34-深度洞察三种模式的三重奏">3.4 深度洞察：三种模式的“三重奏”</h3> <p>“NTK-by-parts” 是一个极其精妙的设计，它完美地合成了 PI 和 NTK-aware 的优点。我们可以通过分析 $ \gamma(r) $ 的三个区间来理解其工作原理：</p> <ol> <li>模式 1：低频维度 (Low Frequencies) <ul> <li><strong>条件：</strong> $ r &lt; \alpha $ (例如 $ r &lt; 1 $)。这意味着波长 $ \lambda_d &gt; L $。这些是在原始上下文中“一圈都没转完”的维度，它们是 OOD 错误的<em>主要来源</em>。</li> <li><strong>计算：</strong> $ \gamma(r) = 0 $。</li> <li><strong>公式：</strong> $ h(\theta_d) = (1-0) \cdot (\theta_d / s) + 0 \cdot \theta_d = \theta_d / s $。</li> <li><strong>结论：</strong> <strong>这等同于纯粹的 PI</strong> 。YaRN <em>只</em>对这些最容易产生 OOD 错误的低频维度进行插值，完美解决了外推问题 。</li> </ul> </li> <li>模式 2：高频维度 (High Frequencies) <ul> <li><strong>条件：</strong> $ r &gt; \beta $ (例如 $ r &gt; 32 $)。这意味着波长 $ \lambda_d $ 极短，在原始上下文中“转了超过 32 圈”。这些维度对<em>局部</em>相对位置至关重要。</li> <li><strong>计算：</strong> $ \gamma(r) = 1 $。</li> <li><strong>公式：</strong> $ h(\theta_d) = (1-1) \cdot (\theta_d / s) + 1 \cdot \theta_d = \theta_d $。</li> <li><strong>结论：</strong> <strong>频率保持不变</strong> 10。YaRN <em>完全保留</em>了这些对区分近距离 token 至关重要的高频维度，完美解决了 PI 导致的“近距离混淆”问题 。</li> </ul> </li> <li><strong>模式 3：过渡维度 (Transition)</strong> <ul> <li><strong>条件：</strong> $ \alpha \le r \le \beta $。</li> <li><strong>计算：</strong> $ 0 &lt; \gamma(r) &lt; 1 $。</li> <li><strong>公式：</strong> $ h(\theta_d) $ 是 $ \theta_d/s $ 和 $ \theta_d $ 之间的平滑线性插值。这确保了从“插值”到“保留”的过渡是平滑的，避免了在频率空间中产生突兀的“断崖”。</li> </ul> </li> </ol> <p>综上所述，”NTK-by-parts” 保留了 PI 的“插值”稳定性（用于低频），又获得了 NTK-aware 的“高频保留”优势（用于高频），同时规避了两者的所有缺点。</p> <p><img src="/assets/img/posts/Transformer3/image9.jpg" alt="" class="img-fluid"/></p> <h2 id="第四部分yarn-的核心机制-ii--注意力缩放与温度调节">第四部分：YaRN 的核心机制 (II) —— 注意力缩放与温度调节</h2> <p>“NTK-by-parts” 解决了位置编码问题，但这只完成了 YaRN 拼图的一半 。</p> <h3 id="41-新问题长上下文中的注意力熵-entropy">4.1 新问题：长上下文中的注意力熵 (Entropy)</h3> <ul> <li> <p><strong>问题：</strong> 当上下文被“压缩”（即使是智能压缩）时，token 在 RoPE 嵌入空间中的有效“距离”被拉近了 。</p> </li> <li> <p><strong>后果：</strong> $ q \cdot k $ 的点积（即 logits）的方差会增大，导致 $ \text{softmax} $ 函数的输入值变得非常大。</p> </li> <li> <p><strong>“过度锐化” (Overly “sharp”)：</strong> 当 $ \text{softmax} $ 函数的输入值差异巨大时，其输出会“坍缩”到一个单一的最大值上。</p> </li> <li> <p><strong>致命缺陷：</strong> 这种过度锐化的注意力分布意味着模型“过度自信”，只关注极少数几个 token，而失去了对全局上下文的关注能力。这对于需要整合长距离信息的任务是致命的。</p> </li> </ul> <h3 id="42-yarn-的解决方案引入温度--t-">4.2 YaRN 的解决方案：引入温度 $ t $</h3> <p>解决 $ \text{softmax} $ 过度锐化的标准方法是使用“温度” (Temperature) $ t $ 。</p> <ul> <li><strong>数学公式：</strong> YaRN 修改了标准的注意力计算公式： <ul> <li> <table> <tbody> <tr> <td>标准注意力： $ \text{softmax}\left(\frac{q^T_m k_n}{\sqrt{</td> <td>D</td> <td>}}\right) $</td> </tr> </tbody> </table> </li> <li> <table> <tbody> <tr> <td>YaRN 注意力： $ \text{softmax}\left(\frac{q^T_m k_n}{t \sqrt{</td> <td>D</td> <td>}}\right) $</td> </tr> </tbody> </table> </li> </ul> </li> <li><strong>效果：</strong> 当 $ t &gt; 1 $ 时，它会“压平” logits，使 $ \text{softmax} $ 的输出更平滑（熵更高），从而恢复模型对全局上下文的敏感性，降低困惑度。</li> </ul> <h3 id="43-经验公式-t--与--s--的关系">4.3 经验公式：$ t $ 与 $ s $ 的关系</h3> <p>温度 $ t $ 不应是一个固定值，它必须随着上下文缩放因子 $ s $ 的增加而增加。通过在 Llama 模型上拟合困惑度 PPL 与缩放因子 $ s $ 的曲线，YaRN 的作者们得出了以下经验公式：</p> \[\frac{1}{\sqrt{t}} = 0.1 \ln(s) + 1\] <p><em>注：</em> 这一公式中的 $ 0.1 $ 是一个可调参数；例如，后续的 DeepSeek-V2 模型将其修改为 $ 0.0707 $ ，但这表明 $ 1/\sqrt{t} $ 与 $ \ln(s) $ 之间的对数关系是关键。</p> <h3 id="44-零开销实现技巧-the-length-scaling-trick">4.4 “零开销”实现技巧 (The “Length Scaling” Trick)</h3> <p><strong>挑战：</strong> 直接修改 $ \text{softmax} $ 公式（如上所示）意味着需要重写底层的注意力核（Kernel）。这将导致无法使用 Flash Attention 2 等高度优化的库，从而牺牲性能。</p> <p>YaRN 采用了一种极其巧妙的数学等价来实现零开销：</p> <ol> <li> <p>数学等价：</p> \[\frac{q^T k}{t} = \frac{(q / \sqrt{t})^T (k / \sqrt{t})}{1}\] </li> <li> <p><strong>实现：</strong> 我们不需要修改 $ \text{softmax} $。我们只需要在 $ q $ 和 $ k $ 向量进入点积运算<em>之前</em>，将它们分别乘以一个常数因子 $ \frac{1}{\sqrt{t}} $ 。</p> </li> <li> <p><strong>优化：</strong> $ \frac{1}{\sqrt{t}} $ 是一个常数（由 $ s $ 决定）。RoPE 嵌入 $ R_m $ 通常也是预先计算并缓存的。</p> </li> <li> <p><strong>“烘焙” (Bake-in)：</strong> YaRN 将这个 $ \frac{1}{\sqrt{t}} $ 缩放因子<em>直接“烘焙”到预计算的 RoPE 旋转嵌入中</em>。</p> </li> <li> <p><strong>结果：</strong> 这种“注意力缩放”是通过修改预计算的位置嵌入缓存来实现的。底层的注意力代码（如 Flash Attention）保持不变。因此，该技术在训练和推理期间<strong>完全没有（Zero）额外开销</strong>。</p> </li> </ol> <h3 id="45-yarn-完整定义">4.5 YaRN 完整定义</h3> <p>YaRN 是一个“组合拳”，它由两个核心组件构成： <strong>YaRN = “NTK-by-parts” 插值 + 注意力温度缩放</strong> 。</p> <p>“NTK-by-parts” 修正了<em>位置编码</em>的频率，而“注意力缩放”修正了<em>注意力分数</em>的动态范围。</p> <h2 id="第五部分实证分析yarn-的性能表现">第五部分：实证分析——YaRN 的性能表现</h2> <p>YaRN 的设计在理论上是完备的，其在基准测试中的表现也证实了这一点。</p> <h3 id="51-关键基准-1长序列语言建模-ppl">5.1 关键基准 (1)：长序列语言建模 (PPL)</h3> <ul> <li><strong>任务：</strong> 评估模型在超长文本（如 Proof-pile ）上的困惑度 (PPL)。PPL 越低，模型对文本的理解越流畅。</li> <li><strong>模型：</strong> <code class="language-plaintext highlighter-rouge">Yarn-Llama-2-7b-64k</code> 和 <code class="language-plaintext highlighter-rouge">Yarn-Llama-2-13b-128k</code> 。</li> <li><strong>结果：</strong> YaRN 模型的 PPL 曲线在整个 128k 上下文窗口内保持了强劲的性能（即 PPL 保持低位或持续下降），成功地将 Llama 2 的有效上下文扩展到 128k 。</li> <li>“训练短，测试长” (Train short, test long) 10： 一个惊人的发现是：目标为 128k (s=32) 的 YaRN 模型是在<em>长度仅为 64k</em> 的数据上进行微调的。然而，事实上这些模型在 64k 到 128k 范围内的 PPL 仍然<em>持续下降</em>。 这证明了 YaRN 不仅仅是“记住”了 64k 的长序列。模型在微调中实际上是学会了 $ \gamma(r) $ 和 $ \ln(s) $ 所定义的<em>新的缩放定律</em>。由于这些定律是平滑且连续的，模型能够将这种“定律”<em>泛化</em>（外推）到它在微调中也未见过的、更长的 128k 序列。这对于在计算受限下训练长下文模型至关重要。</li> </ul> <h3 id="52-关键基准-2大海捞针-passkey-retrieval">5.2 关键基准 (2)：”大海捞针” (Passkey Retrieval)</h3> <ul> <li><strong>任务：</strong> 这是对长上下文“注意力”的压力测试 。在一个长达 128k 的“干草堆”（无意义文本）中，能否找出一个随机插入的“针”（一个简单的五位数密码）。</li> <li><strong>测试目的：</strong> 验证模型是否在<em>整个</em>上下文（尤其是中间部分）都保持了注意力，以对抗“U 型”注意力衰减问题（即模型只关注开头和结尾） 。</li> <li><strong>结果：</strong> YaRN 微调的 7B 和 13B 模型（128k 上下文）在<em>整个 128k 窗口</em> 内，以 <strong>&gt; 99%</strong> 的高精度通过了 Passkey 检索任务 。</li> <li><strong>原因分析：</strong> 这种近乎完美的检索能力归功于 YaRN 的双重机制。 <ol> <li>“NTK-by-parts” 保留了高频信息，确保了模型在任何局部（无论是在 50k 还是 100k）都能精确地“看清” passkey。</li> <li>“Attention Scaling” 确保了注意力熵足够高 ，使模型不会“忽视”掉中间的大块上下文。</li> </ol> </li> </ul> <h3 id="53-关键基准-3短上下文基准-the-cost">5.3 关键基准 (3)：短上下文基准 (The “Cost”)</h3> <ul> <li><strong>任务：</strong> 评估 YaRN 模型在 Hugging Face Open LLM 排行榜上的标准基准（如 ARC, HellaSwag, MMLU, TruthfulQA ）上的表现。</li> <li><strong>测试目的：</strong> 扩展上下文窗口（例如到 128k）是否以牺牲模型<em>原始</em>预训练能力（即短上下文推理）为代价？ 。</li> <li><strong>结果：</strong> 结果是惊人的：“我们观察到 YaRN 模型与其各自的 Llama 2 基线之间几乎没有性能下降” 。</li> </ul> <p>下面的表格（基于 中的 Table 3）定量地证明了 YaRN 相比其他方法的“无缺点”特性：</p> <p><strong>表 1：YaRN 与 Llama 2 基线及其他扩展方法在短上下文基准上的性能对比 (Llama 7B)</strong></p> <table> <thead> <tr> <th>模型</th> <th>目标上下文</th> <th>扩展方法</th> <th>ARC-c</th> <th>Hellaswag</th> <th>MMLU</th> <th>TruthfulQA</th> </tr> </thead> <tbody> <tr> <td>Llama 2</td> <td>4k</td> <td>(基线)</td> <td>53.1</td> <td>77.8</td> <td>43.8</td> <td>39.0</td> </tr> <tr> <td>Together</td> <td>32k</td> <td>PI</td> <td>47.6</td> <td>76.1</td> <td>43.3</td> <td>39.2</td> </tr> <tr> <td>Code Llama</td> <td>100k</td> <td>NTK</td> <td>39.9</td> <td>60.8</td> <td>31.1</td> <td>37.8</td> </tr> <tr> <td><strong>YaRN (s=32)</strong></td> <td><strong>128k</strong></td> <td><strong>YaRN</strong></td> <td><strong>52.1</strong></td> <td><strong>78.4</strong></td> <td><strong>41.7</strong></td> <td><strong>37.3</strong></td> </tr> </tbody> </table> <p><strong>表格分析：</strong> 此表格是证明 YaRN 优越性的关键证据。</p> <ol> <li><strong>PI (Together 32k)</strong> 在所有指标上都显示出轻微但明显的性能下降，尤其是在 ARC-c 上 。</li> <li><strong>NTK-aware (Code Llama 100k)</strong> 显示出<em>灾难性</em>的性能下降，证实了其在微调后的不稳定性 。</li> <li><strong>YaRN (128k)</strong> 的分数几乎与 4k 基线<em>完全相同</em>，甚至在 Hellaswag 上略有提升。</li> </ol> <p>这无可辩驳地证明了 YaRN 首次实现了在<em>不牺牲短上下文性能</em>的前提下，<em>高效地</em>将上下文扩展到 128k 。</p> <h2 id="第六部分实践与应用指南">第六部分：实践与应用指南</h2> <h3 id="61-高效微调yarn-的计算优势">6.1 高效微调：YaRN 的计算优势</h3> <p>YaRN 不仅性能卓越，而且“计算高效” (compute-efficient) 。</p> <ul> <li><strong>定量数据：</strong> YaRN 声称比以前的方法（如 PI）需要<strong>少 10 倍的 token</strong> 和<strong>少 2.5 倍的训练步数</strong> 。</li> <li><strong>实例：</strong> <code class="language-plaintext highlighter-rouge">NousResearch/Yarn-Llama-2-7b-64k</code> 模型仅在 PG19 数据集的一个子集上进行了 <strong>400 步</strong> 的进一步预训练，就实现了 64k 的上下文窗口 。这证明了 YaRN 微调的极高效率 。</li> </ul> <h3 id="62-如何在-hugging-face-transformers-中使用-yarn">6.2 如何在 Hugging Face Transformers 中使用 YaRN</h3> <p>要在 <code class="language-plaintext highlighter-rouge">transformers</code> 库中正确加载和使用 YaRN 模型（如 <code class="language-plaintext highlighter-rouge">NousResearch/Yarn-Llama-2-7b-64k</code>），必须满足以下依赖和配置：</p> <ul> <li><strong>关键依赖：</strong> <ol> <li><strong>Flash Attention 2 (FA2)：</strong> YaRN 兼容 FA2 。要使用 YaRN 模型，必须安装 FA2 (<code class="language-plaintext highlighter-rouge">pip install flash-attn</code>) 。</li> <li><strong>Rotary Extensions：</strong> 需要安装 HazyResearch 的 <code class="language-plaintext highlighter-rouge">csrc/rotary</code> 扩展库 (<code class="language-plaintext highlighter-rouge">pip install git+https://github.com/HazyResearch/flash-attention.git#subdirectory=csrc/rotary</code>) 。</li> </ol> </li> <li> <p><strong><code class="language-plaintext highlighter-rouge">config.json</code> 配置：</strong> 要在 <code class="language-plaintext highlighter-rouge">transformers</code> 库中启用 YaRN 缩放，需要在模型的 <code class="language-plaintext highlighter-rouge">config.json</code> 文件中添加（或修改）<code class="language-plaintext highlighter-rouge">rope_scaling</code> 字典 。 <strong>配置示例：</strong></p> <p>JSON</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>"rope_scaling": {
    "type": "yarn",
    "factor": 16.0,
    "original_max_position_embeddings": 4096
}
</code></pre></div> </div> <ul> <li><code class="language-plaintext highlighter-rouge">"type": "yarn"</code>： 告知库使用 YaRN 的插值逻辑（即 “NTK-by-parts” + “Attention Scaling”）。</li> <li><code class="language-plaintext highlighter-rouge">"factor": 16.0"</code>： 目标缩放因子 <em>s</em> (例如 65536/4096=16.0）。</li> <li><code class="language-plaintext highlighter-rouge">"original_max_position_embeddings": 4096"</code>： <strong>（关键）</strong> 必须是<em>原始</em>预训练上下文长度 $ L $。</li> </ul> </li> <li><strong>实现的陷阱：</strong> 社区讨论 指出，不同库（如 <code class="language-plaintext highlighter-rouge">transformers</code> 和 <code class="language-plaintext highlighter-rouge">vLLM</code>）在读取这些配置时可能存在不一致。例如，<code class="language-plaintext highlighter-rouge">transformers</code> 的 <code class="language-plaintext highlighter-rouge">modeling_rope_utils.py</code> 过去可能错误地读取 <code class="language-plaintext highlighter-rouge">config.max_position_embeddings</code>（例如 64k）而不是 <code class="language-plaintext highlighter-rouge">config.original_max_position_embeddings</code>（4k）来计算缩放，这会导致完全错误的频率计算。因此，在实践中，必须<em>仔细检查</em>所用库的 RoPE 工具函数，以确保它正确地使用了 $ s $ 和 $ L $ 。</li> </ul> <h3 id="63-dynamic-yarn-vs-static-yarn-推理时">6.3 Dynamic-YaRN vs. Static-YaRN (推理时)</h3> <p>在推理时，YaRN 有两种截然不同的使用模式：</p> <ul> <li><strong>1. Static-YaRN (静态，用于微调模型)</strong> <ul> <li><strong>描述：</strong> 这是 <code class="language-plaintext highlighter-rouge">NousResearch/Yarn-Llama-2-7b-64k</code> 使用的方法。<code class="language-plaintext highlighter-rouge">factor</code> 是一个<em>固定</em>值（例如 16.0）。</li> <li><strong>优势：</strong> <strong>这是最高效、最推荐的推理方式</strong>。由于 $ s $ 固定，所有 RoPE 嵌入（已烘焙了 NTK-by-parts 和温度缩放）都可以被预计算、缓存，并与 KV 缓存 (Key-Value Caching) 完美兼容。</li> </ul> </li> <li><strong>2. Dynamic-YaRN (动态，用于非微调模型)</strong> <ul> <li> <p><strong>描述：</strong> 这是一种<em>纯推理时</em>技术，无需任何微调即可使用。</p> </li> <li> <p><strong>机理：</strong> 缩放因子 $ s = \max(1, L<em>{current} / L</em>{original}) $ 在<em>每个</em>前向传播步骤中<em>动态</em>更新 。</p> </li> <li> <p><strong>优势：</strong> 无需微调即可将 Llama 2 基线模型的上下文扩展 2 倍以上。</p> </li> <li> <p>严重性能陷阱 (KV 缓存失效)：Dynamic Scaling (动态缩放) 与标准 KV 缓存不兼容 。<strong>原因：</strong> KV 缓存依赖于 $ k<em>n $（包含 RoPE 旋转 $ R_n $）在 $ n $ 步计算后是恒定的。但在 Dynamic Scaling 中，RoPE 旋转 $ R_n $ 依赖于 $ s $，而 $ s $ 依赖于 $ L</em>{current} $（当前总长度）。当 $ L_{current} $ 从 100 变为 101 时， $ s $ 发生变化，导致 $ n=1…100 $ 的所有 $ R_n $ 全部失效。</p> <p>后果： 必须在每一步都对整个 KV 缓存重新应用 RoPE 旋转 。这会带来巨大的计算开销，可能完全抵消 KV 缓存带来的速度提升。</p> </li> </ul> <p><strong>实践建议：</strong> 应优先使用 <strong>Static-YaRN</strong>（即使用 YaRN <em>微调</em> 的模型），而非 Dynamic-YaRN。</p> </li> </ul> <h2 id="第七部分总结yarn-的贡献与未来">第七部分：总结——YaRN 的贡献与未来</h2> <h3 id="71-总结为什么-yarn-胜出">7.1 总结：为什么 YaRN 胜出？</h3> <p>YaRN 不是一个单一的技巧，而是对上下文扩展问题的一次<em>系统性</em>的、双管齐下的解决方案。它的成功在于它同时解决了两个独立但相关的问题：</p> <ol> <li><strong>理论完备性：</strong> <ul> <li><strong>“NTK-by-parts”</strong> 精确地识别并分别解决了高频（保留）和低频（插值）维度的问题，解决了<em>位置编码</em>的 OOD 和分辨率损失问题。</li> <li><strong>“Attention Scaling”</strong> 解决了在长下文中由压缩引起的<em>注意力动力学</em>的熵崩溃问题 。</li> </ul> </li> <li><strong>实践高效性：</strong> <ul> <li><strong>训练：</strong> 训练成本极低（10 倍更少 token, 400 步） 。</li> <li><strong>推理：</strong> “零开销” 并与 Flash Attention 2 兼容 。</li> <li><strong>性能：</strong> 在长上下文（PPL, Passkey） 和短上下文（MMLU, ARC） 上均达到 SOTA 或与基线持平。</li> </ul> </li> </ol>]]></content><author><name></name></author><category term="AI"/><category term="Transformer"/><summary type="html"><![CDATA[从 RoPE 的长度外推问题出发，解析 YaRN 的 NTK-by-parts 与注意力缩放。]]></summary></entry><entry><title type="html">论文阅读(1)——TpuGraphs</title><link href="https://samsz04.github.io/2025/11/05/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB1-tpugraphs/" rel="alternate" type="text/html" title="论文阅读(1)——TpuGraphs"/><published>2025-11-05T18:10:52+08:00</published><updated>2025-11-05T18:10:52+08:00</updated><id>https://samsz04.github.io/2025/11/05/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB1-tpugraphs</id><content type="html" xml:base="https://samsz04.github.io/2025/11/05/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB1-tpugraphs/"><![CDATA[<p>论文：<a href="https://arxiv.org/abs/2308.13490">TpuGraphs: A Performance Prediction Dataset on Large Tensor Computational Graphs</a></p> <p>Github仓库：<a href="https://github.com/google-research-datasets/tpu_graphs">google-research-datasets/tpu_graphs</a></p> <p>论文分析：</p> <p><img src="/assets/img/posts/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB1-tpugraphs/TpuGraph_RoPE_Page1.png" alt="" class="img-fluid"/> <img src="/assets/img/posts/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB1-tpugraphs/TpuGraph_RoPE_Page2.png" alt="" class="img-fluid"/> <img src="/assets/img/posts/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB1-tpugraphs/TpuGraph_RoPE_Page3.png" alt="" class="img-fluid"/> <img src="/assets/img/posts/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB1-tpugraphs/TpuGraph_RoPE_Page4.png" alt="" class="img-fluid"/> <img src="/assets/img/posts/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB1-tpugraphs/TpuGraph_RoPE_Page5.png" alt="" class="img-fluid"/> <img src="/assets/img/posts/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB1-tpugraphs/TpuGraph_RoPE_Page6.png" alt="" class="img-fluid"/> <img src="/assets/img/posts/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB1-tpugraphs/TpuGraph_RoPE_Page7.png" alt="" class="img-fluid"/> <img src="/assets/img/posts/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB1-tpugraphs/TpuGraph_RoPE_Page8.png" alt="" class="img-fluid"/> <img src="/assets/img/posts/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB1-tpugraphs/TpuGraph_RoPE_Page9.png" alt="" class="img-fluid"/> <img src="/assets/img/posts/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB1-tpugraphs/TpuGraph_RoPE_Page10.png" alt="" class="img-fluid"/> <img src="/assets/img/posts/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB1-tpugraphs/TpuGraph_RoPE_Page11.png" alt="" class="img-fluid"/> <img src="/assets/img/posts/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB1-tpugraphs/TpuGraph_RoPE_Page12.png" alt="" class="img-fluid"/> <img src="/assets/img/posts/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB1-tpugraphs/TpuGraph_RoPE_Page13.png" alt="" class="img-fluid"/> <img src="/assets/img/posts/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB1-tpugraphs/TpuGraph_RoPE_Page14.png" alt="" class="img-fluid"/> <img src="/assets/img/posts/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB1-tpugraphs/TpuGraph_RoPE_Page15.png" alt="" class="img-fluid"/> <img src="/assets/img/posts/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB1-tpugraphs/TpuGraph_RoPE_Page16.png" alt="" class="img-fluid"/> <img src="/assets/img/posts/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB1-tpugraphs/TpuGraph_RoPE_Page17.png" alt="" class="img-fluid"/> <img src="/assets/img/posts/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB1-tpugraphs/TpuGraph_RoPE_Page18.png" alt="" class="img-fluid"/> <img src="/assets/img/posts/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB1-tpugraphs/TpuGraph_RoPE_Page19.png" alt="" class="img-fluid"/> <img src="/assets/img/posts/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB1-tpugraphs/TpuGraph_RoPE_Page20.png" alt="" class="img-fluid"/> <img src="/assets/img/posts/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB1-tpugraphs/TpuGraph_RoPE_Page21.png" alt="" class="img-fluid"/> <img src="/assets/img/posts/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB1-tpugraphs/TpuGraph_RoPE_Page22.png" alt="" class="img-fluid"/></p>]]></content><author><name></name></author><category term="AI"/><category term="TPU"/><category term="Compiler"/><category term="AutoTuner"/><summary type="html"><![CDATA[TpuGraphs 论文阅读笔记：面向大型张量计算图的性能预测数据集。]]></summary></entry><entry><title type="html">Transformer位置编码(2)——RoPE</title><link href="https://samsz04.github.io/2025/11/04/Transformer-position-embedding2/" rel="alternate" type="text/html" title="Transformer位置编码(2)——RoPE"/><published>2025-11-04T14:38:41+08:00</published><updated>2025-11-04T14:38:41+08:00</updated><id>https://samsz04.github.io/2025/11/04/Transformer-position-embedding2</id><content type="html" xml:base="https://samsz04.github.io/2025/11/04/Transformer-position-embedding2/"><![CDATA[<h2 id="第一部分深入解析旋转位置编码rope">第一部分：深入解析旋转位置编码（RoPE）</h2> <p>旋转位置编码（RoPE）代表了位置编码领域的一次范式转移，它通过一种新颖的<strong>几何视角</strong>统一了绝对位置编码和相对位置编码。自提出以来，RoPE因其优越的性能和良好的理论特性，迅速成为众多先进大语言模型（如Llama、PaLM、Qwen）的标准配置。</p> <p><img src="/assets/img/posts/Transformer-position-embedding2/image1.png" alt="" class="img-fluid"/></p> <h3 id="11-概念框架通过旋转编码位置">1.1 概念框架：通过旋转编码位置</h3> <p>RoPE的<strong>核心思想</strong>极其直观且优雅：它不再通过向量加法来注入位置信息，而是通过<strong>旋转</strong>查询（Q）和键（K）向量来实现。<strong>每个词元在序列中的绝对位置 $m$ 对应一个特定的旋转角度</strong>。当Q和K向量根据它们各自的绝对位置 $m$ 和 $n$ 进行旋转后，它们之间的点积（即注意力分数的核心部分）将<strong>只依赖于它们的相对位置 $m-n$</strong>。</p> <p><img src="/assets/img/posts/Transformer-position-embedding2/image2.png" alt="" class="img-fluid"/></p> <p><img src="/assets/img/posts/Transformer-position-embedding2/image3.webp" alt="" class="img-fluid"/></p> <p>我们可以借助一个“时钟”的比喻来理解这个过程：</p> <ol> <li><strong>多指针时钟</strong>：将一个 $d$ 维的嵌入向量看作由 $d/2$ 个<strong>二维平面</strong>上的指针（或复数）组成。<strong>每个指针代表一个维度对</strong>。</li> <li><strong>不同的转速</strong>：每个指针（维度对）都<strong>以自己独特的速度（频率</strong>旋转。低维度的指针转得快，高维度的指针转得慢。</li> <li><strong>位置即角度</strong>：<strong>一个词元的绝对位置 $m$ 决定了所有指针需要旋转的角度</strong>。具体来说，第 $i$ 个指针的旋转角度是 $m \cdot \theta_i$，其中 $\theta_i$ 是该指针固有的转速。</li> <li><strong>相对位置的体现</strong>：当计算位置为 $m$ 的查询和位置为 $n$ 的键之间的注意力时，我们实际上是在比较这两个“时钟”状态。由于<strong>点积运算对旋转具有不变性</strong>（两个向量一起旋转相同的角度，它们的点积不变），最终的计算结果只取决于两个时钟指针之间的<strong>角度差</strong>，这个差值正比于相对距离 $m-n$。</li> </ol> <p><img src="/assets/img/posts/Transformer-position-embedding2/image4.png" alt="" class="img-fluid"/></p> <p>这种多尺度的旋转机制是RoPE成功的关键。快速旋转的指针（低维，高频）能够精确地区分邻近的位置，为模型提供细粒度的局部信息。而缓慢旋转的指针（高维，低频）则能在很长的距离上保持独特的角度，从而为模型提供捕捉远距离依赖所需的粗粒度全局信息。这种设计避免了单一频率可能导致的“混叠”问题，即在某个周期后，不同位置的旋转状态变得无法区分。</p> <h3 id="12-数学公式与推导">1.2 数学公式与推导</h3> <p>为了严谨地理解RoPE，我们需要深入其数学推导。其目标是找到一个编码函数 $f(\mathbf{x}, m)$，它作用于词元嵌入 $\mathbf{x}$ 和其绝对位置 $m$，使得编码后的查询 $f(\mathbf{q}, m)$ 和键 $f(\mathbf{k}, n)$ 的内积<strong>只与</strong> $\mathbf{q}$、$\mathbf{k}$ 以及它们的相对位置 $m-n$ 有关：</p> \[\langle f(\mathbf{q}, m), f(\mathbf{k}, n) \rangle = g(\mathbf{q}, \mathbf{k}, m-n)\] <p>最简洁的推导方式是借助复数。我们可以将一个 $d$ 维的实数向量 $\mathbf{x} \in \mathbb{R}^d$ 视为一个 $d/2$ 维的复数向量 $\mathbf{x} \in \mathbb{C}^{d/2}$，其中每两个连续的实数分量 $(x_{2i}, x_{2i+1})$ 组成一个复数 $x_i = x_{2i} + j \cdot x_{2i+1}$ 。</p> <p>在复数域中，旋转可以通过乘以一个模为1的复数 $e^{j\theta}$ 来实现。我们定义编码函数为：</p> \[f(\mathbf{x}, m) = \mathbf{x} \odot e^{jm\mathbf{\theta}}\] <p>其中 $\odot$ 表示逐元素相乘，$\mathbf{\theta} = [\theta_1, \theta_2, \dots, \theta_{d/2}]$ 是一个包含不同旋转频率的向量。</p> <p>现在，我们来计算编码后的查询和键的内积（在复数域中，内积定义为 $\langle a, b \rangle = a \cdot \bar{b}$，其中 $\bar{b}$ 是 $b$ 的共轭）：</p> \[\begin{align*} \langle f(\mathbf{q}, m), f(\mathbf{k}, n) \rangle &amp;= \operatorname{Re}\big( (\mathbf{q}\odot e^{jm\boldsymbol{\theta}})\cdot\overline{(\mathbf{k}\odot e^{jn\boldsymbol{\theta}})} \big) \\ &amp;= \operatorname{Re}\big( (\mathbf{q}\odot e^{jm\boldsymbol{\theta}})\cdot(\overline{\mathbf{k}}\odot e^{-jn\boldsymbol{\theta}}) \big) \\ &amp;= \operatorname{Re}\big( (\mathbf{q}\cdot\overline{\mathbf{k}})\odot e^{j(m-n)\boldsymbol{\theta}} \big) \end{align*}\] <p>从最后的结果可以看出，内积的表达式中只包含了相对位置 $m-n$，而绝对位置 $m$ 和 $n$ 被完美地消除了。</p> <p>将这个思想转换回实数域，对于向量中的每一对维度 $(x_{2i}, x_{2i+1})$，<strong>上述复数乘法等价于乘以一个2D旋转矩阵</strong>：</p> \[\begin{pmatrix} x'_{2i} \\ x'_{2i+1} \end{pmatrix} = \begin{pmatrix} \cos(m\theta_i) &amp; -\sin(m\theta_i) \\ \sin(m\theta_i) &amp; \cos(m\theta_i) \end{pmatrix} \begin{pmatrix} x_{2i} \\ x_{2i+1} \end{pmatrix}\] <p>对于整个 $d$ 维向量，这个操作<strong>相当于左乘一个块对角矩阵</strong>，其中<strong>每个对角块都是一个2D旋转矩阵</strong>。</p> <p><img src="/assets/img/posts/Transformer-position-embedding2/image5.webp" alt="" class="img-fluid"/></p> <p><img src="/assets/img/posts/Transformer-position-embedding2/image6.webp" alt="" class="img-fluid"/></p> <p>旋转的频率 $\theta_i$ 通常按照以下公式定义：</p> \[\theta_i = \text{base}^{-2(i-1)/d}\] <p>其中 $d$ 是嵌入维度中用于RoPE的部分（通常是每个注意力头的维度），而 $\text{base}$ 是一个超参数，原始论文中设为10000。这个公式确保了频率 $\theta_i$ 随着维度索引 $i$ 的增加而几何递减，从而实现了前文所述的<strong>多尺度“时钟”效果</strong>。</p> <h3 id="13-rope的关键特性与理论优势">1.3 RoPE的关键特性与理论优势</h3> <p>RoPE之所以被广泛采用，得益于其几个核心的理论优势：</p> <ol> <li><strong>序列长度的灵活性</strong>：由于RoPE在注意力计算中有效地编码了相对位置，它对序列长度具有很强的泛化能力。模型在较短序列上训练后，可以直接应用于更长的序列，而不会像某些绝对位置编码方法那样出现性能急剧下降的情况。</li> <li> <table> <tbody> <tr> <td><strong>远程依赖的衰减特性</strong>：从数学上可以证明，经过RoPE旋转后的两个向量，它们的内积会随着相对距离 $</td> <td>m-n</td> <td>$ 的增大而衰减。这为模型提供了一个非常有用的归纳偏置：<strong>距离越近的词元通常关系越密切，注意力得分应该越高；反之，距离越远的词元关系可能越弱</strong>。</td> </tr> </tbody> </table> </li> <li><strong>与线性注意力的兼容性</strong>：这是RoPE相较于传统RPE的一个决定性优势。因为RoPE是对Q和K向量的独立预处理，它发生在点积注意力计算之前。这意味着它与任何旨在避免计算完整注意力矩阵的线性注意力或高效注意力机制都是<strong>完全兼容</strong>的。这使得RoPE能够应用于对计算效率要求极高的超长序列模型中。</li> </ol> <p><img src="/assets/img/posts/Transformer-position-embedding2/image7.webp" alt="" class="img-fluid"/></p> <h3 id="14-现代大语言模型中的rope分析以llama-3的rope_theta为例">1.4 现代大语言模型中的RoPE分析：以Llama 3的<code class="language-plaintext highlighter-rouge">rope_theta</code>为例</h3> <p>理论的优雅需要通过实践来验证和优化。RoPE在现代大语言模型中的应用，特别是Llama 3系列模型的实现，为我们提供了一个绝佳的案例，展示了理论属性如何根据实际需求被调整。</p> <p>在Llama 3的配置文件中，一个关键的超参数<code class="language-plaintext highlighter-rouge">rope_theta</code>被设置为500000.0，远大于原始RoPE论文中使用的10000.0。这个参数正是前文频率公式中的$\text{base}$项。</p> <table> <tbody> <tr> <td>这一调整并非无心之举，它深刻地改变了RoPE的行为。增大<code class="language-plaintext highlighter-rouge">rope_theta</code>的值，会使得所有的旋转频率 $\theta_i$ 变小。换言之，它让所有维度的“时钟指针”都转得更慢了。其直接后果是，RoPE固有的“远程依赖衰减”特性被显著减弱。当旋转角度随位置增长得更慢时，**即使相对距离 $</td> <td>m-n</td> <td>$ 很大，旋转带来的相位差也较小，从而使得内积（注意力分数）的衰减变得平缓**。</td> </tr> </tbody> </table> <p>这一改动背后的动机是显而易见的。随着大模型竞赛进入“长上下文”时代，模型需要处理越来越长的文档、代码库或对话历史。在这些场景下，<strong>相距非常遥远的两个词元之间可能存在着至关重要的联系（例如，“大海捞针”测试）。在这种情况下，RoPE原始的快速衰减特性反而成了一种阻碍，因为它会惩罚模型对远距离信息的关注</strong>。</p> <p>因此，Llama 3的工程师们通过调整<code class="language-plaintext highlighter-rouge">rope_theta</code>这一简单的杠杆，有原则地修改了模型的归纳偏置，使其更适应长上下文推理的任务。这完美地说明了RoPE的特性既是其优点，也是一个可调节的参数。理论上被认为是“理想属性”的远程衰减，在新的应用需求下，可以被灵活地调整甚至抑制。这突显了在最先进的模型开发中，深刻的理论理解与务实的工程决策之间相辅相成的关系。</p> <h2 id="第二部分将rope扩展至多模态环境">第二部分：将RoPE扩展至多模态环境</h2> <p>RoPE在处理一维文本序列方面取得了巨大成功，但真实世界的信息远不止于此。图像、视频等多模态数据具有更复杂的结构，这对位置编码提出了新的挑战。<strong>将RoPE从一维扩展到多维是构建像Qwen3-VL这样的高级视觉语言模型的关键一步</strong>。</p> <h3 id="21-多维度的挑战从一维文本到二维视觉">2.1 多维度的挑战：从一维文本到二维视觉</h3> <p>文本本质上是一维序列，而图像是二维的空间结构，<strong>视频则是在二维空间基础上增加了第三个维度——时间</strong>。简单地将图像分割成块（patches）然后展平成一个一维序列，虽然是Vision Transformer（ViT）的初始做法，但这种方式会丢失关键的几何信息。模型将无法理解“上方”、“左侧”或“右下角”等基本的空间关系，这对于需要细粒度视觉理解的任务（如目标检测、文档布局分析）是致命的。</p> <p>因此，一个适用于多模态数据的位置编码方案，必须能够同时处理多个坐标轴（例如，时间 $t$、高度 $h$、宽度 $w$），并让模型理解这些维度上的相对关系。</p> <h3 id="22-多模态ropem-rope位置设计与频率分配">2.2 多模态RoPE（M-RoPE）：位置设计与频率分配</h3> <p>为了将RoPE扩展到多维，研究者们提出了多模态RoPE（M-RoPE）的概念。其核心思想是为每个维度（如 $t, h, w$）应用独立的旋转。然而，这一看似简单的扩展引入了两个关键且复杂的设计抉择：</p> <ol> <li><strong>位置设计（Position Design）</strong>：如何为文本和视觉（图像/视频帧）词元分配多维坐标 $(t, h, w)$。一个好的设计必须能够明确区分不同模态的词元，并避免位置歧义。例如，一些早期方案可能会导致视觉词元和后续生成的文本词元拥有重叠的坐标，造成“模态混淆”。</li> <li><strong>频率分配（Frequency Allocation）</strong>：如何将模型的嵌入维度（例如，一个注意力头的128维）分配给不同的坐标轴（$t, h, w$）来计算旋转。这是M-RoPE实现中最具挑战性也最关键的一环。</li> </ol> <p>一种直接的频率分配策略是“<strong>分块式</strong>”（Blocked）分配。例如，对于一个128维的向量，可以将前42维分配给时间轴 $t$，接下来的43维分配给高度轴 $h$，最后43维分配给宽度轴 $w$。每个轴在其分配到的维度块内，独立地应用从高到低的旋转频率。这种方法虽然简单，但存在严重缺陷：<strong>它迫使某些轴（在这个例子中是时间轴 $t$）只能使用高频旋转</strong>，而其他轴只能使用中低频旋转。高频旋转意味着注意力会随着距离的增加而迅速衰减，这对于需要<strong>捕捉长时序关系的视频理解任务</strong>是极其不利的。同时，不同轴使用<strong>不对称</strong>的频率范围也可能引入不必要的偏见。</p> <p>下表对比了不同的M-RoPE设计策略，系统地展示了它们各自的局限性，并为理解Qwen3-VL所采用的“交错式”方案的动机提供了背景。</p> <table> <thead> <tr> <th><strong>设计变体</strong></th> <th><strong>位置分配策略</strong></th> <th><strong>频率分配策略</strong></th> <th><strong>主要局限性</strong></th> </tr> </thead> <tbody> <tr> <td><strong>一维序列化</strong></td> <td>将所有词元展平为一维序列</td> <td>所有维度用于单一轴</td> <td>丢失2D/3D几何结构，空间推理能力差</td> </tr> <tr> <td><strong>MRoPE (分块式)</strong></td> <td>为视觉词元分配3D坐标</td> <td>将嵌入维度<strong>分块</strong>分配给t, h, w轴</td> <td>频率分配不均，导致某些轴（如时间）注意力快速衰减，不利于长时序建模</td> </tr> <tr> <td><strong>VideoRoPE (对角线布局)</strong></td> <td>对角线式分配位置ID</td> <td>将时间轴分配给低频维度</td> <td>可能导致视觉和文本词元位置重叠，引发模态混淆</td> </tr> <tr> <td><strong>Interleaved-MRoPE (交错式)</strong></td> <td>为视觉词元分配3D坐标</td> <td>将嵌入维度<strong>交错</strong>分配给t, h, w轴</td> <td>解决了频率分配不均的问题，为所有轴提供全频谱频率覆盖</td> </tr> </tbody> </table> <h3 id="23-交错式rope变体频率分配的范式转变">2.3 交错式RoPE变体：频率分配的范式转变</h3> <p><img src="/assets/img/posts/Transformer-position-embedding2/image7.jpg" alt="" class="img-fluid"/></p> <p>为了克服分块式分配的缺陷，一种更先进的策略——<strong>“交错式”</strong>(Interleaved)频率分配——被提出并应用于Qwen3-VL等模型中。</p> <p>交错式分配的核心思想是，不再将连续的维度块分配给单个轴，而是在所有轴之间以<strong>轮询（round-robin）的方式</strong>交错分配维度。以一个三维坐标 $(t, h, w)$ 为例，分配方式可能如下：</p> <ul> <li>维度对0分配给时间轴 $t$</li> <li>维度对1分配给高度轴 $h$</li> <li>维度对2分配给宽度轴 $w$</li> <li>维度对3分配给时间轴 $t$</li> <li>维度对4分配给高度轴 $h$</li> <li>… 以此类推</li> </ul> <p>通过这种方式，<strong>每一个坐标轴（$t, h, w$）都能获得从最高到最低的完整频率谱</strong>。时间轴 $t$ 不再局限于高频维度，它同样可以使用低频维度来进行缓慢旋转，从而有效捕捉长距离的时间依赖。同理，<strong>空间轴 $h$ 和 $w$ 也能利用高频维度来感知局部细节，利用低频维度来理解全局布局</strong>。</p> <p>这种方法从根本上解决了分块式分配导致的注意力快速衰减和不对称衰减的问题，为所有维度提供了均衡且鲁棒的多尺度建模能力。这种实现模式在一些底层算子库中也有体现，例如ONNX的<code class="language-plaintext highlighter-rouge">RotaryEmbedding</code>算子就提供了一个<code class="language-plaintext highlighter-rouge">interleaved</code>属性来支持这种计算模式，这表明它是一种被业界认可的高效实现方案。</p> <h2 id="第三部分解构qwen3-vl架构中的rope">第三部分：解构Qwen3-VL架构中的RoPE</h2> <p>本部分将综合前述所有理论知识，对目标模型Qwen3-VL中的RoPE实现进行一次集中的、深入的分析。我们将追溯其在Qwen系列中的演进，并详细剖析其“交错式M-RoPE”的具体实现及其对模型性能的深远影响。</p> <h3 id="31-qwen-vl系列中位置编码的架构概览">3.1 Qwen-VL系列中位置编码的架构概览</h3> <p>Qwen（通义千问）系列模型在位置编码的选择上经历了一个清晰的演进过程，反映了该领域技术发展的趋势。早期的Qwen-VL模型，在其视觉-语言适配器中采用了二维绝对位置编码来保留图像特征的位置信息，这是一种相对传统和直接的方法。然而，随着模型向更复杂的时空理解能力发展，后续的模型版本，特别是Qwen2-VL和Qwen3-VL，转向了更先进的RoPE方案，并专门为其多模态特性设计了M-RoPE。这一转变标志着模型设计从简单的位置注入转向了通过几何变换来编码复杂的相对关系，旨在获得更强的泛化和外推能力。</p> <h3 id="32-qwen3-vl中的交错式m-rope实现">3.2 Qwen3-VL中的交错式M-RoPE实现</h3> <p>Qwen3-VL模型架构的一项核心更新，被官方明确描述为“<strong>增强的、采用交错式布局的MRoPE</strong>” (enhanced MRope with interleaved layout) 和 <strong>“交错式MRoPE” (Interleaved-MRoPE)</strong>。这正是前面部分所讨论的先进频率分配方案。</p> <p>Qwen团队在其<a href="[Qwen](https://qwen.ai/blog?id=99f0335c4ad9ff6153e517418d48535ab6d8afef&amp;from=research.latest-advancements-list)">技术博客</a>中明确指出了做出这一改变的原因：他们识别出原始“分块式”MRoPE将所有时序信息集中在高频维度的缺陷，并采用交错式方案来实现“<strong>跨越时间、高度和宽度的全频率覆盖</strong>”。这一决策是经过深思熟虑的，旨在直接解决前代M-RoPE方案的瓶颈。</p> <p>通过分析Qwen3-VL在Hugging Face等平台的官方代码库（例如<code class="language-plaintext highlighter-rouge">modeling_qwen3_vl.py</code>文件）和文档，我们可以进一步理解其实现细节。在代码层面，模型会为输入的视觉词元（来自图像或视频帧的patches）生成三维坐标 $(t, h, w)$。在应用RoPE时，查询和键向量的嵌入维度会根据交错模式被逻辑上地分配给这三个轴。对于一个给定的维度对，它会被指定用于旋转其中一个轴的坐标，而这个指定关系会在所有维度对上循环。最终，每个词元的Q和K向量会经历三次独立的旋转（分别由$t, h, w$坐标驱动），这些旋转效果叠加在一起，形成最终的位置编码。这种方式确保了模型在计算注意力时，能够同时、均衡地考虑所有维度上的相对位置关系。</p> <h3 id="33-实践意义与性能分析">3.3 实践意义与性能分析</h3> <p>Qwen3-VL采用交错式M-RoPE并非单纯的学术探索，而是由解决实际问题驱动的工程决策。官方文档和技术报告反复强调，这一特定的实现带来了“<strong>更好的时空建模能力</strong>”和“<strong>增强的长时程视频推理能力</strong>”。</p> <p>这背后的因果联系是清晰且直接的：</p> <ol> <li><strong>提升长视频理解能力</strong>：通过确保时间轴 $t$ 能够使用低频旋转，模型的注意力不会随着视频时长的增加而过快衰减。这使得模型能够有效地关联视频开头和结尾的关键事件，从而在长达数小时的视频中实现精准的事件定位和内容理解。</li> <li><strong>增强空间推理能力</strong>：通过确保空间轴 $h$ 和 $w$ 也能访问完整的频率谱，模型获得了真正的多尺度空间感知能力。高频旋转使其能够关注图像中的精细纹理和微小物体（如文档中的字符），而低频旋转使其能够理解整体的布局和场景结构（如表格的行列关系）。</li> </ol> <p>这种架构上的优化，直接转化为模型在各项基准测试和实际应用中的卓越表现。Qwen3-VL在复杂的长视频问答、文档解析和视觉定位等任务上的领先性能，很大程度上归功于其先进且经过精心设计的交错式M-RoPE机制。</p> <p>总而言之，Qwen3-VL中交错式M-RoPE的应用，是复杂问题驱动架构演进的典范。它并非一项全新的发明，而是对现有技术（M-RoPE）的深刻理解和精巧改良。这反映出大模型研发已进入一个成熟阶段，性能的提升不再仅仅依赖于数据和参数规模的堆砌，更来自于对模型内部机制的深刻洞察和有针对性的架构优化。这个过程可以概括为：识别关键任务瓶颈（如长视频理解）-&gt; 分析底层架构局限（如分块式M-RoPE的频率分配问题）-&gt; 提出并实施针对性的解决方案（交错式分配）-&gt; 实现模型能力的代际跃升。</p>]]></content><author><name></name></author><category term="AI"/><category term="Transformer"/><summary type="html"><![CDATA[系统梳理 RoPE 的原理、数学形式及其在 Transformer 中的实现逻辑。]]></summary></entry><entry><title type="html">Transformer位置编码(1)——初探</title><link href="https://samsz04.github.io/2025/11/03/Transformer-position-embedding1/" rel="alternate" type="text/html" title="Transformer位置编码(1)——初探"/><published>2025-11-03T15:32:38+08:00</published><updated>2025-11-03T15:32:38+08:00</updated><id>https://samsz04.github.io/2025/11/03/Transformer-position-embedding1</id><content type="html" xml:base="https://samsz04.github.io/2025/11/03/Transformer-position-embedding1/"><![CDATA[<h2 id="第一部分transformer中位置信息的基础原理">第一部分：Transformer中位置信息的基础原理</h2> <h3 id="11-自注意力机制中的置换不变性问题">1.1 自注意力机制中的置换不变性问题</h3> <p>Transformer架构的核心是<strong>自注意力（Self-Attention）机制</strong>，它赋予了模型强大的并行处理能力和捕捉长距离依赖的潜力。然而，这种设计也带来了一个固有的、必须被正视的局限性：<strong>置换不变性（Permutation Invariance）</strong>。从根本上说，自注意力机制将输入序列视为一个<strong>无序的标记集合（”bag of words”）</strong>，而非一个有序的序列。</p> <p>这种特性源于其核心计算过程。对于一个给定的输入序列，自注意力机制通过计算查询（Query, Q）、键（Key, K）和值（Value, V）矩阵之间的点积来生成注意力分数，其公式可以简化为 $Attention(Q, K, V) = \text{softmax}(\frac{QK^T}{\sqrt{d_k}})V$。在这个计算中，任何一个标记的输出表示都是其对序列中所有其他标记的加权求和。关键在于，这些权重仅取决于Q和K向量之间的相似度，而与它们在序列中的原始位置无关。因此，如果输入序列的顺序被打乱，自注意力机制的输出序列也会以同样的方式被打乱，但每个标记自身的表示向量并不会因其位置的改变而改变。这一特性被称为置换等变性（Permutation Equivariance）。</p> <p>这种架构特性意味着，如果没有额外的位置信息，模型将无法区分语义完全不同的句子，例如“猫坐在垫子上”和“垫子坐在猫上”。对于模型而言，这两个句子包含了完全相同的词元集合，因此自注意力机制会为它们生成相似的内部表示，这在自然语言处理任务中是不可接受的。</p> <p>深入分析可以发现，对位置编码的需求并非Transformer设计中的疏忽，而是其最大优势——<strong>并行化</strong>——所带来的必然结果。传统的序列模型，如循环神经网络（RNN）和长短期记忆网络（LSTM），通过其固有的循环结构来处理序列。它们一次处理一个词元，将前一个时间步的信息通过隐藏状态传递到下一个时间步，这种顺序处理的方式天然地编码了词元的位置和顺序信息。然而，这种顺序依赖性也成为了它们的瓶颈，阻碍了大规模并行计算，限制了模型在现代硬件（如GPU）上的训练效率。</p> <p>Transformer架构通过完全摒弃循环结构，实现了对整个输入序列的并行处理，从而极大地提升了计算效率。模型中的每个词元可以同时与所有其他词元进行交互，这使得Transformer能够高效地处理长序列。然而，正是这种架构选择，即用并行计算换取顺序处理，导致了模型失去了对序列顺序的内在感知能力。因此，<strong>位置编码</strong>（Positional Encoding）应运而生，它是一种工程上的解决方案，旨在将至关重要的顺序信息重新注入到一个本质上是并行化的框架中。这体现了在计算效率和结构感知能力之间经典的工程权衡。</p> <p><img src="/assets/img/posts/Transformer-position-embedding1/image1.jpg" alt="" class="img-fluid"/></p> <h3 id="12-位置编码策略分类">1.2 位置编码策略分类</h3> <p>为了解决自注意力机制的置换不变性问题，研究者们开发了多种策略来为模型提供位置信息。这些策略可以大致分为<strong>三个主要类别</strong>，为理解后续更高级的技术（如RoPE）提供了清晰的框架。</p> <ol> <li><strong>绝对位置编码 (Absolute Positional Embeddings, APE):</strong> 这类方法为序列中的<strong>每一个绝对位置</strong>（例如，第1个位置、第2个位置等）<strong>分配一个唯一的、固定的向量</strong>。这个位置向量随后会与对应位置的词元嵌入（token embedding）相结合，通常是通过相加的方式。这样，即使是相同的词元，在序列的不同位置也会拥有不同的最终表示，从而使模型能够区分它们的顺序。最经典的方法是Vaswani等人在原始Transformer论文中提出的正弦/余弦编码。</li> <li><strong>相对位置编码 (Relative Positional Embeddings, RPE):</strong> 与关注绝对位置不同，相对位置编码的核心思想是模型更应该关注词元之间的相对关系，即<strong>它们之间的距离或方向</strong>。这类方法通常不是在输入层修改词元嵌入，而是在自注意力计算过程中直接注入相对位置信息。例如，通过为查询和键之间的特定距离添加一个可学习的偏置项（bias），使得注意力分数能够感知到两个词元“相距多远”。</li> <li><strong>混合/旋转方法 (Hybrid/Rotary Approaches): **这类方法，以旋转位置编码（Rotary Position Embedding, RoPE）为代表，巧妙地</strong>结合了绝对位置和相对位置编码的思想<strong>。RoPE利用一个与绝对位置相关的函数（旋转矩阵）来</strong>变换查询Q和键向量K<strong>。其精妙之处在于，经过变换后的查询和键向量进行点积运算时，其</strong>结果仅依赖于它们的相对位置**。这样，模型既利用了绝对位置信息来生成编码，又在注意力机制中实现了纯粹的相对位置依赖。</li> </ol> <h2 id="第二部分向相对位置感知的演进">第二部分：向相对位置感知的演进</h2> <p>位置编码技术的发展历程反映了研究界对模型如何最有效地利用序列信息的不断深入的理解。从最初的绝对位置方案，到更加灵活的相对位置方案，每一次演进都是为了克服前代方法的局限性。</p> <h3 id="21-绝对位置编码ape正弦函数方法">2.1 绝对位置编码（APE）：正弦函数方法</h3> <p>在最初的Transformer论文《Attention Is All You Need》中，Vaswani等人提出了一种优雅且高效的绝对位置编码方案，即正弦位置编码。该方法不依赖于学习，而是通过一个固定的数学公式生成位置向量。</p> <p>其核心公式如下：</p> \[PE_{(pos, 2i)} = \sin(\frac{pos}{10000^{2i/d_{\text{model}}}})\] \[PE_{(pos, 2i+1)} = \cos(\frac{pos}{10000^{2i/d_{\text{model}}}})\] <p>其中：</p> <ul> <li>$pos$ 是词元在序列中的绝对位置索引（从0开始）。</li> <li>$i$ 是位置编码向量中的维度索引（从0开始）。</li> <li>$d_{\text{model}}$​ 是词元嵌入和位置编码向量的总维度。</li> </ul> <p><img src="/assets/img/posts/Transformer-position-embedding1/image2.webp" alt="" class="img-fluid"/></p> <p><img src="/assets/img/posts/Transformer-position-embedding1/image3.png" alt="" class="img-fluid"/></p> <p>这个公式的设计蕴含了深刻的考量。首先，通过<strong>交替使用正弦和余弦函数</strong>，并为每个维度对（$2i$ 和 $2i+1$）分配一个不同的波长（频率），它为每个位置 $pos$ 生成了一个唯一的 $d_{\text{model}}$ 维向量。这些波长的变化范围从短到长：对于维度索引 $i$ 较小的<strong>低维部分</strong>（例如，$i=0,1,2…$，即编码向量的起始部分），分母中的指数项接近0，使得频率很大（接近1），对应的波长很短，函数值变化迅速。这种快速的变化为模型提供了非常精确的、关于<strong>相邻词元</strong>之间差异的信号。模型可以轻易地分辨出“这是第3个词”和“这是第4个词”；对于<strong>高维部分</strong>（例如，$i$接近$d_{model}/2$，即编码向量的末尾部分），频率则变得非常小，对应波长较大，那么函数值会随着$pos$的增加而变得非常缓慢，只有当$pos$的值发生巨大变化时（例如，从$pos=5$到$pos=500$），编码值才会有明显的不同，从而使模型把握到全局信息。这种多尺度的频率组合使得模型能够同时捕捉到粗粒度和细粒度的位置信息。</p> <p><img src="/assets/img/posts/Transformer-position-embedding1/image4.jpg" alt="" class="img-fluid"/></p> <p>其次，这种基于正弦函数的设计有一个重要的特性：对于任意固定的偏移量 $k$，位置 $pos+k$ 的位置编码 $PE_{(pos+k)}$ 可以表示为 $PE_{(pos)}$ 的线性函数。这一特性使得模型能够更容易地学习到<strong>相对位置关系</strong>。模型可以通过注意力机制学习到如何关注相距特定距离的词元，因为它们的<strong>位置编码之间存在固定的线性变换关系</strong>。</p> <p>最后，一个常被引用的优点是，这种确定性的公式使得模型理论上能够外推到比训练时遇到的更长的序列长度。因为即使对于未见过的位置 $pos$，我们依然可以计算出其对应的位置编码向量（泛化能力更强）。生成的位置编码向量会与词元的语义嵌入向量逐元素相加，形成最终的输入表示，然后被送入Transformer的后续层。</p> <p><img src="/assets/img/posts/Transformer-position-embedding1/image5.png" alt="" class="img-fluid"/></p> <h3 id="22-相对位置编码rpe的兴起">2.2 相对位置编码（RPE）的兴起</h3> <p>尽管正弦绝对位置编码在实践中表现良好，但它也存在一些理论上的局限性。例如，虽然它允许模型学习相对关系，但这种关系是间接的。此外，对于非常长的序列，其外推能力的鲁棒性也受到质疑。为了更直接、更灵活地建模词元间的相对关系，相对位置编码（RPE）应运而生。</p> <p>RPE的核心思想是，词元之间的注意力强度不应取决于它们的绝对位置，而应取决于它们之间的相对距离。例如，在句子中相距3个词元的两个词，无论它们出现在句首还是句末，它们之间的关系模式都可能具有共性。</p> <p>与APE在输入层修改嵌入向量不同，RPE通常在自注意力机制的内部发挥作用。一种常见且有影响力的方法（如T5模型中所使用的）是，在计算注意力分数时，直接向查询-键（Query-Key）点积结果中添加一个可学习的偏置项（bias）。这个偏置项的值取决于查询和键之间的相对距离 $j-i$。</p> <p>具体来说，注意力分数的计算可以修改为：</p> \[e_{ij} = \frac{(x_i W_Q)(x_j W_K)^T + b_{j-i}}{\sqrt{d_k}}\] <p>其中，$x_i W_Q$ 是查询向量，$x_j W_K$ 是键向量，$b_{j-i}$ 是一个与相对距离 $j-i$ 对应的可学习标量偏置。通过为每个可能的相对距离（例如，-k到+k）学习一个独立的偏置值，模型可以直接建模相对位置对注意力强度的影响。这种方式使得模型对序列长度的变化更加鲁棒，并且能够显式地捕捉到词元间的成对关系。</p> <h3 id="23-对比分析ape与rpe的优势与局限">2.3 对比分析：APE与RPE的优势与局限</h3> <p>APE和RPE代表了两种不同的哲学思想，它们的演进为RoPE的出现奠定了基础。这场演进的背后，是模型设计中计算效率与表示能力之间根本性的张力，尤其是在“高效注意力”机制兴起的背景下，这一矛盾变得尤为突出。</p> <p>APE，特别是正弦编码，其实现非常简单且计算高效。位置编码向量可以预先计算并存储，然后在模型前向传播的开始阶段与词元嵌入相加。这个过程是“可分离的”，意味着它在注意力层之外完成，并且每个词元的位置编码是独立计算的。这种特性使其与任何类型的注意力机制都能无缝兼容。然而，其主要缺点在于对相对位置的建模是间接的，并且在面对远超训练长度的序列时，其泛化能力可能会下降。</p> <p>RPE通过直接修改注意力分数，为模型提供了更强大的、关于词元间相对距离的归纳偏置。这使得它在处理可变长度序列和捕捉局部上下文方面表现出色。然而，这种方法的实现方式带来了新的挑战。特别是，像T5风格的偏置方法，需要在计算注意力时访问一个依赖于相对位置的偏置矩阵，这与标准注意力机制的 $O(L^2 \cdot d)$ 复杂度和内存占用是相容的。</p> <p>然而，随着模型规模和序列长度的不断增长，标准注意力机制的二次方复杂度成为一个巨大的瓶颈。为了解决这个问题，研究界开发了多种“高效注意力”或“线性注意力”方法（例如，基于核函数的方法，如Performer）。这些方法的核心思想是通过数学变换来避免显式地计算和存储完整的 $N \times N$ 注意力矩阵。</p> <p>这就产生了一个深刻的架构冲突：RPE需要修改一个我们正极力避免去计算的注意力矩阵。如何为一个不存在的矩阵添加相对位置偏置？这个难题揭示了一个深层次的架构约束。社区迫切需要一种新的位置编码方法，它既能提供RPE的相对位置建模优势（如灵活性和泛化能力），又能保持APE的计算可分离性，从而与新兴的线性注意力架构兼容。</p> <p>旋转位置编码（RoPE）正是对这一需求的直接回应。它通过在计算点积之前独立地变换查询和键向量，巧妙地将相对位置信息编码进去。这种“预处理”的方式是可分离的，因此完美地解决了上述架构冲突，统一了相对编码的强大能力和线性注意力的计算效率。</p> <p>下表系统地总结了这几种主流位置编码方法的特点，突显了驱动技术向RoPE演进的核心动因。</p> <table> <thead> <tr> <th><strong>方法论</strong></th> <th><strong>机制</strong></th> <th><strong>位置类型</strong></th> <th><strong>长度外推能力</strong></th> <th><strong>与线性注意力兼容性</strong></th> </tr> </thead> <tbody> <tr> <td><strong>绝对位置编码 (APE)</strong></td> <td>将位置向量<strong>加</strong>到词元嵌入上</td> <td>绝对位置</td> <td>理论上可行，但鲁棒性有限</td> <td>良好</td> </tr> <tr> <td><strong>相对位置编码 (RPE)</strong></td> <td>将位置偏置<strong>加</strong>到注意力分数上</td> <td>相对位置</td> <td>良好</td> <td>差（不兼容）</td> </tr> <tr> <td><strong>旋转位置编码 (RoPE)</strong></td> <td>将词元嵌入（Q/K）与位置向量<strong>相乘</strong>（旋转）</td> <td>绝对位置编码，实现相对位置依赖</td> <td>优秀</td> <td>良好</td> </tr> </tbody> </table> <h2 id="第三部分通往旋转位置编码之路">第三部分：通往旋转位置编码之路</h2> <p>至此，我们已经完整地回顾了位置编码技术演进的脉络。我们从Transformer架构最根本的需求——克服“置换不变性”——出发，了解了最初的绝对位置编码（APE）如何通过巧妙的正弦函数设计，为模型注入了顺序感。随后，我们看到了相对位置编码（RPE）的兴起，它将关注点从“绝对位置”转向了更灵活的“相对距离”，为模型提供了更强的归纳偏置。</p> <p><img src="/assets/img/posts/Transformer-position-embedding1/image6.jpg" alt="" class="img-fluid"/></p> <p>然而，正如我们的对比分析所揭示的，这场演进也带来了一个深刻的架构矛盾：随着模型对计算效率的要求越来越高，尤其是线性注意力机制的出现，旨在修改注意力矩阵的RPE方案变得难以兼容。一个核心问题摆在了研究者面前：<strong>我们能否创造出一种既拥有RPE相对位置建模的强大能力，又具备APE计算上的高效与分离特性的位置编码方法？</strong></p> <p>这个问题的答案，正是我们下一期将要深入探讨的主角——<strong>旋转位置编码（RoPE）</strong>。</p> <p>在第二期中，我们将彻底解构RoPE的迷人之处：</p> <ul> <li><strong>核心思想揭秘</strong>：它究竟是如何通过“旋转”而非“相加”来编码位置的？</li> <li><strong>数学原理剖析</strong>：我们将深入其背后的数学公式，直观地理解它如何利用绝对位置实现相对位置的感知。</li> <li><strong>关键优势解读</strong>：为什么RoPE能在序列长度外推和捕捉远程依赖方面表现如此卓越？</li> <li><strong>前沿应用追踪</strong>：我们将一探究竟，看看像Llama 3和Qwen3-VL这样的顶尖模型是如何应用并优化RoPE，以解决更复杂的多模态任务的。</li> </ul>]]></content><author><name></name></author><category term="AI"/><category term="Transformer"/><summary type="html"><![CDATA[从自注意力的置换不变性出发，梳理绝对、相对与旋转位置编码的基本思路。]]></summary></entry></feed>