v1.1: 同步HTML

This commit is contained in:
2026-08-27 03:32:32 +00:00
parent 2fd7751c05
commit c5f9fe299b

View File

@@ -183,11 +183,25 @@ $$</div>
<hr> <hr>
<h2>六、实现方案</h2> <h2>六、实现方案</h2>
<h3>Step 0BaseM / BaseN 的确定L0 级 tile先把 L0C 用满)</h3> <h3>Step 0BaseM / BaseN 的确定L0 级 tile先把 L0C 用满)</h3>
<p>L0C 是 Cube 的累加器BaseM × BaseN 是每次 Cube 计算的输出 tile。BaseM/N 应<b>尽量把 L0C 用满</b>——L0C 利用率越高,每次 Cube 计算的输出越大,单位计算的启动/排空开销摊得越薄</p> <p>L0C 是 Cube 的累加器BaseM × BaseN 是每次 Cube 计算的输出 tile。BaseM/N 应<b>尽量把 L0C 用满</b>——L0C 利用率越高,每次 Cube 计算的输出越大,单位计算的启动/排空开销摊得越薄</p>
<p><b>L0C 双缓冲 vs UnitFlag 单缓冲</b></p>
<p>传统做法用 L0C 双缓冲实现 tile 间流水——计算 tile N+1 时fixpipe 同时写出 tile N</p>
<div class="math">$$ <div class="math">$$
\text{BaseM} \times \text{BaseN} = \frac{L0C}{2 \times 4\text{B}} = 32768 \text{ 元素} \text{BaseM} \times \text{BaseN} = \frac{L0C}{2 \times 4\text{B}} = 32768 \text{ 元素(双缓冲)}
$$</div> $$</div>
<p>双缓冲两份FP32 4B/元素。BaseM/BaseN 的长宽比跟随 SingleCoreM/SingleCoreN进而跟随 M/N对齐 16 的倍数。baseK 由 L0A/L0B 容量决定L1→L0 搬移无 dValue 要求dValue 约束的是 GM→L1 的 $k_{L1}$</p> <p>但昇腾 950PR 的 Fixpipe 支持 <b>UnitFlag</b>——MMAD 每完成一个 16×16×16 基本块512B 结果Fixpipe 立即将其写出,无需等整个 L0C tile 算完。UnitFlag 提供的是 <b>tile 内部的细粒度流水</b>16×16×16 粒度),替代双缓冲的 <b>tile 间粗粒度流水</b>BaseM×BaseN 粒度)。</p>
<p>UnitFlag 单缓冲下L0C 只需一份 buffer</p>
<div class="math">$$
\text{BaseM} \times \text{BaseN} = \frac{L0C}{4\text{B}} = 65536 \text{ 元素(单缓冲)}
$$</div>
<p>BaseM/N 可放大 $\sqrt{2}$ 倍(如 256→362mCnt/nCnt 相应减小,<b>L2 重复读率降低</b>(单 batch 块数减少 → 每行 A 被更少的组读取)。</p>
<p>*时延对比*(单 tile 粒度BF16 输出):</p>
<table><tr><th>方案</th><th>tile 大小</th><th>tile 间流水</th><th>tile 内流水</th><th>单 tile 时延</th></tr>
<tr><td>双缓冲</td><td>181×18132761 元素)</td><td>tile N 写出 ∥ tile N+1 计算)</td><td></td><td>max($T_{comp}$, $T_{write}$)</td></tr>
<tr><td>UnitFlag 单缓冲</td><td>256×25665536 元素)</td><td></td><td>16×16×16 粒度)</td><td>max($T_{comp}$, $T_{write}$)</td></tr></table>
<p>两种方案的稳态时延相同(都是 max($T_{comp}$, $T_{write}$)),但 UnitFlag 单缓冲的 tile 更大 → 总 tile 数更少 → 循环开销更小。<b>但当前 BMM ASW kernel 未启用 UnitFlag</b><code>unitFlag = 0</code>,注释 "each l0 only process one block, disable unit flag"),且源码在 baseM=baseN=256 时已自动选 dbL0C=1256×256×4B×2 &gt; L0C——即<b>源码已经是单缓冲 + 无 UnitFlag</b>tile 到顶但无流水交叠。</p>
<p>*建议*:对计算 Bound 的 case 启用 UnitFlagMMAD 与 Fixpipe 流水并行),可将单 tile 时延从 $T_{comp} + T_{write}$ 降至 $\max(T_{comp}, T_{write})$。对访存 Bound 的 caseMTE2 BoundUnitFlag 收益小([CANN 文档](https://www.hiascend.com/document/detail/zh/CANNCommunityEdition/920beta1/API/ascendcopapi/atlasascendc_api_07_0003.html)MTE2 Bound 时 MMAD/FIX 流水可被搬移掩盖)。</p>
<p>BaseM/BaseN 的长宽比跟随 SingleCoreM/SingleCoreN进而跟随 M/N对齐 16 的倍数。baseK 由 L0A/L0B 容量决定L1→L0 搬移无 dValue 要求dValue 约束的是 GM→L1 的 $k_{L1}$</p>
<div class="math">$$ <div class="math">$$
baseK = \min\Big(\frac{L0A}{2 \cdot \text{BaseM} \cdot \text{dtype}},\; \frac{L0B}{2 \cdot \text{BaseN} \cdot \text{dtype}}\Big) \text{ 向下 16 对齐} baseK = \min\Big(\frac{L0A}{2 \cdot \text{BaseM} \cdot \text{dtype}},\; \frac{L0B}{2 \cdot \text{BaseN} \cdot \text{dtype}}\Big) \text{ 向下 16 对齐}
$$</div> $$</div>
@@ -346,7 +360,9 @@ $$</div>
cubeBoundEdge = \frac{l2BW}{computePower} + l2CacheUsage \cdot \Big(1 - \frac{l2BW}{hbmBW}\Big) \cdot cmr - \frac{1 + l2BW/hbmBW}{kValue} cubeBoundEdge = \frac{l2BW}{computePower} + l2CacheUsage \cdot \Big(1 - \frac{l2BW}{hbmBW}\Big) \cdot cmr - \frac{1 + l2BW/hbmBW}{kValue}
$$</div> $$</div>
<p>三项含义:① L2 供数速率 ÷ Cube 耗数速率(理论阈值);② 工作集超 L2 时的访存惩罚(抬高 edge倾向更大 tile③ K 向复用修正K 越大 edge 越小,偏 compute bound。乘以 CUBE_BOUND_RATIO=0.85 余量。枚举 baseM/baseN 递减balanceRate ≥ 0.9 剪枝。</p> <p>三项含义:① L2 供数速率 ÷ Cube 耗数速率(理论阈值);② 工作集超 L2 时的访存惩罚(抬高 edge倾向更大 tile③ K 向复用修正K 越大 edge 越小,偏 compute bound。乘以 CUBE_BOUND_RATIO=0.85 余量。枚举 baseM/baseN 递减balanceRate ≥ 0.9 剪枝。</p>
<p><b>差异分析</b>:理论直接取 L0C 满载32768 元素),源码用 256×256=65536 元素——<b>源码的 baseM×baseN 是理论上限的 2 倍</b>。这说明源码的 baseM/baseN 不是 L0C 级 tile 尺寸,而是 SingleCoreM/N 级参数。源码中 L0 级 tile 由 stepM/stepN 二次切分决定per-core tile = baseM × stepM。理论的分层SingleCoreM ≥ BaseM在源码中无显式概念</p> <p><b>差异分析</b>:理论(修正前)按双缓冲取 L0C 满载的一半32768 元素),源码用 256×256=65536 元素——<b>源码的 baseM×baseN 恰好等于 L0C 单缓冲上限</b>256×256×4B = 256KB = L0C。源码的 dbL0C 逻辑:<code>dbL0C = (baseM × baseN × 4B × 2 &gt; L0C) ? 1 : 2</code>——baseM=baseN=256 时 512KB &gt; 256KB自动选 dbL0C=1单缓冲</p>
<p>这说明源码的 baseM/baseN 不是 L0 级 tile 尺寸,而是 SingleCoreM/N 级参数。源码中 L0 级 tile 由 stepM/stepN 二次切分决定per-core tile = baseM × stepM。理论的分层SingleCoreM ≥ BaseM在源码中无显式概念。</p>
<p><b>UnitFlag 现状</b>BMM ASW kernel 中 <code>unitFlag = 0</code><code>block_mmad_iterbatch.h</code> L315 注释:"each l0 only process one block, disable unit flag"——MMAD 与 Fixpipe 之间是<b>指令级同步</b>(整个 L0C tile 算完才写出)。若启用 UnitFlagMMAD 每完成一个 16×16×16 块512BFixpipe 立即写出——tile 内部细粒度流水替代 tile 间粗粒度流水,单缓冲即可达到双缓冲的流水效果。对计算 Bound 的 caseUnitFlag 可将单 tile 时延从 $T_{comp} + T_{write}$ 降至 $\max(T_{comp}, T_{write})$。</p>
<h3>7.3 SingleCoreM / SingleCoreN 确定Step 1</h3> <h3>7.3 SingleCoreM / SingleCoreN 确定Step 1</h3>
<table><tr><th>维度</th><th>理论</th><th>源码</th></tr> <table><tr><th>维度</th><th>理论</th><th>源码</th></tr>
<tr><td>概念</td><td>独立于 L0由 GM→L1 效率 + L2 复用决定</td><td>无显式概念per-core tile = baseM × stepM</td></tr> <tr><td>概念</td><td>独立于 L0由 GM→L1 效率 + L2 复用决定</td><td>无显式概念per-core tile = baseM × stepM</td></tr>