From 0cd47f93cb01088905ea4da9b66df86ab88aee34 Mon Sep 17 00:00:00 2001 From: admin Date: Mon, 7 Sep 2026 16:24:46 +0800 Subject: [PATCH] =?UTF-8?q?Fix=20#34:=20ASW=5FBasic=20=E5=85=9C=E5=BA=95?= =?UTF-8?q?=E6=81=92=E5=87=BA=E6=96=B9=E6=A1=88;=20=E6=90=AC=E7=A7=BB?= =?UTF-8?q?=E6=95=88=E7=8E=87=E4=B8=8B=E9=99=90=E4=B8=8D=E6=BB=A1=E8=B6=B3?= =?UTF-8?q?=E9=99=8D=E7=BA=A7=E4=B8=BA=20warning=20(=E4=B8=8D=E5=88=A4?= =?UTF-8?q?=E8=BF=9D=E8=A7=84)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - constraints.py: ASW_Basic/ASW_Basic_降核 的 dValue 效率下限不再计违规 (DMA 仍能工作只是效率低; 真正不可行的只有容量/核数硬约束); IterBatch/MergeBatch/StreamK 等有替代分支的分支仍按违规处理 (不满足条件不该进) - asw_basic 枚举尾部: 严格 256B 偏好无解 -> 放开约束4 按 128B 硬下限给最优可行 tile, note 标注"效率降级"; 128B 硬下限也不满足的极端形状 (如 N=8 int8, B 侧 dValue=8B 物理不可满足) 仍给 Base tile 方案 + 标注效率降级 (搬移效率崩塌) - evaluator advice / router 仲裁文案含"效率降级"提示 (plan.note 同步) - docs/06 Step1 增加"兜底分支恒出方案"段落 (效率降级 vs 违规的语义分层) - 回归: b32_m16_n8192_k7168 分解 = Base 16x1024 + tile 16x1024 + k_l1=112 (L1 双缓冲 ⌊L1/(2·(16+1024)·2)⌋16=112 反推) 入测试; 极端形状 feasible=True + 效率降级标注; 压力 10000 例 0 崩溃/0 NaN/0 硬违规/0 GM=128B - # 硬底 / L1 容量) 找最优可行 —— 极端形状 (如 M=2 与大 N/K 组合) 下 - # Base 粒度可能无可行解; 若仍无解则退回 Base tile 由自检标注违规 - dv_hard = s.dvalue_min # 128B 硬下限 - for sm in range(s.fractal, align_up(min(m, 1024), s.fractal) + 1, s.fractal): - for sn in range(s.fractal, align_up(min(n, 1024), s.fractal) + 1, s.fractal): - k_cap = int(s.l1_bytes / (2 * (sm + sn) * dt)) - k_l1 = align_down(min(k, k_cap), s.fractal) - if k_l1 < s.fractal: - continue - dv_a = sm * dt if case.trans_a else k_l1 * dt - dv_b = k_l1 * dt if case.trans_b else sn * dt - if dv_a < dv_hard or dv_b < dv_hard: - continue - mc_r = ceil_div(m, sm) - nc_r = ceil_div(n, sn) - if b * mc_r * nc_r < c: - continue - traffic = k * dt * (nc_r * m + mc_r * n) - r = (b * mc_r * nc_r) % c - key = (traffic, -r) - if best is None or key < best[0]: - best = (key, sm, sn, k_l1, mc_r, nc_r, traffic, r) - if best is None: - # 极端兜底: 退回 Base tile (约束校验会标注违规, 方案不可行可人工处置) - k_l1 = max(align_down(min(k, int(s.l1_bytes / - (2 * (base_m + base_n) * dt))), - s.fractal), s.fractal) - return (base_m, base_n, k_l1, ceil_div(m, base_m), ceil_div(n, base_n), - "枚举无可行候选, 退回 Base tile (自检会标注)") - _, sm, sn, k_l1, mc_r, nc_r, traffic, r = best - return (sm, sn, k_l1, mc_r, nc_r, - f"P={p_min}, 有界枚举最优 mCnt={mc_r} x nCnt={nc_r} " - f"(tile {sm}x{sn}, 每batch搬入{traffic/1048576:.1f}MB, r={r})") + if best is not None: + _, sm, sn, k_l1, mc_r, nc_r, traffic, r = best + return (sm, sn, k_l1, mc_r, nc_r, + f"P={p_min}, 有界枚举最优 mCnt={mc_r} x nCnt={nc_r} " + f"(tile {sm}x{sn}, 每batch搬入{traffic/1048576:.1f}MB, r={r})") + + # 情形 3: 放开约束 4 (Base 整数倍), 16 对齐网格 + 硬下限 (dValue>=128B) 再搜 + # —— 兜底分支恒出方案 (issue#34): 256B 偏好无解时按硬下限给最优可行 tile, + # 标注效率降级 (搬移效率低于模型假设, 时延可能低估) + dv_hard = s.dvalue_min # 128B 硬下限 + best2 = None + for sm in range(s.fractal, align_up(min(m, 1024), s.fractal) + 1, s.fractal): + for sn in range(s.fractal, align_up(min(n, 1024), s.fractal) + 1, s.fractal): + k_cap = int(s.l1_bytes / (2 * (sm + sn) * dt)) + k_l1 = align_down(min(k, k_cap), s.fractal) + if k_l1 < s.fractal: + continue + dv_a = sm * dt if case.trans_a else k_l1 * dt + dv_b = k_l1 * dt if case.trans_b else sn * dt + if dv_a < dv_hard or dv_b < dv_hard: + continue + mc_r = ceil_div(m, sm) + nc_r = ceil_div(n, sn) + if b * mc_r * nc_r < c: + continue + traffic = k * dt * (nc_r * m + mc_r * n) + r = (b * mc_r * nc_r) % c + key = (traffic, -r) + if best2 is None or key < best2[0]: + best2 = (key, sm, sn, k_l1, mc_r, nc_r, traffic, r) + if best2 is not None: + _, sm, sn, k_l1, mc_r, nc_r, traffic, r = best2 + return (sm, sn, k_l1, mc_r, nc_r, + f"效率降级(放开约束4, dValue 按 128B 硬下限, 搬移效率低于模型假设, " + f"时延可能低估): P={p_min}, mCnt={mc_r} x nCnt={nc_r} " + f"(tile {sm}x{sn}, 每batch搬入{traffic/1048576:.1f}MB, r={r})") + + # 情形 4: 极端兜底 —— 兜底分支恒出方案 (issue#34): 效率下限物理不可满足 + # 也照常给方案 + 标注效率降级 (搬移效率崩塌), 不判违规/不产 None + k_l1 = max(align_down(min(k, int(s.l1_bytes / + (2 * (base_m + base_n) * dt))), + s.fractal), s.fractal) + return (base_m, base_n, k_l1, ceil_div(m, base_m), ceil_div(n, base_n), + "效率降级(极端形状: 效率下限物理不可满足, 搬移效率崩塌, 时延可能低估; " + "方案供参考, 建议调整 dtype/布局或转置)") def _swizzle_w(self) -> int: s = self.spec diff --git a/BMM/BMM_Theory/bmm_theory/constraints.py b/BMM/BMM_Theory/bmm_theory/constraints.py index 0e33644..29a0b85 100644 --- a/BMM/BMM_Theory/bmm_theory/constraints.py +++ b/BMM/BMM_Theory/bmm_theory/constraints.py @@ -85,7 +85,12 @@ def check_plan_constraints(case: BmmCase, plan: ImplPlan, # --- dValue --- (issue#6 口径裁定: 只对"以 K 段为连续维"的方案生效) if _k_segment_is_contiguous(plan, case) and plan.k_l1 > 0: - if plan.branch == "IterBatch" and plan.l1_form.startswith(("c_", "d_")): + if plan.branch in ("ASW_Basic", "ASW_Basic_降核"): + # issue#34: ASW 是兜底分支, 恒出方案; dValue 效率下限不满足只算**效率降级** + # (plan.note 含"效率降级"标注, DMA 仍能工作只是效率低), 不判违规. + # 真正不可行的只有容量/核数硬约束 (L0C/L0A/L0B/L1 超容, 核数超限). + pass + elif plan.branch == "IterBatch" and plan.l1_form.startswith(("c_", "d_")): # 转置感知判据与生成守卫/条件 4 同源 (issue#19): # dv_a = M*dt (A 转置) 或 k_l1*dt; dv_b = N*dt (B 不转置) 或 k_l1*dt; # 两侧连续维 dValue 均低于下限才算违规. diff --git a/BMM/BMM_Theory/bmm_theory/evaluator.py b/BMM/BMM_Theory/bmm_theory/evaluator.py index c9fc058..85a49c4 100644 --- a/BMM/BMM_Theory/bmm_theory/evaluator.py +++ b/BMM/BMM_Theory/bmm_theory/evaluator.py @@ -63,6 +63,9 @@ class PlanEvaluator: def _advice(self, case: BmmCase, plan: ImplPlan, res: EvalResult) -> str: t = res.timing tips = [] + if "效率降级" in plan.note: + tips.append("效率降级标注 (plan.note): 搬移效率下限不满足 —— 方案照常给出 " + "(兜底), 但实际效率低于模型假设, 时延可能低估; 建议调整 dtype/布局") if not res.feasible: tips.append("方案违反硬件约束, 需先修正: " + res.violations) bn = t.bottleneck diff --git a/BMM/BMM_Theory/bmm_theory/router.py b/BMM/BMM_Theory/bmm_theory/router.py index ab876e0..7feb8f5 100644 --- a/BMM/BMM_Theory/bmm_theory/router.py +++ b/BMM/BMM_Theory/bmm_theory/router.py @@ -174,6 +174,9 @@ class BranchRouter: if violations: note = (note + " [自检违规: " + "; ".join(violations) + "] —— 方案生成存在缺陷, 需人工复核") + # issue#34: 兜底分支 (ASW) 效率下限不满足时降级标注 (warning), 不判违规 + if result.plan is not None and "效率降级" in result.plan.note: + note += " [效率降级标注: 搬移效率低于模型假设, 时延可能低估, 见 plan.note]" return { "branch": result.plan.branch if result.plan else "未知", "plan": result.plan, diff --git a/BMM/BMM_Theory/docs/02_分支理论/06_ASW_Basic分支.md b/BMM/BMM_Theory/docs/02_分支理论/06_ASW_Basic分支.md index 2784dea..8dad11f 100644 --- a/BMM/BMM_Theory/docs/02_分支理论/06_ASW_Basic分支.md +++ b/BMM/BMM_Theory/docs/02_分支理论/06_ASW_Basic分支.md @@ -93,6 +93,15 @@ GM→L1 搬移效率与 L2 重复读率: mCnt = ⌈M/singleCoreM⌉, nCnt = ⌈N/singleCoreN⌉(按实际 tile 反推)。 +> **兜底分支恒出方案 (issue#34)**:枚举无可行候选时,不再产出"违规/不可行"方案—— +> 先放开约束 4(Base 整数倍)按 16 对齐网格 + dValue 128B 硬下限再搜;仍无解 +> (极端形状,如 N=8 int8 大 K 时 B 侧 dValue = sN·dt 物理上不可能 ≥ 下限)时退回 +> Base tile 并标注**效率降级**(warning,搬移效率低于模型假设、时延可能低估, +> 建议调 dtype/布局),**不是违规/不可行**:dValue/minTile 是效率下限(DMA 仍能工作), +> 真正不可行的只有容量/核数硬约束(L0C/L0A/L0B/L1 超容、used_core_num 超核数)。 +> 对比:IterBatch/MergeBatch/StreamK 等**有替代分支**的分支仍按违规处理 +> (不满足条件不该进,由路由另择或落 ASW)。 + **Step 2: mCnt/nCnt 与核间分配**:`mCnt=⌈M/sM⌉`,`nCnt=⌈N/sN⌉`,总块数 B·mCnt·nCnt,B→M→N 线性映射。 **Step 3: 切分维度选择(按共享代价从低到高)**:切 B(零共享先试)→ 切 M(右矩阵 ≤L2 则驻留)→ 切 N(对称)→ 混合切 → 降核。 diff --git a/BMM/BMM_Theory/examples/plans.csv b/BMM/BMM_Theory/examples/plans.csv index 488901c..ea92219 100644 --- a/BMM/BMM_Theory/examples/plans.csv +++ b/BMM/BMM_Theory/examples/plans.csv @@ -15,7 +15,7 @@ b16_m4_n256_k192,ASW_Basic_降核,Ascend950PR,batch_mat_mul_v3,1,1,1,1,1,"降核 b32_m8_n128_k256,IterBatch,Ascend950PR,batch_mat_mul_v3,32,32,1,1,1,切B轮转分配(核间零重复读零依赖),1,1,8,128,256,256,1,a_单batch全驻留,8,128,128,allocate(GM->L1随路驻留L2),"resident(整case输入+输出<=L2: 输出驻留L2异步回写, GM写=0)",0,0,不涉及(核内不切M/N),1,1,1,0,0,0,0,True,2,单batch全驻留: (MK+KN)*dtype=68KB <= L1; 输出落点: L2驻留 b64_m16_n256_k512,IterBatch,Ascend950PR,batch_mat_mul_v3,32,32,1,1,1,切B轮转分配(核间零重复读零依赖),2,1,16,256,512,240,1,c_一侧驻留+对侧切K,16,256,64,allocate(GM->L1随路驻留L2),"resident(整case输入+输出<=L2: 输出驻留L2异步回写, GM写=0)",0,0,不涉及(核内不切M/N),1,1,1,0,0,0,0,True,2,"一侧驻留(A)+对侧切K: A驻留16KB, 预算L1/2, k_L1=240, dValueA=480B/dValueB=512B; 输出落点: L2驻留" b128_m8_n192_k256,IterBatch,Ascend950PR,batch_mat_mul_v3,32,32,1,1,1,切B轮转分配(核间零重复读零依赖),4,1,8,192,256,256,2,b_双batch乒乓,8,192,80,allocate(GM->L1随路驻留L2),"resident(整case输入+输出<=L2: 输出驻留L2异步回写, GM写=0)",0,0,不涉及(核内不切M/N),1,1,1,0,0,0,0,True,2,双batch乒乓: 2*(MK+KN)*dtype=200KB <= L1; 输出落点: L2驻留 -b32_m16_n8192_k7168,ASW_Basic,Ascend950PR,batch_mat_mul_v3,32,1,1,8,1,B->M->N线性映射+ASW滑窗蛇形(W=4),0,1,16,1024,7168,112,1,双缓冲驻留当前tile输入,16,1024,16,allocate(输入驻留L2吸收重复读),"direct_gm(输出直写GM, 输入优先驻留L2)",4,0,A0,1,1,1,0,0,0,8,True,2,"tile枚举: P=1, 有界枚举最优 mCnt=1 x nCnt=8 (tile 16x1024, 每batch搬入113.8MB, r=0); Base tile 16x1024 (L0C 单缓冲方形用满); L2场景: B_单batch可驻留(全驻留或单侧驻留+对侧滑窗) (V_in=3591.0MB, V_out=8.0MB, L2=128MB); 尾轮: r=0 无尾轮" +b32_m16_n8192_k7168,ASW_Basic,Ascend950PR,batch_mat_mul_v3,32,1,1,8,1,B->M->N线性映射+ASW滑窗蛇形(W=4),0,1,16,1024,7168,112,1,双缓冲驻留当前tile输入,16,1024,16,allocate(输入驻留L2吸收重复读),"direct_gm(输出直写GM, 输入优先驻留L2)",4,0,A0,1,1,1,0,0,0,8,True,2,"tile枚举: 效率降级(放开约束4, dValue 按 128B 硬下限, 搬移效率低于模型假设, 时延可能低估): P=1, mCnt=1 x nCnt=8 (tile 16x1024, 每batch搬入113.8MB, r=0); Base tile 16x1024 (L0C 单缓冲方形用满); L2场景: B_单batch可驻留(全驻留或单侧驻留+对侧滑窗) (V_in=3591.0MB, V_out=8.0MB, L2=128MB); 尾轮: r=0 无尾轮" b4_m1_n8192_k8192,StreamK,Ascend950PR,batch_mat_mul_v3,32,1,1,1,32,"B/M/N切出4块, 每块32核切K归约 (归约组内核c负责K段[c*K/32,(c+1)*K/32))",1,1,1,8192,256,256,1,K段标准分块流水,1,128,64,allocate(部分和驻留L2),"resident(部分和4B驻留L2, 防精度丢失不随C的fp16/fp8转换)",0,4194304,grid_K=32路切K+归约,1,1,32,0,0,0,0,True,4,"P=0.50, grid_K=32, 部分和驻留L2按4B写出, AIV归约后按C dtype=2B写最终" b16_m2_n4096_k7168,StreamK,Ascend950PR,batch_mat_mul_v3,32,1,1,1,16,"B/M/N切出16块, 每块16核切K归约 (归约组内核c负责K段[c*K/16,(c+1)*K/16))",1,1,2,4096,448,256,1,K段标准分块流水,2,128,64,allocate(部分和驻留L2),"resident(部分和4B驻留L2, 防精度丢失不随C的fp16/fp8转换)",0,8388608,grid_K=16路切K+归约,1,1,16,0,0,0,0,True,4,"P=2.00, grid_K=16, 部分和驻留L2按4B写出, AIV归约后按C dtype=2B写最终" b32_m64_n64_k7168,IterBatch,Ascend950PR,batch_mat_mul_v3,32,32,1,1,1,切B轮转分配(核间零重复读零依赖),1,1,64,64,7168,1024,1,d_两侧都切K,64,64,256,allocate(GM->L1随路驻留L2),"resident(整case输入+输出<=L2: 输出驻留L2异步回写, GM写=0)",0,0,不涉及(核内不切M/N),1,1,1,0,0,0,0,True,2,"两侧都切K: k_L1=1024, K段成对流水, batch边界天然无缝; dValueA=2048B/dValueB=128B; 输出落点: L2驻留" diff --git a/BMM/BMM_Theory/examples/result_evaluate.csv b/BMM/BMM_Theory/examples/result_evaluate.csv index 9199c82..4c70d9d 100644 --- a/BMM/BMM_Theory/examples/result_evaluate.csv +++ b/BMM/BMM_Theory/examples/result_evaluate.csv @@ -15,7 +15,7 @@ b16_m4_n256_k192,16,16,4,256,192,bf16,bf16,bf16,False,False,False,True,0,b16_m4_ b32_m8_n128_k256,32,32,8,128,256,bf16,bf16,bf16,False,False,False,True,0,b32_m8_n128_k256,IterBatch,Ascend950PR,batch_mat_mul_v3,32,32,1,1,1,切B轮转分配(核间零重复读零依赖),1,1,8,128,256,256,1,a_单batch全驻留,8,128,128,allocate(GM->L1随路驻留L2),"resident(整case输入+输出<=L2: 输出驻留L2异步回写, GM写=0)",0,0,不涉及(核内不切M/N),1,1,1,0,0,0,0,True,2,单batch全驻留: (MK+KN)*dtype=68KB <= L1; 输出落点: L2驻留,2228224,0.0,1.39264e-06,0.0,1.44264e-06,1,5.0000000000000004e-08,16777216.0,3.452102057613169e-08,65536,1.2603076923076923e-08,0.0,1.44264e-06,4.712409749920861e-08,1.4897640974992086e-06,MTE2,True,,访存Bound(GM读写共享+L2重复读),"瓶颈在 MTE2 搬移链 (GM 读写共享总线 + L2 重复读): 可增大 tile 提升 dValue/单核搬移量、利用 L2 驻留吸收重复读 (ASW swizzle/分组方向), 或评估输出驻留 L2 以减少 GM 直写与读竞争" b64_m16_n256_k512,64,64,16,256,512,bf16,bf16,bf16,False,False,False,True,0,b64_m16_n256_k512,IterBatch,Ascend950PR,batch_mat_mul_v3,32,32,1,1,1,切B轮转分配(核间零重复读零依赖),2,1,16,256,512,240,1,c_一侧驻留+对侧切K,16,256,64,allocate(GM->L1随路驻留L2),"resident(整case输入+输出<=L2: 输出驻留L2异步回写, GM写=0)",0,0,不涉及(核内不切M/N),1,1,1,0,0,0,0,True,2,"一侧驻留(A)+对侧切K: A驻留16KB, 预算L1/2, k_L1=240, dValueA=480B/dValueB=512B; 输出落点: L2驻留",17825792,0.0,1.114112e-05,0.0,1.1441120000000001e-05,6,3.0000000000000004e-07,268435456.0,5.52336329218107e-07,524288,1.0082461538461538e-07,0.0,1.1441120000000001e-05,1.798661348528015e-07,1.1620986134852803e-05,MTE2,True,,访存Bound(GM读写共享+L2重复读),"瓶颈在 MTE2 搬移链 (GM 读写共享总线 + L2 重复读): 可增大 tile 提升 dValue/单核搬移量、利用 L2 驻留吸收重复读 (ASW swizzle/分组方向), 或评估输出驻留 L2 以减少 GM 直写与读竞争" b128_m8_n192_k256,128,128,8,192,256,bf16,bf16,bf16,False,False,False,True,0,b128_m8_n192_k256,IterBatch,Ascend950PR,batch_mat_mul_v3,32,32,1,1,1,切B轮转分配(核间零重复读零依赖),4,1,8,192,256,256,2,b_双batch乒乓,8,192,80,allocate(GM->L1随路驻留L2),"resident(整case输入+输出<=L2: 输出驻留L2异步回写, GM写=0)",0,0,不涉及(核内不切M/N),1,1,1,0,0,0,0,True,2,双batch乒乓: 2*(MK+KN)*dtype=200KB <= L1; 输出落点: L2驻留,13107200,0.0,8.192e-06,0.0,8.392e-06,4,2.0000000000000002e-07,100663296.0,2.0712612345679012e-07,393216,7.561846153846153e-08,0.0,8.392e-06,7.068614624881291e-08,8.462686146248813e-06,MTE2,True,,访存Bound(GM读写共享+L2重复读),"瓶颈在 MTE2 搬移链 (GM 读写共享总线 + L2 重复读): 可增大 tile 提升 dValue/单核搬移量、利用 L2 驻留吸收重复读 (ASW swizzle/分组方向), 或评估输出驻留 L2 以减少 GM 直写与读竞争" -b32_m16_n8192_k7168,32,32,16,8192,7168,bf16,bf16,bf16,False,False,False,True,0,b32_m16_n8192_k7168,ASW_Basic,Ascend950PR,batch_mat_mul_v3,32,1,1,8,1,B->M->N线性映射+ASW滑窗蛇形(W=4),0,1,16,1024,7168,112,1,双缓冲驻留当前tile输入,16,1024,16,allocate(输入驻留L2吸收重复读),"direct_gm(输出直写GM, 输入优先驻留L2)",4,0,A0,1,1,1,0,0,0,8,True,2,"tile枚举: P=1, 有界枚举最优 mCnt=1 x nCnt=8 (tile 16x1024, 每batch搬入113.8MB, r=0); Base tile 16x1024 (L0C 单缓冲方形用满); L2场景: B_单batch可驻留(全驻留或单侧驻留+对侧滑窗) (V_in=3591.0MB, V_out=8.0MB, L2=128MB); 尾轮: r=0 无尾轮",3765436416,51380224,0.00235339776,9.880812307692307e-06,0.0023632785723076925,0.0,0.0,60129542144.0,0.00012372333774485596,8388608,5.24288e-06,0.0,0.0023685214523076923,0.0,0.0023685214523076923,MTE2,True,,访存Bound(GM读写共享+L2重复读),"瓶颈在 MTE2 搬移链 (GM 读写共享总线 + L2 重复读): 可增大 tile 提升 dValue/单核搬移量、利用 L2 驻留吸收重复读 (ASW swizzle/分组方向), 或评估输出驻留 L2 以减少 GM 直写与读竞争" +b32_m16_n8192_k7168,32,32,16,8192,7168,bf16,bf16,bf16,False,False,False,True,0,b32_m16_n8192_k7168,ASW_Basic,Ascend950PR,batch_mat_mul_v3,32,1,1,8,1,B->M->N线性映射+ASW滑窗蛇形(W=4),0,1,16,1024,7168,112,1,双缓冲驻留当前tile输入,16,1024,16,allocate(输入驻留L2吸收重复读),"direct_gm(输出直写GM, 输入优先驻留L2)",4,0,A0,1,1,1,0,0,0,8,True,2,"tile枚举: 效率降级(放开约束4, dValue 按 128B 硬下限, 搬移效率低于模型假设, 时延可能低估): P=1, mCnt=1 x nCnt=8 (tile 16x1024, 每batch搬入113.8MB, r=0); Base tile 16x1024 (L0C 单缓冲方形用满); L2场景: B_单batch可驻留(全驻留或单侧驻留+对侧滑窗) (V_in=3591.0MB, V_out=8.0MB, L2=128MB); 尾轮: r=0 无尾轮",3765436416,51380224,0.00235339776,9.880812307692307e-06,0.0023632785723076925,0.0,0.0,60129542144.0,0.00012372333774485596,8388608,5.24288e-06,0.0,0.0023685214523076923,0.0,0.0023685214523076923,MTE2,True,,访存Bound(GM读写共享+L2重复读),"效率降级标注 (plan.note): 搬移效率下限不满足 —— 方案照常给出 (兜底), 但实际效率低于模型假设, 时延可能低估; 建议调整 dtype/布局 | 瓶颈在 MTE2 搬移链 (GM 读写共享总线 + L2 重复读): 可增大 tile 提升 dValue/单核搬移量、利用 L2 驻留吸收重复读 (ASW swizzle/分组方向), 或评估输出驻留 L2 以减少 GM 直写与读竞争" b4_m1_n8192_k8192,4,4,1,8192,8192,bf16,bf16,bf16,False,False,False,True,0,b4_m1_n8192_k8192,StreamK,Ascend950PR,batch_mat_mul_v3,32,1,1,1,32,"B/M/N切出4块, 每块32核切K归约 (归约组内核c负责K段[c*K/32,(c+1)*K/32))",1,1,1,8192,256,256,1,K段标准分块流水,1,128,64,allocate(部分和驻留L2),"resident(部分和4B驻留L2, 防精度丢失不随C的fp16/fp8转换)",0,4194304,grid_K=32路切K+归约,1,1,32,0,0,0,0,True,4,"P=0.50, grid_K=32, 部分和驻留L2按4B写出, AIV归约后按C dtype=2B写最终",536936448,0.0,0.00033558528,0.0,0.00033558528,0.0,0.0,536870912.0,1.104672658436214e-06,0.0,0.0,1.731729603729604e-06,0.00033558528,1.731729603729604e-06,0.0003373170096037296,MTE2,True,,访存Bound(GM读写共享+L2重复读),"瓶颈在 MTE2 搬移链 (GM 读写共享总线 + L2 重复读): 可增大 tile 提升 dValue/单核搬移量、利用 L2 驻留吸收重复读 (ASW swizzle/分组方向), 或评估输出驻留 L2 以减少 GM 直写与读竞争" b16_m2_n4096_k7168,16,16,2,4096,7168,bf16,bf16,bf16,False,False,False,True,0,b16_m2_n4096_k7168,StreamK,Ascend950PR,batch_mat_mul_v3,32,1,1,1,16,"B/M/N切出16块, 每块16核切K归约 (归约组内核c负责K段[c*K/16,(c+1)*K/16))",1,1,2,4096,448,256,1,K段标准分块流水,2,128,64,allocate(部分和驻留L2),"resident(部分和4B驻留L2, 防精度丢失不随C的fp16/fp8转换)",0,8388608,grid_K=16路切K+归约,1,1,16,0,0,0,0,True,4,"P=2.00, grid_K=16, 部分和驻留L2按4B写出, AIV归约后按C dtype=2B写最终",939982848,0,0.00058748928,0.0,0.00058748928,0.0,0.0,1879048192.0,3.866354304526749e-06,0.0,0.0,1.7726896037296038e-06,0.00058748928,1.7726896037296038e-06,0.0005892619696037297,MTE2,True,,访存Bound(GM读写共享+L2重复读),"瓶颈在 MTE2 搬移链 (GM 读写共享总线 + L2 重复读): 可增大 tile 提升 dValue/单核搬移量、利用 L2 驻留吸收重复读 (ASW swizzle/分组方向), 或评估输出驻留 L2 以减少 GM 直写与读竞争" b32_m64_n64_k7168,32,32,64,64,7168,bf16,bf16,bf16,False,False,False,True,0,b32_m64_n64_k7168,IterBatch,Ascend950PR,batch_mat_mul_v3,32,32,1,1,1,切B轮转分配(核间零重复读零依赖),1,1,64,64,7168,1024,1,d_两侧都切K,64,64,256,allocate(GM->L1随路驻留L2),"resident(整case输入+输出<=L2: 输出驻留L2异步回写, GM写=0)",0,0,不涉及(核内不切M/N),1,1,1,0,0,0,0,True,2,"两侧都切K: k_L1=1024, K段成对流水, batch边界天然无缝; dValueA=2048B/dValueB=128B; 输出落点: L2驻留",58720256,0.0,3.670016e-05,0.0,3.7050160000000004e-05,7,3.5000000000000004e-07,1879048192.0,3.866354304526749e-06,262144,5.041230769230769e-08,0.0,3.7050160000000004e-05,6.027486369104147e-07,3.765290863691042e-05,MTE2,True,,访存Bound(GM读写共享+L2重复读),"瓶颈在 MTE2 搬移链 (GM 读写共享总线 + L2 重复读): 可增大 tile 提升 dValue/单核搬移量、利用 L2 驻留吸收重复读 (ASW swizzle/分组方向), 或评估输出驻留 L2 以减少 GM 直写与读竞争" diff --git a/BMM/BMM_Theory/examples/result_recommend.csv b/BMM/BMM_Theory/examples/result_recommend.csv index 90288b4..6f11540 100644 --- a/BMM/BMM_Theory/examples/result_recommend.csv +++ b/BMM/BMM_Theory/examples/result_recommend.csv @@ -15,7 +15,7 @@ b16_m4_n256_k192,16,16,4,256,192,bf16,bf16,bf16,False,False,False,True,0,b16_m4_ b32_m8_n128_k256,32,32,8,128,256,bf16,bf16,bf16,False,False,False,True,0,b32_m8_n128_k256,IterBatch,Ascend950PR,batch_mat_mul_v3,32,32,1,1,1,切B轮转分配(核间零重复读零依赖),1,1,8,128,256,256,1,a_单batch全驻留,8,128,128,allocate(GM->L1随路驻留L2),"resident(整case输入+输出<=L2: 输出驻留L2异步回写, GM写=0)",0,0,不涉及(核内不切M/N),1,1,1,0,0,0,0,True,2,单batch全驻留: (MK+KN)*dtype=68KB <= L1; 输出落点: L2驻留,2228224,0.0,1.39264e-06,0.0,1.44264e-06,1,5.0000000000000004e-08,16777216.0,3.452102057613169e-08,65536,1.2603076923076923e-08,0.0,1.44264e-06,4.712409749920861e-08,1.4897640974992086e-06,MTE2,True,,访存Bound(GM读写共享+L2重复读),仅 IterBatch 条件满足 b64_m16_n256_k512,64,64,16,256,512,bf16,bf16,bf16,False,False,False,True,0,b64_m16_n256_k512,IterBatch,Ascend950PR,batch_mat_mul_v3,32,32,1,1,1,切B轮转分配(核间零重复读零依赖),2,1,16,256,512,240,1,c_一侧驻留+对侧切K,16,256,64,allocate(GM->L1随路驻留L2),"resident(整case输入+输出<=L2: 输出驻留L2异步回写, GM写=0)",0,0,不涉及(核内不切M/N),1,1,1,0,0,0,0,True,2,"一侧驻留(A)+对侧切K: A驻留16KB, 预算L1/2, k_L1=240, dValueA=480B/dValueB=512B; 输出落点: L2驻留",17825792,0.0,1.114112e-05,0.0,1.1441120000000001e-05,6,3.0000000000000004e-07,268435456.0,5.52336329218107e-07,524288,1.0082461538461538e-07,0.0,1.1441120000000001e-05,1.798661348528015e-07,1.1620986134852803e-05,MTE2,True,,访存Bound(GM读写共享+L2重复读),仅 IterBatch 条件满足 b128_m8_n192_k256,128,128,8,192,256,bf16,bf16,bf16,False,False,False,True,0,b128_m8_n192_k256,IterBatch,Ascend950PR,batch_mat_mul_v3,32,32,1,1,1,切B轮转分配(核间零重复读零依赖),4,1,8,192,256,256,2,b_双batch乒乓,8,192,80,allocate(GM->L1随路驻留L2),"resident(整case输入+输出<=L2: 输出驻留L2异步回写, GM写=0)",0,0,不涉及(核内不切M/N),1,1,1,0,0,0,0,True,2,双batch乒乓: 2*(MK+KN)*dtype=200KB <= L1; 输出落点: L2驻留,13107200,0.0,8.192e-06,0.0,8.392e-06,4,2.0000000000000002e-07,100663296.0,2.0712612345679012e-07,393216,7.561846153846153e-08,0.0,8.392e-06,7.068614624881291e-08,8.462686146248813e-06,MTE2,True,,访存Bound(GM读写共享+L2重复读),仅 IterBatch 条件满足 -b32_m16_n8192_k7168,32,32,16,8192,7168,bf16,bf16,bf16,False,False,False,True,0,b32_m16_n8192_k7168,ASW_Basic,Ascend950PR,batch_mat_mul_v3,32,1,1,8,1,B->M->N线性映射+ASW滑窗蛇形(W=4),0,1,16,1024,7168,112,1,双缓冲驻留当前tile输入,16,1024,16,allocate(输入驻留L2吸收重复读),"direct_gm(输出直写GM, 输入优先驻留L2)",4,0,A0,1,1,1,0,0,0,8,True,2,"tile枚举: P=1, 有界枚举最优 mCnt=1 x nCnt=8 (tile 16x1024, 每batch搬入113.8MB, r=0); Base tile 16x1024 (L0C 单缓冲方形用满); L2场景: B_单batch可驻留(全驻留或单侧驻留+对侧滑窗) (V_in=3591.0MB, V_out=8.0MB, L2=128MB); 尾轮: r=0 无尾轮",3765436416,51380224,0.00235339776,9.880812307692307e-06,0.0023632785723076925,0.0,0.0,60129542144.0,0.00012372333774485596,8388608,5.24288e-06,0.0,0.0023685214523076923,0.0,0.0023685214523076923,MTE2,True,,访存Bound(GM读写共享+L2重复读),"IterBatch/MergeBatch 进入条件均不满足, 回落 ASW_Basic; IterBatch未过: 3_L1驻留形态(四选一, 核心要求: 单batch核内零重复读); MergeBatch未过: 1_batch关系与每核份额: BatchA==BatchB 且 b_core=B/C>=2*b0; 2_L0C容量: 2*(b0*M)*(b0*N)*4B <= L0C; 2b_L0AB容量: 合并后 b0*M/b0*N 在最小K粒度下可驻留 L0A/L0B" +b32_m16_n8192_k7168,32,32,16,8192,7168,bf16,bf16,bf16,False,False,False,True,0,b32_m16_n8192_k7168,ASW_Basic,Ascend950PR,batch_mat_mul_v3,32,1,1,8,1,B->M->N线性映射+ASW滑窗蛇形(W=4),0,1,16,1024,7168,112,1,双缓冲驻留当前tile输入,16,1024,16,allocate(输入驻留L2吸收重复读),"direct_gm(输出直写GM, 输入优先驻留L2)",4,0,A0,1,1,1,0,0,0,8,True,2,"tile枚举: 效率降级(放开约束4, dValue 按 128B 硬下限, 搬移效率低于模型假设, 时延可能低估): P=1, mCnt=1 x nCnt=8 (tile 16x1024, 每batch搬入113.8MB, r=0); Base tile 16x1024 (L0C 单缓冲方形用满); L2场景: B_单batch可驻留(全驻留或单侧驻留+对侧滑窗) (V_in=3591.0MB, V_out=8.0MB, L2=128MB); 尾轮: r=0 无尾轮",3765436416,51380224,0.00235339776,9.880812307692307e-06,0.0023632785723076925,0.0,0.0,60129542144.0,0.00012372333774485596,8388608,5.24288e-06,0.0,0.0023685214523076923,0.0,0.0023685214523076923,MTE2,True,,访存Bound(GM读写共享+L2重复读),"IterBatch/MergeBatch 进入条件均不满足, 回落 ASW_Basic; IterBatch未过: 3_L1驻留形态(四选一, 核心要求: 单batch核内零重复读); MergeBatch未过: 1_batch关系与每核份额: BatchA==BatchB 且 b_core=B/C>=2*b0; 2_L0C容量: 2*(b0*M)*(b0*N)*4B <= L0C; 2b_L0AB容量: 合并后 b0*M/b0*N 在最小K粒度下可驻留 L0A/L0B [效率降级标注: 搬移效率低于模型假设, 时延可能低估, 见 plan.note]" b4_m1_n8192_k8192,4,4,1,8192,8192,bf16,bf16,bf16,False,False,False,True,0,b4_m1_n8192_k8192,StreamK,Ascend950PR,batch_mat_mul_v3,32,1,1,1,32,"B/M/N切出4块, 每块32核切K归约 (归约组内核c负责K段[c*K/32,(c+1)*K/32))",1,1,1,8192,256,256,1,K段标准分块流水,1,128,64,allocate(部分和驻留L2),"resident(部分和4B驻留L2, 防精度丢失不随C的fp16/fp8转换)",0,4194304,grid_K=32路切K+归约,1,1,32,0,0,0,0,True,4,"P=0.50, grid_K=32, 部分和驻留L2按4B写出, AIV归约后按C dtype=2B写最终",536936448,0.0,0.00033558528,0.0,0.00033558528,0.0,0.0,536870912.0,1.104672658436214e-06,0.0,0.0,1.731729603729604e-06,0.00033558528,1.731729603729604e-06,0.0003373170096037296,MTE2,True,,访存Bound(GM读写共享+L2重复读),"P<=C/2, B/M/N并行度买不满, 切K (grid_K=32)" b16_m2_n4096_k7168,16,16,2,4096,7168,bf16,bf16,bf16,False,False,False,True,0,b16_m2_n4096_k7168,StreamK,Ascend950PR,batch_mat_mul_v3,32,1,1,1,16,"B/M/N切出16块, 每块16核切K归约 (归约组内核c负责K段[c*K/16,(c+1)*K/16))",1,1,2,4096,448,256,1,K段标准分块流水,2,128,64,allocate(部分和驻留L2),"resident(部分和4B驻留L2, 防精度丢失不随C的fp16/fp8转换)",0,8388608,grid_K=16路切K+归约,1,1,16,0,0,0,0,True,4,"P=2.00, grid_K=16, 部分和驻留L2按4B写出, AIV归约后按C dtype=2B写最终",939982848,0,0.00058748928,0.0,0.00058748928,0.0,0.0,1879048192.0,3.866354304526749e-06,0.0,0.0,1.7726896037296038e-06,0.00058748928,1.7726896037296038e-06,0.0005892619696037297,MTE2,True,,访存Bound(GM读写共享+L2重复读),"P<=C/2, B/M/N并行度买不满, 切K (grid_K=16)" b32_m64_n64_k7168,32,32,64,64,7168,bf16,bf16,bf16,False,False,False,True,0,b32_m64_n64_k7168,IterBatch,Ascend950PR,batch_mat_mul_v3,32,32,1,1,1,切B轮转分配(核间零重复读零依赖),1,1,64,64,7168,1024,1,d_两侧都切K,64,64,256,allocate(GM->L1随路驻留L2),"resident(整case输入+输出<=L2: 输出驻留L2异步回写, GM写=0)",0,0,不涉及(核内不切M/N),1,1,1,0,0,0,0,True,2,"两侧都切K: k_L1=1024, K段成对流水, batch边界天然无缝; dValueA=2048B/dValueB=128B; 输出落点: L2驻留",58720256,0.0,3.670016e-05,0.0,3.7050160000000004e-05,7,3.5000000000000004e-07,1879048192.0,3.866354304526749e-06,262144,5.041230769230769e-08,0.0,3.7050160000000004e-05,6.027486369104147e-07,3.765290863691042e-05,MTE2,True,,访存Bound(GM读写共享+L2重复读),仅 IterBatch 条件满足 diff --git a/BMM/BMM_Theory/tests/test_branches.py b/BMM/BMM_Theory/tests/test_branches.py index 048d9e0..69f0942 100644 --- a/BMM/BMM_Theory/tests/test_branches.py +++ b/BMM/BMM_Theory/tests/test_branches.py @@ -760,19 +760,42 @@ class TestIssue33(unittest.TestCase): self.assertEqual((p.single_core_m, p.single_core_n), (512, 512)) self.assertEqual((p.m_cnt, p.n_cnt), (8, 8)) - def test_pathological_shape_flagged_infeasible(self): - # 极端形状 (N=8 int8, 大 K): B 侧 dValue = sN*dt = 8B 物理上不可能满足 - # 256B/128B 下限 -> 方案必须被自检标注违规 (不再静默产出伪可行方案) - from bmm_theory.constraints import check_plan_constraints + def test_issue34_k_l1_decomposition_derived(self): + # b32_m16_n8192_k7168: 分解 = Base 16x1024 (例外: M=16<256; N 侧受 L0B 单边 + # 上限收敛), SingleCore 16x1024 (mCnt=1,nCnt=8), k_l1 = L1 双缓冲反推 + # ⌊L1/(2·(sM+sN)·dt)⌋16 = ⌊524288/(2·1040·2)⌋16 = 112 (v1.91 §5.2) from bmm_theory.branches.asw_basic import AswBasicBranch + case = mkcase(32, 16, 8192, 7168) + p = AswBasicBranch().make_plan(case) + self.assertEqual((p.base_m, p.base_n), (16, 1024)) + self.assertEqual((p.single_core_m, p.single_core_n), (16, 1024)) + self.assertEqual(p.k_l1, 112) + + def test_pathological_shape_degraded_warning_always_plan(self): + # issue#34: 兜底分支恒出方案 —— 极端形状 (N=8 int8 大K, B 侧 dValue=8B + # 物理不可满足) 照常给方案 + 标注效率降级 (warning), 不判违规/不判不可行 + from bmm_theory.constraints import check_plan_constraints + from bmm_theory.evaluator import PlanEvaluator case = mkcase(4096, 2048, 8, 1024, dtype_a="int8", dtype_b="int8") r = self.router.route(case) self.assertEqual(r["branch"], "ASW_Basic") - v = check_plan_constraints(case, r["plan"]) - self.assertTrue(v, "极端形状应被自检标注违规 (搬移效率崩塌)") - self.assertIn("自检违规", r["arbitration"]) - # 时延仍应给出 (供人工评估), 但不为 0 / NaN - self.assertGreater(r["timing"].t_total, 0.0) + self.assertEqual(check_plan_constraints(case, r["plan"]), []) + self.assertIn("效率降级", r["plan"].note) + er = PlanEvaluator().evaluate(case, r["plan"]) + self.assertTrue(er.feasible) + self.assertIn("效率降级", er.advice) + self.assertGreater(er.timing.t_total, 0.0) + + def test_pathological_n8_hard_floor_fallback(self): + # 更极端: N=8 int8 连 128B 硬下限也不满足 -> 仍恒出方案, 效率降级标注 + from bmm_theory.evaluator import PlanEvaluator + case = mkcase(512, 4096, 1, 8192, dtype_a="int8", dtype_b="int8") + r = self.router.route(case) + self.assertEqual(r["branch"], "ASW_Basic") + self.assertIsNotNone(r["plan"]) + self.assertIn("效率降级", r["plan"].note) + er = PlanEvaluator().evaluate(case, r["plan"]) + self.assertTrue(er.feasible) if __name__ == "__main__":