From 12b2af44600ab4dea406051f595e3c25d30aa94d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E6=B2=90=E5=B7=9D?= Date: Thu, 18 Jun 2026 10:40:08 +0800 Subject: [PATCH] update OJ instructions --- .../MCTLASS_Fused MoE 算子优化.md | 764 +++++++++++++++--- 1 file changed, 662 insertions(+), 102 deletions(-) diff --git a/基于AI Agent开发范式的国产GPU大模型推理算子库优化/MCTLASS_Fused MoE 算子优化.md b/基于AI Agent开发范式的国产GPU大模型推理算子库优化/MCTLASS_Fused MoE 算子优化.md index cf5a175..67c8bbe 100644 --- a/基于AI Agent开发范式的国产GPU大模型推理算子库优化/MCTLASS_Fused MoE 算子优化.md +++ b/基于AI Agent开发范式的国产GPU大模型推理算子库优化/MCTLASS_Fused MoE 算子优化.md @@ -1,3 +1,5 @@ +# MCTLASS\_Fused MoE 算子优化 + # Fused MoE Baseline 入门:快速跑通最小闭环教程 ## 一、教程定位 @@ -27,7 +29,7 @@ * Triton:基于 Python 编写的高效 GPU Kernel,可利用 Agent 自动调优,**开发效率高、易于迁移**; * 要求 pybind 和 Triton 结果均与 reference 一致,鼓励参赛选手持续调优 Triton ,使其性能逼近甚至超越 pybind 性能。 - + 6. 输出 benchmark 结果对比表。 @@ -58,27 +60,31 @@ **环境准备:** * 已进入赛事专属镜像环境。 + **工具准备:** -* 已准备 Agent 工具; -* 已配置 Token / API Key; -* 已确认 Agent 可以正常调用模型。 +* 已准备 Agent 工具; + +* 已配置 Token / API Key; + +* 已确认 Agent 可以正常调用模型。 + **代码准备:** -* 已获取 Fused MoE Baseline 源码。 - +* 已获取 Fused MoE Baseline 源码。 + ## 五、项目实践1-算力平台 baseline 源码部署 -**项目目标:**在算力平台上拉取 Fused MoE 的 baseline 源码,快速跑通最小闭环,并记录一份 baseline 性能结果,为后续算子优化提供对比基准。 +\*\*项目目标:\*\*在算力平台上拉取 Fused MoE 的 baseline 源码,快速跑通最小闭环,并记录一份 baseline 性能结果,为后续算子优化提供对比基准。 ### 步骤 1:检查运行环境 -**目标:**确认当前环境满足本模块运行要求,包括编译器、MXMACA 工具链及 Python 依赖库。 +\*\*目标:\*\*确认当前环境满足本模块运行要求,包括编译器、MXMACA 工具链及 Python 依赖库。 -**操作:**检查 Python、编译工具、MXMACA 编译器及关键 Python 包(numpy、torch、triton)是否存在。 +\*\*操作:\*\*检查 Python、编译工具、MXMACA 编译器及关键 Python 包(numpy、torch、triton)是否存在。 **命令示例:** @@ -92,7 +98,9 @@ which mxcc # 确认 MACA 编译器存在 python - << 'EOF' import sys deps = ["numpy", "torch", "triton"] -missing = [] + +missing = [ ] + for d in deps: try: __import__(d) @@ -104,8 +112,8 @@ if missing: else: print("[OK] numpy, torch, triton are installed.") EOF -``` +``` **预期结果:** @@ -115,7 +123,7 @@ EOF * /opt/maca/mxgpu\_llvm/bin/mxcc -* \[OK\] numpy, torch, triton are installed. +* [OK] numpy, torch, triton are installed. **常见问题:** @@ -126,68 +134,71 @@ EOF | `Python 3.6.x/ Python 3.7.x` | Python 版本过低 | `conda install python=3.12` (推荐3.10+) | | `ModuleNotFoundError: numpy` | 当前 Python 缺少依赖 | `pip install numpy torch triton` | - ### 步骤 2:进入项目目录 -**目标:**进入本模块所需的源码目录:https://gitlink.org.cn/metax-maca/op_optimization/tree/master/%E5%9F%BA%E4%BA%8EAI%20Agent%E5%BC%80%E5%8F%91%E8%8C%83%E5%BC%8F%E7%9A%84%E5%9B%BD%E4%BA%A7GPU%E5%A4%A7%E6%A8%A1%E5%9E%8B%E6%8E%A8%E7%90%86%E7%AE%97%E5%AD%90%E5%BA%93%E4%BC%98%E5%8C%96%2Fbaselines%2Ffused_moe +\*\*目标:\*\*进入本模块所需的源码目录:https://gitlink.org.cn/metax-maca/op\_optimization/tree/master/%E5%9F%BA%E4%BA%8EAI%20Agent%E5%BC%80%E5%8F%91%E8%8C%83%E5%BC%8F%E7%9A%84%E5%9B%BD%E4%BA%A7GPU%E5%A4%A7%E6%A8%A1%E5%9E%8B%E6%8E%A8%E7%90%86%E7%AE%97%E5%AD%90%E5%BA%93%E4%BC%98%E5%8C%96%2Fbaselines%2Ffused\_moe -1. 克隆代码仓库 +1. 克隆代码仓库 + + ```Bash + git clone https://gitlink.org.cn/metax-maca/op\_optimization.git + + ``` + +2. 准备fused\_moe + - ```Bash - git clone https://gitlink.org.cn/metax-maca/op_optimization.git - ``` - -2. 准备fused_moe - - 在仓库目录 `op_optimization/基于AI Agent开发范式的国产GPU大模型推理算子库优化` 下,找到 `fused_moe` 文件夹。可以将 `fused_moe` 整个目录复制到工作目录 `data/` 下。 +在仓库目录 `op_optimization/基于AI Agent开发范式的国产GPU大模型推理算子库优化` 下,找到 `fused_moe` 文件夹。可以将 `fused_moe` 整个目录复制到工作目录 `data/` 下。 **下一步操作:** 切换到 FlashInfer Baseline 项目目录。 -**操作:**切换到指定项目路径。 +\*\*操作:\*\*切换到指定项目路径。 **命令示例:** ```apl cd data/fused_moe # 这里需要替换成自己的项目路径 + ``` **预期结果:** 终端提示符路径显示为 fused\_moe 项目路径: -* (base) root@0a5a9d0c0f06:/data/fused_moe# +* (base) root@0a5a9d0c0f06:/data/fused\_moe# ### 步骤 3:pybind 编译 -**目标:**将用 C++ 编写的 fused\_moe 算子编译为 Python 可调用的 pybind 模块。 +\*\*目标:\*\*将用 C++ 编写的 fused\_moe 算子编译为 Python 可调用的 pybind 模块。 -**操作:**运行 `fused_moe/scripts/build_fused_moe_i8_tn_pybind.sh` 脚本 +\*\*操作:\*\*运行 `fused_moe/scripts/build_fused_moe_i8_tn_pybind.sh` 脚本 **命令示例:** ```apl bash scripts/build_fused_moe_i8_tn_pybind.sh + ``` 切换 Python 环境命令示例: ```apl [SUCCESS] /data/fused_moe/standalone/fused_moe_i8_tn/build/fused_moe_i8_tn_pybind.sh + ``` **预期结果:** 编译成功无报错,终端显示: -* \[SUCCESS] /data/fused_moe/standalone/fused_moe_i8_tn/build/fused_moe_i8_tn_pybind.so - - 且成功生成 `fused_moe/standalone/fused_moe_i8_tn/build/fused_moe_i8_tn_pybind.cpython-310-x86_64-linux-gnu.so` 文件 +* \[SUCCESS\] /data/fused\_moe/standalone/fused\_moe\_i8\_tn/build/fused\_moe\_i8\_tn\_pybind.so +且成功生成 `fused_moe/standalone/fused_moe_i8_tn/build/fused_moe_i8_tn_pybind.cpython-310-x86_64-linux-gnu.so` 文件 + **常见问题:** - | 报错 | 原因 | 解决办法 | | --- | --- | --- | | `Python.h: No such file or directory` | Python 头文件路径未找到 | 确认 `PYTHON_BIN` 路径正确,脚本自动探测 `sysconfig.get_path('include')` | @@ -198,12 +209,12 @@ bash scripts/build_fused_moe_i8_tn_pybind.sh ### 步骤 4:正确性测试 -**目标:**验证 reference 计算、pybind 计算、Triton 计算这三种方式计算结果的数值是否完全一致。 - -**操作:**运行 `fused_moe/scripts/run_fused_moe_i8_tn_pybind_test.sh` 脚本 - +\*\*目标:\*\*验证 reference 计算、pybind 计算、Triton 计算这三种方式计算结果的数值是否完全一致。 + +\*\*操作:\*\*运行 `fused_moe/scripts/run_fused_moe_i8_tn_pybind_test.sh` 脚本 + **命令示例:** - + ```apl bash scripts/run_fused_moe_i8_tn_pybind_test.sh --backend all # 运行全部计算方式 @@ -214,28 +225,21 @@ bash scripts/run_fused_moe_i8_tn_pybind_test.sh --backend pybind bash scripts/run_fused_moe_i8_tn_pybind_test.sh --backend triton # 只测 reference: bash scripts/run_fused_moe_i8_tn_pybind_test.sh --backend reference + ``` - **预期结果:** - + 编译成功无报错,输出示例如下: - -> pybind:fused\_moe\_i8\_tn\_topk1 passed: rows=256, cols=128, sample C\[0\]=0.69531, C\[last\]=-0.44531 -> pybind:fused\_moe\_i8\_tn\_topk2 passed: rows=512, cols=128, sample C\[0\]=-0.57813, C\[last\]=-0.49805 -> pybind:fused\_moe\_i8\_tn\_topk3 passed: rows=384, cols=128, sample C\[0\]=-1.08594, C\[last\]=-0.33594 -> reference:fused\_moe\_i8\_tn\_topk1 passed: rows=256, cols=128, sample C\[0\]=0.6934, C\[last\]=-0.4451 -> reference:fused\_moe\_i8\_tn\_topk2 passed: rows=512, cols=128, sample C\[0\]=-0.5768, C\[last\]=-0.4975 -> reference:fused\_moe\_i8\_tn\_topk3 passed: rows=384, cols=128, sample C\[0\]=-1.0875, C\[last\]=-0.3362 +> pybind:fused\_moe\_i8\_tn\_topk1 passed: rows=256, cols=128, sample C\[0\]=0.69531, C\[last\]=-0.44531  pybind:fused\_moe\_i8\_tn\_topk2 passed: rows=512, cols=128, sample C\[0\]=-0.57813, C\[last\]=-0.49805  pybind:fused\_moe\_i8\_tn\_topk3 passed: rows=384, cols=128, sample C\[0\]=-1.08594, C\[last\]=-0.33594 -> triton:fused\_moe\_i8\_tn\_topk1 passed: rows=256, cols=128, sample C\[0\]=0.69337, C\[last\]=-0.44513 -> triton:fused\_moe\_i8\_tn\_topk2 passed: rows=512, cols=128, sample C\[0\]=-0.57678, C\[last\]=-0.49749 -> triton:fused\_moe\_i8\_tn\_topk3 passed: rows=384, cols=128, sample C\[0\]=-1.08748, C\[last\]=-0.33618 +> reference:fused\_moe\_i8\_tn\_topk1 passed: rows=256, cols=128, sample C\[0\]=0.6934, C\[last\]=-0.4451  reference:fused\_moe\_i8\_tn\_topk2 passed: rows=512, cols=128, sample C\[0\]=-0.5768, C\[last\]=-0.4975  reference:fused\_moe\_i8\_tn\_topk3 passed: rows=384, cols=128, sample C\[0\]=-1.0875, C\[last\]=-0.3362 +> triton:fused\_moe\_i8\_tn\_topk1 passed: rows=256, cols=128, sample C\[0\]=0.69337, C\[last\]=-0.44513  triton:fused\_moe\_i8\_tn\_topk2 passed: rows=512, cols=128, sample C\[0\]=-0.57678, C\[last\]=-0.49749  triton:fused\_moe\_i8\_tn\_topk3 passed: rows=384, cols=128, sample C\[0\]=-1.08748, C\[last\]=-0.33618 **结果解释:** - + * “pybind/reference/Triton”:三种计算方式; * “fused\_moe\_i8\_tn\_topk1/2/3 passed”:测试算子通过数值校验,数值误差在允许范围内且无明显异常,否则会报错 FAILED; @@ -247,50 +251,42 @@ bash scripts/run_fused_moe_i8_tn_pybind_test.sh --backend reference **常见问题:** - | 报错 | 原因 | 解决办法 | -| :--- | :--- | :--- | -| `ModuleNotFoundError: fused_moe_i8_tn_pybind` | pybind 模块未编译或未加入 `PYTHONPATH` | 回到步骤 3,确认 `.so` 已生成;执行 `export PYTHONPATH=/root/Project/fused_moe:$PYTHONPATH` | -| `FAILED: max abs diff too large` | 数值误差超过阈值 | 检查 scale 是否应用位置错误;确认 TopK 索引与权重是否一致 | -| `FAILED: shape mismatch` | 输出张量形状不一致 | 检查 Token Permute / Unpermute 逻辑;确认 expert 维度对齐 | -| `FAILED: NaN or Inf detected` | 溢出或未初始化内存 | 检查 INT8 乘加是否溢出;确认 GEMM 输出是否反量化 | -| 终端长时间无输出 | Kernel 死锁或 Launch 失败 | 减小测试 shape;检查是否触发 MACA 硬件限制 | +| --- | --- | --- | +| `ModuleNotFoundError: fused_moe_i8_tn_pybind` | pybind 模块未编译或未加入 `PYTHONPATH` | 回到步骤 3,确认 `.so` 已生成;执行 `export PYTHONPATH=/root/Project/fused_moe:$PYTHONPATH` | +| `FAILED: max abs diff too large` | 数值误差超过阈值 | 检查 scale 是否应用位置错误;确认 TopK 索引与权重是否一致 | +| `FAILED: shape mismatch` | 输出张量形状不一致 | 检查 Token Permute / Unpermute 逻辑;确认 expert 维度对齐 | +| `FAILED: NaN or Inf detected` | 溢出或未初始化内存 | 检查 INT8 乘加是否溢出;确认 GEMM 输出是否反量化 | +| 终端长时间无输出 | Kernel 死锁或 Launch 失败 | 减小测试 shape;检查是否触发 MACA 硬件限制 | ### 步骤5:性能测试 -**目标:**输出 benchmark 结果对比表 - -**操作:**运行 `fused_moe/scripts/run_fused_moe_i8_tn_benchmark.sh` 脚本 - +\*\*目标:\*\*输出 benchmark 结果对比表 + +\*\*操作:\*\*运行 `fused_moe/scripts/run_fused_moe_i8_tn_benchmark.sh` 脚本 + **命令示例:** - + ```apl bash scripts/run_fused_moe_i8_tn_benchmark.sh --backend all --warmup 5 --iters 20 # --backend:选择计算方式 # --warmup:设置预热次数 # --iters:设置迭代次数 + ``` - **预期结果:** - + 编译成功无报错,输出示例如下: - -> pybind:fused\_moe\_i8\_tn\_topk1 benchmark: avg\_ms=0.308978, TOPS=0.027149, warmup=5, iters=20 -> pybind:fused\_moe\_i8\_tn\_topk2 benchmark: avg\_ms=0.304500, TOPS=0.055098, warmup=5, iters=20 -> pybind:fused\_moe\_i8\_tn\_topk3 benchmark: avg\_ms=0.297775, TOPS=0.042256, warmup=5, iters=20 -> reference:fused\_moe\_i8\_tn\_topk1 benchmark: avg\_ms=1685.43, TOPS=0.000005, warmup=5, iters=20 -> reference:fused\_moe\_i8\_tn\_topk2 benchmark: avg\_ms=3384.52, TOPS=0.000005, warmup=5, iters=20 -> reference:fused\_moe\_i8\_tn\_topk3 benchmark: avg\_ms=2532.14, TOPS=0.000005, warmup=5, iters=20 +> pybind:fused\_moe\_i8\_tn\_topk1 benchmark: avg\_ms=0.308978, TOPS=0.027149, warmup=5, iters=20 pybind:fused\_moe\_i8\_tn\_topk2 benchmark: avg\_ms=0.304500, TOPS=0.055098, warmup=5, iters=20 pybind:fused\_moe\_i8\_tn\_topk3 benchmark: avg\_ms=0.297775, TOPS=0.042256, warmup=5, iters=20 -> triton:fused\_moe\_i8\_tn\_topk1 benchmark: avg\_ms=19.013421, TOPS=0.000441, warmup=5, iters=20 -> triton:fused\_moe\_i8\_tn\_topk2 benchmark: avg\_ms=16.745914, TOPS=0.001002, warmup=5, iters=20 -> triton:fused\_moe\_i8\_tn\_topk3 benchmark: avg\_ms=19.630328, TOPS=0.000641, warmup=5, iters=20 +> reference:fused\_moe\_i8\_tn\_topk1 benchmark: avg\_ms=1685.43, TOPS=0.000005, warmup=5, iters=20 reference:fused\_moe\_i8\_tn\_topk2 benchmark: avg\_ms=3384.52, TOPS=0.000005, warmup=5, iters=20  reference:fused\_moe\_i8\_tn\_topk3 benchmark: avg\_ms=2532.14, TOPS=0.000005, warmup=5, iters=20 +> triton:fused\_moe\_i8\_tn\_topk1 benchmark: avg\_ms=19.013421, TOPS=0.000441, warmup=5, iters=20  triton:fused\_moe\_i8\_tn\_topk2 benchmark: avg\_ms=16.745914, TOPS=0.001002, warmup=5, iters=20 triton:fused\_moe\_i8\_tn\_topk3 benchmark: avg\_ms=19.630328, TOPS=0.000641, warmup=5, iters=20 **结果解释:** - + * “pybind/reference/Triton”:三种计算方式; * “fused\_moe\_i8\_tn\_topk1/2/3”:分别对应选择前 1 / 2 / 3 个专家场景下的 MoE 算子; @@ -304,7 +300,6 @@ bash scripts/run_fused_moe_i8_tn_benchmark.sh --backend all --warmup 5 --iters 2 **常见问题:** - | 报错 | 原因 | 解决办法 | | --- | --- | --- | | `ModuleNotFoundError: fused_moe_i8_tn_pybind` | pybind 模块未编译或未加入 `PYTHONPATH` | 回到步骤 3,确认 `.so`已生成;执行 `export PYTHONPATH=/root/Project/fused_moe:$PYTHONPATH` | @@ -315,11 +310,11 @@ bash scripts/run_fused_moe_i8_tn_benchmark.sh --backend all --warmup 5 --iters 2 系统链接:[https://deeplink.org.cn/kernelswift/task](https://deeplink.org.cn/kernelswift/task) -**项目目标:**基于 KernelSwift 智能算子迁移系统,对 Fused MoE 算子进行在线自动调优。通过输入算子代码,一键生成适配沐曦硬件的高性能实现,高效完成算子优化与全流程追踪。 +\*\*项目目标:\*\*基于 KernelSwift 智能算子迁移系统,对 Fused MoE 算子进行在线自动调优。通过输入算子代码,一键生成适配沐曦硬件的高性能实现,高效完成算子优化与全流程追踪。 ### 步骤1:复用算子广场的 fused\_moe 算子进行二次优化 -**目标:**通过提交算子广场的 fused\_moe 算子代码发起自动优化流程,实现二次优化 +\*\*目标:\*\*通过提交算子广场的 fused\_moe 算子代码发起自动优化流程,实现二次优化 **操作:** @@ -402,7 +397,10 @@ bash scripts/run_fused_moe_i8_tn_benchmark.sh --backend all --warmup 5 --iters 2 return [hidden_states, w1, w2, topk_weights, topk_idx, top_k, True] def get_init_inputs(): - return [] + + return [ ] + + ``` 2. 进入新建任务页:点击左侧导航栏【新建任务】 ,进入算子提交页面。 @@ -418,19 +416,19 @@ bash scripts/run_fused_moe_i8_tn_benchmark.sh --backend all --warmup 5 --iters 2 * 选择适配硬件:算子需要适配的目标硬件厂商及型号,建议:沐曦 * 最大演化轮次:优化算法迭代次数,取值范围40-400,建议默认40,复杂算法可提高至100+ - + 5. 提交优化任务:点击右下角 \[优化\] 按钮,系统将提交任务并进入 \[生成中\] 状态 - ![image.png](https://origin.picgo.net/2026/06/04/image659a3f15b96be22c1.png) +![image](https://alidocs.oss-cn-zhangjiakou.aliyuncs.com/res/mxPOG5z1vjjJ9nKa/img/904e116c-9c88-4553-9a55-3ef6b29df1fa.png) - 完成上述步骤将看到如下界面: +完成上述步骤将看到如下界面: - ![image.png](https://origin.picgo.net/2026/06/04/image75c4ccf75e90cf428.png) +![image](https://alidocs.oss-cn-zhangjiakou.aliyuncs.com/res/mxPOG5z1vjjJ9nKa/img/2f72c9b1-e091-4472-a7e3-619e5ffcc7d7.png) ### 步骤2:任务查看与结果管理 -**目标:** 在新建优化任务后可追踪任务进度,获取优化结果 +**目标:** 在新建优化任务后可追踪任务进度,获取优化结果 **操作:** @@ -443,7 +441,7 @@ bash scripts/run_fused_moe_i8_tn_benchmark.sh --backend all --warmup 5 --iters 2 * 操作按钮:查看详情、删除任务 - ![image.png](https://origin.picgo.net/2026/06/04/image75c4ccf75e90cf428.png) + ![image](https://alidocs.oss-cn-zhangjiakou.aliyuncs.com/res/mxPOG5z1vjjJ9nKa/img/2d4678b8-3a3d-4489-8df7-4bef3dffdd63.png) 2. 追踪任务进度:当前任务状态为【运行中】时,点击任务列表中的【查看详情】按钮,追踪任务进度: @@ -459,12 +457,11 @@ bash scripts/run_fused_moe_i8_tn_benchmark.sh --backend all --warmup 5 --iters 2 4. 性能调优:按设定的演化轮次迭代优化算子性能 - * 顶部:任务名称、创建/更新时间、适配硬件、当前轮次进度 - - ![image.png](https://origin.picgo.net/2026/06/04/image9e9b23d9b25ddfe25.png) - + + ![image](https://alidocs.oss-cn-zhangjiakou.aliyuncs.com/res/mxPOG5z1vjjJ9nKa/img/14a88b07-c778-44ce-beef-6e8510c58daa.png) + 3. 获取优化结果:当前任务状态为【已完成】时,可在详情页查看优化结果: * 优化后算子代码支持一键复制 @@ -474,14 +471,14 @@ bash scripts/run_fused_moe_i8_tn_benchmark.sh --backend all --warmup 5 --iters 2 * 可点击【Diff 对比】查看优化前后代码差异,理解性能提升逻辑 - ![image.png](https://origin.picgo.net/2026/06/04/image1083021a27904294b1.png) + ![image](https://alidocs.oss-cn-zhangjiakou.aliyuncs.com/res/mxPOG5z1vjjJ9nKa/img/182f7e0b-a35e-4687-8236-ac40acee9b60.png) 4. 任务异常处理 * 任务失败:查看错误日志,常见原因包括代码不符合规范、测试用例错误、硬件适配问题,修改后重新提交任务; * 排队时间长:可调整提交时间,或联系平台管理员确认资源状态。 - + ## 七、Agent使用说明 @@ -500,12 +497,14 @@ bash scripts/run_fused_moe_i8_tn_benchmark.sh --backend all --warmup 5 --iters 2 请帮我确认: 1. 当前环境是否满足编译与运行要求? 2. 是否有潜在的不兼容风险(如 Python 与 libpython 版本)? + ``` 2. **运行测试** ```plaintext 请帮我运行 scripts/run_fused_moe_i8_tn_pybind_test.sh 脚本 + ``` 3. **分析结果** @@ -520,6 +519,7 @@ bash scripts/run_fused_moe_i8_tn_benchmark.sh --backend all --warmup 5 --iters 2 1. 为什么 pybind 比 Triton 快这么多? 2. TOPS 指标是否可信? 3. 当前结果是否已经具备提交价值? + ``` 4. **报错检查** @@ -536,20 +536,23 @@ bash scripts/run_fused_moe_i8_tn_benchmark.sh --backend all --warmup 5 --iters 2 1. 错误原因是什么? 2. 如何用 find 命令定位 libpython3.10.so? 3. 如何在 build_fused_moe_i8_tn_pybind.sh 中正确指定路径? + ``` 5. **代码理解** ```plaintext 请帮我梳理释 benchmark_fused_moe_i8_tn.py 代码整体框架 + ``` 6. **KernelSwift 系统搜索算子** - ```plaintext - 请帮我在算子广场检索 fused_moe 算子 - ``` +```plaintext +请帮我在算子广场检索 fused_moe 算子 + +``` ## 八、常见问题与注意事项 @@ -559,8 +562,8 @@ bash scripts/run_fused_moe_i8_tn_benchmark.sh --backend all --warmup 5 --iters 2 * 确保算力平台已正确安装 Python 和 C++、MACA 编译器及相关运行时库,避免因环境缺失导致编译失败; - * 镜像环境使用 Conda Python​ 作为默认运行环境,避免系统 Python 与 Conda Python 混用,防止 `Python.h`或 `libpython`路径错误。 - + * 镜像环境使用 Conda Python 作为默认运行环境,避免系统 Python 与 Conda Python 混用,防止 `Python.h`或 `libpython`路径错误。 + 2. pybind 编译与链接 * 若`Python.h not found`,请检查脚本中`PYTHON_INCLUDE`是否指向当前 Python 的 `include`目录; @@ -568,14 +571,14 @@ bash scripts/run_fused_moe_i8_tn_benchmark.sh --backend all --warmup 5 --iters 2 * 若`libpython not found`,请直接指定 Conda 下的`**libpython3.x.so**`绝对路径,避免链接系统静态库; * 编译 `pybind`模块时,务必开启 `-fPIC`,否则会出现 `recompile with -fPIC`错误。 - + 3. 性能测试建议 - * benchmark 应在关闭其他占用 GPU 的任务​后执行,避免干扰性能数据; + * benchmark 应在关闭其他占用 GPU 的任务后执行,避免干扰性能数据; * 多次运行取平均值,避免单次抖动影响结果; - * 性能对比应基于相同随机种子、相同 shape、相同 TopK、相同 batch size​的条件下进行,降低误差。 + * 性能对比应基于相同随机种子、相同 shape、相同 TopK、相同 batch size的条件下进行,降低误差。 ### Kernel Swift 智能算子迁移系统自动调优项目: @@ -589,13 +592,13 @@ bash scripts/run_fused_moe_i8_tn_benchmark.sh --backend all --warmup 5 --iters 2 * `def get_init_inputs`,表示 module init 的输入测试样例; * `def get_inputs`,表示 module forward 的输入测试样例。 - + 2. 性能优化建议 * 对于复杂算子,可适当提高最大演化轮次(如 100-200),获得更高加速比; * 优先选择算子广场中已有优化案例的算子类型,降低适配失败概率。 - + 3. 硬件适配问题 * 提交任务前确认目标硬件支持的算子类型; @@ -607,8 +610,565 @@ bash scripts/run_fused_moe_i8_tn_benchmark.sh --backend all --warmup 5 --iters 2 完成本模块后,建议继续学习以下内容: -1. **研读 fused\_moe源码:**理解代码的底层逻辑,可尝试修改 `build_fused_moe_i8_tn_pybind.sh`中的编译参数,观察其对 `avg_ms` 的影响; +1. \*\*研读 fused\_moe源码:\*\*理解代码的底层逻辑,可尝试修改 `build_fused_moe_i8_tn_pybind.sh`中的编译参数,观察其对 `avg_ms` 的影响; -2. **算子优化基础:**了解如何分析 Kernel 性能瓶颈; +2. \*\*算子优化基础:\*\*了解如何分析 Kernel 性能瓶颈; -3. **性能对比分析:**将 baseline 结果与优化后的结果进行对比分析,明确后续优化方向。 \ No newline at end of file +3. \*\*性能对比分析:\*\*将 baseline 结果与优化后的结果进行对比分析,明确后续优化方向。 + + +## 十、XPU-OJ 冒烟提交:从 Baseline 到评测结果 + +### 10.1 教程定位 + +前面的 Baseline 教程主要帮助你完成三件事: + +1. 看懂 Fused MoE 算子的输入、输出和计算逻辑; + +2. 在模力方舟环境里跑通本地编译、测试和 benchmark; + +3. 得到一组本地性能基线,方便后续判断优化是否真的有效。 + + +需要特别说明: + +* **Baseline 不是最终提交物。** + +* **XPU-OJ 才是最终评测入口。** + +* XPU-OJ 不会直接运行前面的 benchmark 脚本,而是会调用你提交代码里的 `run_kernel(...)` 函数。 + + +简单理解: + +| 内容 | 作用 | +| --- | --- | +| Baseline | 帮你理解算子和建立性能基线 | +| Agent | 帮你读代码、写初版、定位错误、迭代优化 | +| XPU-OJ | 按统一测试数据评测你的 `run_kernel(...)` | +| Candidate | 每一版可提交、可复现的代码结果 | + +完成本节后,你应该能完成一次最小 OJ 提交,确认自己的提交链路是通的。 + +### 10.2 学习目标 + +完成本模块后,你将能够: + +1. 理解 Baseline benchmark 和 XPU-OJ 提交之间的区别; + +2. 找到 Fused MoE GEMM 题目的接口约定; + +3. 准备一个可以提交到 OJ 的 `run_kernel(...)` 文件; + +4. 在 XPU-OJ 页面提交代码并查看结果; + +5. 根据 OJ 返回的 `Wrong Answer`、`Runtime Error`、`Accepted` 等状态判断下一步动作。 + + +### 10.3 适用对象 + +本模块适合已经完成以下准备的参赛者: + +* 已经进入模力方舟赛事镜像; + +* 已经上传或准备好 Fused MoE baseline 源码; + +* 已经可以在终端里运行基础命令; + +* 已经配置好 Agent 工具,例如 OpenCode; + +* 已经拿到组委会发放的 XPU-OJ 账号。 + + +如果你还没有做过 GPU kernel 优化,也可以先照着本节完成一次冒烟提交。这里的目标不是马上拿高分,而是先确认“我能提交、OJ 能调用我的函数、反馈能回来”。 + +### 10.4 前置准备 + +#### 10.4.1 代码准备 + +建议在工作目录下保留一个候选版本目录,例如: + +```bash +cd /data/fusedmoe_v2.1 +mkdir -p oj/problem_1_fused_moe +``` + +本教程建议把 OJ 提交代码先保存为: + +```text +oj/problem_1_fused_moe/solution001.py +``` + +真正提交时,只需要把这个文件里的内容复制到 XPU-OJ 提交框。 + +#### 10.4.2 账号准备 + +XPU-OJ 账号由组委会统一发放。登录入口: + +```text +https://xpuoj.com/ +``` + +如果登录后看不到比赛或题目,请联系助教或赛事运营确认账号是否已经加入对应比赛或用户组。 + +### 10.5 知识预备 + +#### 10.5.1 什么是 OJ + +OJ 可以理解为“自动评测机”。 + +你提交代码后,OJ 会自动完成: + +1. 加载你的代码; + +2. 构造测试输入; + +3. 调用你的 `run_kernel(...)`; + +4. 生成参考答案; + +5. 对比你的输出和参考输出; + +6. 返回评测状态、耗时、内存和分数。 + + +所以,OJ 不是让你提交 benchmark 日志,也不是让你提交本地运行截图,而是让你提交一份符合接口约定的代码。 + +#### 10.5.2 什么是 Candidate + +Candidate 就是一次可复现的候选方案。 + +建议每一轮都记录: + +| 记录项 | 示例 | +| --- | --- | +| 候选编号 | candidate-001 | +| 代码文件 | `oj/problem_1_fused_moe/solution001.py` | +| 本地检查结果 | local check passed | +| OJ 结果 | WA / RE / AC | +| 备注 | 初始冒烟版,只验证接口 | + +这样后续多次打榜时,不会忘记哪一版代码对应哪一次提交结果。 + +### 10.6 项目实践:Fused MoE GEMM OJ 冒烟提交 + +本节以当前 XPU-OJ 题目 **1. Fused MoE GEMM** 为例。 + +题目要求你提交一份 Python 代码,并提供固定函数: + +```python +def run_kernel( + a, + b_col_major, + scale_a, + scale_b, + moe_weights, + token_ids, + expert_ids, + topk, + out, +): + ... +``` + +评测程序会调用这个函数,并检查你是否把结果正确写入 `out`。 + +#### 步骤 1:理解本题要算什么 + +本题计算的是固定规格 `fused_moe_i8_tn`: + +```text +N = 128 +K = 128 +EM = num_tokens * topk +EM % 128 == 0 +``` + +核心公式是: + +```text +out[r, n] = + sum_k(a[token(r), k] * b_col_major[expert(r), n, k]) + * scale_a[token(r)] + * scale_b[expert(r), n] + * moe_weights[r] +``` + +两个索引最容易写错: + +```text +token(r) = token_ids[r] // topk +expert(r) = expert_ids[r // 128] +``` + +再说得直白一点: + +* `token_ids` 不是直接拿来当 `a` 的行号,要先除以 `topk`; + +* `expert_ids` 不是每一行一个 expert,而是每 128 行一个 expert; + +* `b_col_major` 的布局是 `[expert, n, k]`,不是 `[expert, k, n]`; + +* 最终结果必须写回传入的 `out`。 + + +#### 步骤 2:准备 OJ 提交文件 + +在终端中创建目录: + +```bash +cd /data/fusedmoe_v2.1 +mkdir -p oj/problem_1_fused_moe +``` + +新建文件: + +```bash +touch oj/problem_1_fused_moe/solution001.py +``` + +下一步不是手写一份固定答案,而是让 Agent 根据题面生成一份“最小冒烟版”。 + +注意:冒烟版的目标只是确认接口、索引和 OJ 提交流程,不追求性能最优。 + +#### 步骤 3:让 Agent 生成 OJ 冒烟代码 + +在 OpenCode 或其他 Agent 中,把题目的接口约定、输入输出说明和下面这段 Prompt 一起发给 Agent: + +```text +我正在做 XPU-OJ 的 Fused MoE GEMM 题,需要生成一个最小冒烟提交版本。 + +请根据下面接口写一份完整 Python 代码: + +def run_kernel(a, b_col_major, scale_a, scale_b, moe_weights, token_ids, expert_ids, topk, out): + ... + +题目语义: +1. N = 128,K = 128; +2. EM = num_tokens * topk,且 EM 是 128 的倍数; +3. token(r) = token_ids[r] // topk; +4. expert(r) = expert_ids[r // 128]; +5. b_col_major 的布局是 [expert, n, k]; +6. 结果必须原地写入 out; +7. out 的 dtype 是 bfloat16; +8. 正确性优先,不需要优化性能。 + +代码要求: +1. 函数名和参数顺序必须完全一致; +2. 不要添加 torch.Tensor 类型注解; +3. 不要依赖外部文件; +4. 不要打印调试信息; +5. 不要返回新 tensor,只写入 out; +6. 请输出一份可以直接复制到 XPU-OJ 提交框的完整代码。 +``` + +Agent 生成后,把代码保存到: + +```text +oj/problem_1_fused_moe/solution001.py +``` + +保存前建议人工检查 5 个点: + +| 检查项 | 应该满足 | +| --- | --- | +| 函数名 | 必须是 `run_kernel` | +| 参数顺序 | 必须是 `a, b_col_major, scale_a, scale_b, moe_weights, token_ids, expert_ids, topk, out` | +| token 索引 | 必须使用 `token_ids[r] // topk` | +| expert 索引 | 必须使用 `expert_ids[r // 128]` | +| 输出方式 | 必须原地写入 `out` | + +如果 OJ 页面要求选择 `Triton` 或 `Triton Maca` 语言,也可以先让 Agent 生成一个语义正确的冒烟版本。正确性通过后,再让 Agent 把核心计算替换成 Triton kernel 做性能优化。 + +#### 步骤 4:提交到 XPU-OJ + +1. 打开 XPU-OJ: + + ```text + https://xpuoj.com/ + ``` + +2. 使用组委会发放的账号登录; + +3. 进入比赛页面; + + [![image](https://alidocs.oss-cn-zhangjiakou.aliyuncs.com/res/mxPOG5z1vjjJ9nKa/img/f9078ee6-9850-4817-8183-8cab717b613e.png)](https://www.picgo.net/image/image.13ku6N) + +4. 找到题目: + + ```text + 1. Fused MoE GEMM + ``` + +5. 点击题目进入详情页; + +6. 在提交区域选择本题支持的语言,例如: + + ```text + Triton / Triton Maca + ``` + + 具体名称以页面下拉框为准。 + +7. 将 `solution001.py` 中的代码复制到提交框; + +8. 点击提交; + +9. 等待评测结果返回。 + + +#### 步骤 5:查看 OJ 结果 + +提交后,进入: + +```text +我的提交 +``` + +常见状态含义如下: + +| 状态 | 含义 | 下一步 | +| --- | --- | --- | +| Accepted / AC | 正确性通过 | 可以继续优化性能 | +| Wrong Answer / WA | 输出数值不对 | 检查索引、shape、dtype、缩放系数 | +| Runtime Error / RE | 运行时报错 | 点开详情看报错栈 | +| Compile Error / CE | 编译或加载失败 | 检查 import、语法、函数名 | +| Time Limit Exceeded / TLE | 超时 | 说明代码太慢,需要做 kernel 优化 | + +如果看到 `0 pts`,通常表示本次提交没有拿到分数。原因可能是: + +* 样例没过; + +* 测试点没过; + +* 代码运行时报错; + +* 代码超时; + +* 输出与参考答案超过容差。 + + +如果看到用时和内存都是 `0`,很多时候说明代码在正式计时前就失败了,例如函数签名不匹配、导入失败或编译失败。 + +#### 步骤 6:理解 OJ 评测流程 + +一次 OJ 提交通常会经历下面这些步骤: + +1. 选手提交代码; + +2. 平台按所选语言加载代码; + +3. 评测程序构造输入 tensor; + +4. 调用选手代码里的 `run_kernel(...)`; + +5. 选手代码把结果写入 `out`; + +6. 评测程序生成参考结果; + +7. 比较 `out` 和参考结果; + +8. 正确性通过后统计运行耗时; + +9. 根据题目规则计算分数; + +10. 在排行榜或提交记录中更新结果。 + + +本题的正确性校验口径是: + +```python +torch.allclose(out_target.float(), out_ref.float(), rtol=0.0, atol=1e-2) + +``` + +也就是说,OJ 允许很小的数值误差,但不是随便差一点都能过。 + +#### 步骤 7:保存 Candidate + +建议每一次能跑的版本都用 Git 保存。 + +```bash +cd /data/fusedmoe_v2.1 +git status --short +git add oj/problem_1_fused_moe/solution001.py +git commit -m "candidate 001 fused moe i8 tn oj smoke" +git tag candidate-001-oj-smoke + +``` + +查看最近候选版本: + +```bash +git log --oneline --decorate -5 + +``` + +如果下一轮要继续优化,可以复制一份新文件: + +```bash +cp oj/problem_1_fused_moe/solution001.py oj/problem_1_fused_moe/solution002.py + +``` + +然后让 Agent 基于 `solution002.py` 继续改。 + +### 10.7 Agent 使用说明 + +本模块中,Agent 主要用来做三件事: + +1. 读题目接口; + +2. 生成最小可提交代码; + +3. 根据 OJ 报错定位问题。 + + +建议不要一开始就让 Agent “直接写最快版本”。更稳的流程是: + +```text +第一步:先写一个能过正确性的最小版本。 +第二步:提交 OJ,看是否 AC。 +第三步:AC 后再优化性能。 + +``` + +可以使用下面的 Prompt: + +```text +我正在做 XPU-OJ 的 Fused MoE GEMM 题。 + +请只做一件事:根据题目接口写一个最小正确的 run_kernel 冒烟版本。 + +要求: +1. 函数签名必须完全一致: + run_kernel(a, b_col_major, scale_a, scale_b, moe_weights, token_ids, expert_ids, topk, out) +2. token(r) = token_ids[r] // topk +3. expert(r) = expert_ids[r // 128] +4. b_col_major 的布局是 [expert, n, k] +5. 结果必须原地写入 out +6. 不要做性能优化 +7. 不要添加 torch.Tensor 类型注解 +8. 不要依赖外部文件 +9. 请输出完整可复制提交的 Python 代码 + +``` + +如果 OJ 返回 `Wrong Answer`,可以继续问: + +```text +OJ 返回 Wrong Answer。 + +请不要重写整份代码,先根据下面四点检查可能原因: +1. token_ids 是否正确除以 topk; +2. expert_ids 是否按每 128 行一个 expert 使用; +3. b_col_major 是否按 [expert, n, k] 读取; +4. 是否把结果写入 out,且 dtype 与 out 保持一致。 + +请给出最小修改建议。 + +``` + +如果 OJ 返回 `Runtime Error`,可以问: + +```text +OJ 返回 Runtime Error。 + +这是错误日志:[粘贴错误日志] + +请先判断是函数签名、import、RestrictedPython 限制、dtype、shape 还是 GPU 算子调用问题。 +只给出最小修复方案。 + +``` + +### 10.8 常见问题 + +#### Q1:为什么本地能跑,OJ 上却 Runtime Error? + +本地环境和 OJ 沙箱不完全一样。OJ 可能限制某些 Python 写法、外部文件访问或动态编译行为。 + +常见例子: + +```python +def silu(x: torch.Tensor) -> torch.Tensor: + ... + +``` + +这种类型注解可能触发: + +```text +Access to torch.Tensor is not allowed + +``` + +处理方式:去掉 `torch.Tensor` 类型注解。 + +#### Q2:为什么 OJ 是 Wrong Answer? + +优先检查四个点: + +1. `token_ids[r]` 是否先除以 `topk`; + +2. `expert_ids` 是否按 `r // 128` 取; + +3. `b_col_major` 是否按 `[expert, n, k]` 理解; + +4. 结果是否写回 `out`,而不是只返回一个新 tensor。 + + +#### Q3:为什么冒烟代码很慢? + +冒烟代码的目标是确认接口正确,不是追求性能。 + +如果它能过正确性,但耗时很高,这是正常的。下一步才是把核心计算替换成 Triton kernel 或其他更快的 GPU 实现。 + +#### Q4:50 分、10 分是什么意思? + +不同比赛和题目的评分规则可能不同。一般可以先这样理解: + +* 正确性没过时,通常拿不到有效分数; + +* 正确性通过后,平台会继续根据耗时或加速比计算分数; + +* 具体分数含义以 XPU-OJ 当前题目的评分说明为准。 + + +#### Q5:榜单怎么看? + +先看自己的提交是否通过正确性,再看耗时和分数。 + +建议记录: + +| Candidate | OJ 状态 | 用时 | 分数 | 备注 | +| --- | --- | --- | --- | --- | +| candidate-001 | AC / WA / RE | 以页面为准 | 以页面为准 | 冒烟版 | +| candidate-002 | AC / WA / RE | 以页面为准 | 以页面为准 | 第一轮优化 | + +不要只看单次结果。每轮都记录,后面才知道 Agent 的修改到底有没有带来收益。 + +### 10.9 从 Baseline 到参赛作品的路径回顾 + +建议按下面顺序推进: + +1. 跑通 baseline benchmark,理解算子输入输出; + +2. 阅读 XPU-OJ 题目页面,确认 `run_kernel(...)` 接口; + +3. 提交冒烟代码,确认 OJ 链路正常; + +4. 如果冒烟代码 WA / RE,先修正确性; + +5. 正确性通过后,再让 Agent 生成 Triton kernel 优化版本; + +6. 每一轮提交都保存 candidate、prompt、代码 diff 和 OJ 结果; + +7. 用 OJ 分数和耗时判断优化是否有效。 + + +一句话总结: + +```text +Baseline 用来学习,OJ 用来评分,Candidate 用来管理每一轮结果。 + +``` \ No newline at end of file