v0.94: 同步HTML

This commit is contained in:
2026-08-26 06:50:59 +00:00
parent 66e50d2e7e
commit d5a46280df

View File

@@ -344,58 +344,35 @@ $$</div>
</ul> </ul>
<p>max 取更严格的 8192。修正后的归约阈值θ_c≈12grid_K=32 时 K&gt;396远低于 8192说明 <b>8192 的绑定约束是 dValue条件 2不是归约代价条件 3</b>。源码不动态计算 grid_K用固定阈值同时覆盖条件 2 的最保守情形和条件 3是两条条件的保守合并近似。</p> <p>max 取更严格的 8192。修正后的归约阈值θ_c≈12grid_K=32 时 K&gt;396远低于 8192说明 <b>8192 的绑定约束是 dValue条件 2不是归约代价条件 3</b>。源码不动态计算 grid_K用固定阈值同时覆盖条件 2 的最保守情形和条件 3是两条条件的保守合并近似。</p>
<h3>实现方案</h3> <h3>实现方案</h3>
<p><b>Step 0singleCoreM / singleCoreN 的确定</b>(每核输出基本块尺寸)</p> <p><b>Step 0SingleCoreM / SingleCoreN 的确定</b>(每核输出 tile 尺寸)</p>
<p>singleCoreM × singleCoreN 是 ASW_Basic 的基石参数——它决定了每核每次计算的输出 tile 大小,进而决定 mCnt/nCnt、swizzle 窗口、L2 执行组等所有后续参数。确定逻辑按约束链推导</p> <p>SingleCoreM × SingleCoreN 是每核每次处理的输出区域。<b>它不受 L0 容量直接约束</b>——L0 容量约束的是 BaseM/BaseN/BaseKL0 级 tile见 Step 5SingleCoreM/N 在 BaseM/N 之上,一个 [SingleCoreM, SingleCoreN] tile 内部由多个 [BaseM, BaseN] L0 tile 组成。SingleCoreM/N 的核心影响是 <b>GM→L1 搬移效率和 L2 重复读率</b></p>
<p>*约束 1——L0C 容量*(输出 tile 必须放得下 L0C 双缓冲):</p> <ul class="tight">
<li>SingleCoreM/N 越大 → 每次 GM→L1 搬移的数据量越大dValue 越有保障,搬移效率越高;同时 L2 中同一份 A 行带/B 列带被更多核复用,重复读率越低</li>
<li>SingleCoreM/N 越小 → 总块数 mCnt×nCnt 越多核间并行度越高但单次搬移效率降低L2 重复读率升高</li>
</ul>
<p>*约束链*</p>
<p><b>约束 1——并行度下限</b>:总块数须填满 C 核。</p>
<div class="math">$$ <div class="math">$$
\text{singleCoreM} \times \text{singleCoreN} \times 4\text{B} \times 2 \le L0C \Rightarrow \text{singleCoreM} \times \text{singleCoreN} \le 32768 \text{ 元素} mCnt \times nCnt \ge \Big\lceil \frac{C}{B} \Big\rceil \Rightarrow \frac{M}{\text{singleCoreM}} \times \frac{N}{\text{singleCoreN}} \ge \Big\lceil \frac{C}{B} \Big\rceil
$$</div> $$</div>
<p>*约束 2——L0A/L0B 容量*(输入 tile 决定 baseK 上限</p> <p><b>约束 2——L1 容量</b>(双缓冲下驻留当前 tile 的输入</p>
<div class="math">$$
baseK \le \min\Big(\frac{L0A}{2 \cdot \text{singleCoreM} \cdot \text{dtype}},\; \frac{L0B}{2 \cdot \text{singleCoreN} \cdot \text{dtype}}\Big)
$$</div>
<p>*约束 3——dValue*$baseK \cdot \text{dtype} \ge 256\text{B}$BF16 为 128 元素)。</p>
<p>*约束 4——L1 容量*(双缓冲下驻留输入):</p>
<div class="math">$$ <div class="math">$$
2 \cdot (\text{singleCoreM} + \text{singleCoreN}) \cdot k_{L1} \cdot \text{dtype} \le L1 2 \cdot (\text{singleCoreM} + \text{singleCoreN}) \cdot k_{L1} \cdot \text{dtype} \le L1
$$</div> $$</div>
<p>*约束 5——搬移效率*$\text{singleCoreM} \cdot K \cdot \text{dtype} \ge min\_TileSize$ 且 $K \cdot \text{singleCoreN} \cdot \text{dtype} \ge min\_TileSize$。</p> <p>其中 $k_{L1}$ 是 GM→L1 的 K 向粒度,须满足 dValue$k_{L1} \cdot \text{dtype} \ge 256\text{B}$。</p>
<p>*选取策略*:在约束 1 的上界32768 元素singleCoreM/singleCoreN 的长宽比应<b>跟随 M/N 的长宽比</b>——$\text{singleCoreM}/\text{singleCoreN} \approx M/N$,使 GM 访问的空间局部性最优(减少跨行/跨列的 strided 访问)。同时对齐到 16 的倍数Cube 基本块粒度)。</p> <p><b>约束 3——搬移效率</b>:单次 GM→L1 搬移量须达到 min_TileSize</p>
<p>*例*M=N=2048方形 → singleCoreM=singleCoreN=$\lfloor\sqrt{32768}\rfloor_{16}$=176。约束 2$baseK \le 16384/176 = 93$ → 取 8016 对齐)。约束 3$80 \times 2 = 160\text{B} \ge 128\text{B}$ ✓。</p> <div class="math">$$
<p>*例*M=4096、N=512长条 → singleCoreM=256、singleCoreN=128$256 \times 128 = 32768$ 恰好满载 L0C/2。约束 2$baseK \le \min(16384/256, 16384/128) = \min(64, 128) = 64$。</p> \text{singleCoreM} \cdot k_{L1} \cdot \text{dtype} \ge min\_TileSize,\qquad k_{L1} \cdot \text{singleCoreN} \cdot \text{dtype} \ge min\_TileSize
$$</div>
<p><b>选取策略</b></p>
<p>在约束 1并行度下限和约束 2/3搬移效率之间取平衡。SingleCoreM/N 的长宽比应<b>跟随 M/N 的长宽比</b>$\text{singleCoreM}/\text{singleCoreN} \approx M/N$),使 GM 访问的空间局部性最优。对齐到 16 的倍数Cube 基本块粒度)。</p>
<p>*例*B=8、M=N=2048、K=1024、BF16$\lceil C/B \rceil = 4$,需 $mCnt \times nCnt \ge 4$。取 $mCnt = nCnt = 2$ → singleCoreM = singleCoreN = 1024。约束 2$k_{L1} \le 512\text{KB}/(2 \times 2048 \times 2\text{B}) = 64$ 元素 = 128B恰好满足 dValue 下限。约束 3$1024 \times 64 \times 2 = 128\text{KB} \ge 16\text{KB}$ ✓。</p>
<p>*例*B=2、M=N=4096、K=512、BF16$\lceil C/B \rceil = 16$,需 $mCnt \times nCnt \ge 16$。取 $mCnt = nCnt = 4$ → singleCoreM = singleCoreN = 1024。$k_{L1}$ 同上 = 64 元素。</p>
<p><b>Step 1mCnt / nCnt 与核间分配</b></p> <p><b>Step 1mCnt / nCnt 与核间分配</b></p>
<div class="math">$$ <div class="math">$$
mCnt = \Big\lceil \frac{M}{\text{singleCoreM}} \Big\rceil,\qquad nCnt = \Big\lceil \frac{N}{\text{singleCoreN}} \Big\rceil mCnt = \Big\lceil \frac{M}{\text{singleCoreM}} \Big\rceil,\qquad nCnt = \Big\lceil \frac{N}{\text{singleCoreN}} \Big\rceil
$$</div> $$</div>
<p>总输出块数 = $B \times mCnt \times nCnt$,按 B→M→N 优先级分配到 C 核。</p> <p>总输出块数 = $B \times mCnt \times nCnt$,按 B→M→N 优先级分配到 C 核。</p>
<p><b>核间组织</b>:先按 B/M/N 切出输出块,剩余核预算折成 K 向份数:</p>
<div class="math">$$
blocksPerBatch = \Big\lfloor \frac{C}{B} \Big\rfloor,\qquad
grid_K = \frac{blocksPerBatch}{mCnt \cdot nCnt}
$$</div>
<p>mCnt、nCnt 收拢为 blocksPerBatch 的因子(避免碎核尾块);由条件 1 知 $mCnt \cdot nCnt \le blocksPerBatch/2$,故 $grid_K \ge 2$。归约组内核 c 负责 K 段 $[cK/grid_K,\; (c{+}1)K/grid_K)$。</p>
<p><b>核内流水</b>:对自己的 K 段做标准分块流水MTE2→L1→L0→mmad段内多轮在 L0C 原地累加;段完部分和经 Fixpipe 写出。</p>
<p><b>归约</b></p>
<ul class="tight">
<li><b>workspace + AIV 归约(确定性)</b>:部分和写 workspace每核 256×256×4B另加 20MB 核间通信区),<b>workspace 优先驻留 L2</b>——归约读写走 5.2TB/s 的 L2 口而非 GMAIV 从 L2 读回各段部分和、在 UB 内求和后写回(数据流 GM/L2→UB→AIV→UB→L2/GMAIC:AIV=1:2</li>
<li><b>AtomicAdd非确定性</b>:部分和直接原子累加到输出 GM省一遍读回确定性等级 &gt;1 禁用。</li>
</ul>
<p><b>参数搜索</b>$grid_K$ 从 2 起按 2 的幂递增,取同时满足条件 2/3 的最小值;都不满足则退为降核 ASW_Basic。</p>
<hr>
<h2>八、ASW_Basic 分支</h2>
<h3>进入分支条件(汇总)</h3>
<ol class="tight">
<li>$P = \dfrac{B \cdot MN \cdot 4\text{B}}{L0C} \ge C$</li>
<li>无 batch 结构限制BatchA=BatchB、交叉广播均可典型进入路径$B &lt; C$(切 B 买不满核),或 $B \ge C$ 但 IterBatch/MergeBatch 条件不满足时的兜底</li>
<li><b>降核模式</b>$P &lt; C$ 且不满足 StreamK 进入条件 → 只用 $\lceil P \rceil$ 个核,其余核闲置</li>
</ol>
<h3>逐条解释</h3>
<ol class="tight">
<li><b>并行度补齐</b>:以 L0C 满载为基本块粒度B×M×N 能切出至少 C 个独立输出块,则切 M/N或混合切并行度够用。切 M/N 的固有代价是共享矩阵被多核重复读,但共享部分驻留 128MB L2 时重复读以 5.2TB/s 命中 L2 而非 1.6TB/s 的 GM代价大部分被吸收。</li>
<li><b>兜底性质</b>ASW_Basic 是实践中最常命中的分支——B 可大可小可等 1交叉广播也由此承接对广播侧做 L1/L2 驻留,共享关系与切 M/N 同构)。</li>
<li><b>降核模式</b>P &lt; C 且 K 也不够格走 StreamK 时,并行度凑不满核。此时与其强行把 M/N 切得更碎tile 跌破 min_TileSize、dValue 跌破 128B搬移效率崩塌反而更慢不如<b>只用 ⌈P⌉ 个核</b>、每核承担一个完整输出块L0C 满载粒度),其余核闲置。这类 case 的时延绝对值小,继续切分引入的调度与搬移效率损失大于并行收益——降核是理性选择而非偷懒。</li>
</ol>
<h3>实现方案</h3>
<p><b>Step 2核间切分维度选择按共享代价从低到高</b>:切 B零共享先试→ 切 M右矩阵 $KN\cdot\text{dtype} \le L2$ 则驻留 L2→ 切 N对称→ 混合切(靠 swizzle + L2 切分管理)→ 降核(见 Step 7</p> <p><b>Step 2核间切分维度选择按共享代价从低到高</b>:切 B零共享先试→ 切 M右矩阵 $KN\cdot\text{dtype} \le L2$ 则驻留 L2→ 切 N对称→ 混合切(靠 swizzle + L2 切分管理)→ 降核(见 Step 7</p>
<p><b>Step 3swizzle——ASW 滑窗蛇形</b></p> <p><b>Step 3swizzle——ASW 滑窗蛇形</b></p>
<p><b>问题</b>:核间切 M/N 后,同一时刻 C 个核各算一个输出块,它们所需的 A 行块与 B 列块集合就是当前"活跃工作集"。若按行优先顺序朴素分配,一波 C 个块横跨的 A 行、B 列很宽,活跃工作集超过 L2 就回 GM 读1.6TB/s重复读代价真实发生。<b>swizzle 要做的就是编排输出块的执行顺序,把每一波核的活跃工作集压到最小。</b></p> <p><b>问题</b>:核间切 M/N 后,同一时刻 C 个核各算一个输出块,它们所需的 A 行块与 B 列块集合就是当前"活跃工作集"。若按行优先顺序朴素分配,一波 C 个块横跨的 A 行、B 列很宽,活跃工作集超过 L2 就回 GM 读1.6TB/s重复读代价真实发生。<b>swizzle 要做的就是编排输出块的执行顺序,把每一波核的活跃工作集压到最小。</b></p>
@@ -490,9 +467,9 @@ transConflict = \max\big(\lceil C / mCnt \rceil,\; \lceil C / nCnt \rceil\big) \
$$</div> $$</div>
<p>即同一时刻并发核访问同一 A/B 块的最大冲突数不超过阈值(经验值 6切分方案中优先选尾波不满载占比小拖尾 &lt; 一半)的。遍历大方向由 calOrder 决定0=M 优先、1=N 优先),按形状选共享矩阵更能驻留 L2 的方向。</p> <p>即同一时刻并发核访问同一 A/B 块的最大冲突数不超过阈值(经验值 6切分方案中优先选尾波不满载占比小拖尾 &lt; 一半)的。遍历大方向由 calOrder 决定0=M 优先、1=N 优先),按形状选共享矩阵更能驻留 L2 的方向。</p>
<p>补充:若输出会被后续算子立即消费(融合场景),输出驻留 L2 让下游读命中,场景 B/C 的策略反过来;本文按单算子边界分析。</p> <p>补充:若输出会被后续算子立即消费(融合场景),输出驻留 L2 让下游读命中,场景 B/C 的策略反过来;本文按单算子边界分析。</p>
<p><b>Step 5核内 tiling</b>$\text{singleCoreM} \times \text{singleCoreN} \times 4\text{B} \times DB \le L0C$$\text{singleCoreM} \times k_{L0} \times \text{dtype} \times 2 \le L0A$、$k_{L0} \times \text{singleCoreN} \times \text{dtype} \times 2 \le L0B$;内轴按 dValue 256B/512B 对齐L1 按容量开双缓冲,余量充足开 4 buffer。</p> <p><b>Step 5核内 tiling</b>BaseM/BaseN/BaseK——L0 级 tile受 L0 容量直接约束):$\text{BaseM} \times \text{BaseN} \times 4\text{B} \times DB \le L0C$$\text{BaseM} \times k_{L0} \times \text{dtype} \times 2 \le L0A$、$k_{L0} \times \text{BaseN} \times \text{dtype} \times 2 \le L0B$;内轴按 dValue 256B/512B 对齐。SingleCoreM/N 内部按 BaseM/BaseN 进一步切分为 L0 tile 逐个计算。L1 按容量开双缓冲,余量充足开 4 buffer。</p>
<p><b>Step 6内部特化参数极限不是独立分支</b>:单边无 batch 且该侧矩阵小($M \le 256$、$MK\cdot\text{dtype}\cdot 2 \le L1$、对侧每核循环 ≥4 轮)时小侧整个常驻 L1、只搬一次L1 全载)。</p> <p><b>Step 6内部特化参数极限不是独立分支</b>:单边无 batch 且该侧矩阵小($M \le 256$、$MK\cdot\text{dtype}\cdot 2 \le L1$、对侧每核循环 ≥4 轮)时小侧整个常驻 L1、只搬一次L1 全载)。</p>
<p><b>Step 7降核模式实现</b>tiling 时 <code>usedCoreNum = ⌈P⌉</code>(不强制 C基本块在 L0C 容量内取最大($M^t N^t \cdot 4\text{B} \le L0C$每核按标准核内流水L1→L0→Cube→L0C→Fixpipe处理自己的输出块核间无共享无依赖无需 swizzle 与 L2 切分。降核后 GM 并发搬移核数若 &lt; minCoreNum带宽利用率上限被压低——这正是降核区 case 时延的瓶颈所在,也是"时延绝对值小、不再继续优化"的定量注脚。</p> <p><b>Step 7降核模式实现</b>tiling 时 <code>usedCoreNum = ⌈P⌉</code>(不强制 CSingleCoreM/N 在 L0C 容量内取最大($\text{singleCoreM} \times \text{singleCoreN} \times 4\text{B} \le L0C$每核按标准核内流水L1→L0→Cube→L0C→Fixpipe处理自己的输出块核间无共享无依赖无需 swizzle 与 L2 切分。降核后 GM 并发搬移核数若 &lt; minCoreNum带宽利用率上限被压低——这正是降核区 case 时延的瓶颈所在,也是"时延绝对值小、不再继续优化"的定量注脚。</p>
<hr> <hr>
<h2>九、特殊分支</h2> <h2>九、特殊分支</h2>
<ul class="tight"> <ul class="tight">