From 5da0ba33b383154a6632ca0f3e2f852bb0dc20eb Mon Sep 17 00:00:00 2001 From: david135792468 Date: Wed, 20 May 2026 15:38:43 +0800 Subject: [PATCH] matmul related skills init --- .../matmul-related-gen/k_axis_offset/skill.md | 448 ++++++++++++++++++ .../matmul_skill_for_any_shape/README.md | 64 +++ .../matmul_skill_for_any_shape/SKILL.md | 202 ++++++++ .../matmul_skill_for_any_shape/code_lib.zip | Bin 0 -> 441482 bytes .../script/.upload_status.json | 1 + .../script/analyze_results.py | 178 +++++++ .../script/batch_verification.py | 341 +++++++++++++ .../script/check_config.py | 182 +++++++ .../script/check_file_exist.py | 90 ++++ .../script/reorder_excel.py | 78 +++ .../script/server_check.py | 275 +++++++++++ .../script/server_config.json | 11 + .../script/verify_code.py | 275 +++++++++++ .../matmul_skill_for_any_shape/shape_list.md | 94 ++++ .../matmul-related-gen/skills_overview.md | 175 +++++++ .../tiling_diagonal/skill.md | 104 ++++ .../triton_w_nd2nz/SKILL.md | 361 ++++++++++++++ 17 files changed, 2879 insertions(+) create mode 100644 skills/triton/matmul-related-gen/k_axis_offset/skill.md create mode 100644 skills/triton/matmul-related-gen/matmul_skill_for_any_shape/README.md create mode 100644 skills/triton/matmul-related-gen/matmul_skill_for_any_shape/SKILL.md create mode 100644 skills/triton/matmul-related-gen/matmul_skill_for_any_shape/code_lib.zip create mode 100644 skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/.upload_status.json create mode 100644 skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/analyze_results.py create mode 100644 skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/batch_verification.py create mode 100644 skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/check_config.py create mode 100644 skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/check_file_exist.py create mode 100644 skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/reorder_excel.py create mode 100644 skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/server_check.py create mode 100644 skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/server_config.json create mode 100644 skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/verify_code.py create mode 100644 skills/triton/matmul-related-gen/matmul_skill_for_any_shape/shape_list.md create mode 100644 skills/triton/matmul-related-gen/skills_overview.md create mode 100644 skills/triton/matmul-related-gen/tiling_diagonal/skill.md create mode 100644 skills/triton/matmul-related-gen/triton_w_nd2nz/SKILL.md diff --git a/skills/triton/matmul-related-gen/k_axis_offset/skill.md b/skills/triton/matmul-related-gen/k_axis_offset/skill.md new file mode 100644 index 00000000..2b41d56f --- /dev/null +++ b/skills/triton/matmul-related-gen/k_axis_offset/skill.md @@ -0,0 +1,448 @@ +# K-Axis Offset Optimization Algorithm for GEMM + +## Inputs + +- `input_triton_code` - Original Triton kernel code containing matrix multiplication + - Must contain `tl.dot()` operation (indicates matrix multiplication) + - Should use `tl.make_block_ptr()` for pointer management + - Should have K-axis reduction loop + +## Outputs + +- `triton_code_with_koffset` - Optimized Triton code with K-axis offset technique applied + - All K positions are computed exactly once + - Uses cyclic K-axis traversal + +## Overview + +K-Axis Offset Optimization is a technique for optimizing GEMM (General Matrix Multiply) operations on NPU by distributing K-axis computation across different blocks with different starting positions. This reduces memory access conflicts and improves parallelism. + +## Preconditions + +Before applying this optimization, verify the following conditions: + +1. **Contains Matrix Multiplication**: The code must contain `tl.dot()` operation +2. **K-Axis Reduction Loop**: There should be a loop that iterates over the K dimension +3. **Block Pointer Usage**: Code should use `tl.make_block_ptr()` for pointer management +4. **Sufficient K Dimension**: K should be significantly larger than BLOCK_SIZE_K for meaningful benefit +5. **Multi-Core Target**: Target hardware should have multiple cores for parallelism benefit + +## Code Pattern Recognition + +### Pattern to Match + +Look for the following code patterns that indicate applicability of K-axis offset optimization: + +```python +# Standard K-axis loop pattern (BEFORE optimization) +for k in range(0, K, BLOCK_SIZE_K): + a_val = tl.load(a_ptr, boundary_check=(0, 1)) + b_val = tl.load(b_ptr, boundary_check=(0, 1)) + acc += tl.dot(a_val, b_val, out_dtype=tl.int32) + a_ptr = tl.advance(a_ptr, (0, BLOCK_SIZE_K)) + b_ptr = tl.advance(b_ptr, (BLOCK_SIZE_K, 0)) +``` + +### Key Indicators + +1. **`tl.dot()` presence**: The code contains `tl.dot()` operation +2. **K-axis loop**: A loop iterating over K dimension with step size `BLOCK_SIZE_K` +3. **Pointer advancement**: Uses `tl.advance()` to move pointers along K dimension +4. **Accumulator pattern**: Uses an accumulator variable (e.g., `acc`) that accumulates dot products + +### Detection Logic + +```python +def can_apply_koffset(code): + indicators = [ + "tl.dot(" in code, + "tl.advance(" in code, + "tl.make_block_ptr(" in code, + any(keyword in code for keyword in ["BLOCK_SIZE_K", "for k", "range(0, K"]) + ] + return sum(indicators) >= 3 +``` + +## Algorithm Principle + +### Core Idea + +Different blocks start from different K positions and traverse the entire K axis cyclically: + +1. **Calculate K Offset**: Each block calculates its starting K position using modulo arithmetic +2. **Cyclic Traversal**: Traverse from offset to K end, then wrap around to 0 and continue to offset +3. **Complete Coverage**: Ensure all K positions are computed exactly once + +### Mathematical Foundation + +For a block with index `block_idx`: +```python +num_k_blocks = tl.cdiv(K, BLOCK_SIZE_K) +k_offset = (2 * block_idx) % num_k_blocks + +for k_iter in range(num_k_blocks): + k_idx = (k_iter + k_offset) % num_k_blocks + current_k = k_idx * BLOCK_SIZE_K +``` + +The K-axis traversal follows this pattern: +- **Phase 1**: From `k_offset * BLOCK_SIZE_K` to `K` (exclusive) +- **Phase 2**: From `0` to `k_offset * BLOCK_SIZE_K` (exclusive) + +This ensures complete K-axis coverage with cyclic behavior. + +## Implementation + +### Method 1: Fusion Approach with Per-Iteration Pointer Creation (Recommended) + +This approach is based on the reference implementation and provides an optimized fusion pattern: + +```python +num_k_blocks = tl.cdiv(K, BLOCK_SIZE_K) +k_offset = (2 * block_idx) % num_k_blocks + +acc = tl.zeros((BLOCK_SIZE_M, BLOCK_SIZE_N), dtype=tl.int32) + +for k_iter in range(num_k_blocks): + k_idx = (k_iter + k_offset) % num_k_blocks + current_k = k_idx * BLOCK_SIZE_K + + # Create new pointers with current offset each iteration + a_ptr = tl.make_block_ptr( + base=a, + shape=(M, K), + strides=(stride_am, stride_ak), + offsets=(block_m * BLOCK_SIZE_M, current_k), + block_shape=(BLOCK_SIZE_M, BLOCK_SIZE_K), + order=(1, 0), + ) + + b_ptr = tl.make_block_ptr( + base=b, + shape=(K, N), + strides=(stride_bk, stride_bn), + offsets=(current_k, block_n * BLOCK_SIZE_N), + block_shape=(BLOCK_SIZE_K, BLOCK_SIZE_N), + order=(1, 0), + ) + + a_val = tl.load(a_ptr, boundary_check=(0, 1)) + b_val = tl.load(b_ptr, boundary_check=(0, 1)) + acc += tl.dot(a_val, b_val, out_dtype=tl.int32) +``` + +**Pros**: +- Simplest code structure +- No complex pointer management +- Direct fusion pattern +- No conditional logic + +**Cons**: +- Does not use `tl.advance()` (violates checklist requirement) +- More pointer creation overhead +- Potentially less efficient than hybrid approach + +### Method 2: Two-Phase Approach (Alternative) + +```python +num_k_blocks = tl.cdiv(K, BLOCK_SIZE_K) +k_offset = ((2 * block_idx) % num_k_blocks) * BLOCK_SIZE_K + +# Phase 1: From offset to K +a_ptr = tl.make_block_ptr(..., offsets=(..., k_offset), ...) +b_ptr = tl.make_block_ptr(..., offsets=(k_offset, ...), ...) + +num_k_blocks_phase1 = tl.cdiv(K - k_offset, BLOCK_SIZE_K) +for k_iter in range(num_k_blocks_phase1): + a_val = tl.load(a_ptr, boundary_check=(0, 1)) + b_val = tl.load(b_ptr, boundary_check=(0, 1)) + acc += tl.dot(a_val, b_val, out_dtype=tl.int32) + a_ptr = tl.advance(a_ptr, (0, BLOCK_SIZE_K)) + b_ptr = tl.advance(b_ptr, (BLOCK_SIZE_K, 0)) + +# Phase 2: From 0 to offset +a_ptr = tl.make_block_ptr(..., offsets=(..., 0), ...) +b_ptr = tl.make_block_ptr(..., offsets=(0, ...), ...) + +num_k_blocks_phase2 = tl.cdiv(k_offset, BLOCK_SIZE_K) +for k_iter in range(num_k_blocks_phase2): + a_val = tl.load(a_ptr, boundary_check=(0, 1)) + b_val = tl.load(b_ptr, boundary_check=(0, 1)) + acc += tl.dot(a_val, b_val, out_dtype=tl.int32) + a_ptr = tl.advance(a_ptr, (0, BLOCK_SIZE_K)) + b_ptr = tl.advance(b_ptr, (BLOCK_SIZE_K, 0)) +``` + +**Pros**: +- Clear separation of two phases +- Uses `tl.advance()` efficiently (satisfies checklist requirement) + +**Cons**: +- Two separate loops +- More code duplication +- Manual calculation of phase lengths + +## Key Techniques + +### 1. Modulo Arithmetic for Wrap-Around + +```python +num_k_blocks = tl.cdiv(K, BLOCK_SIZE_K) +k_offset = (2 * block_idx) % num_k_blocks + +for k_iter in range(num_k_blocks): + k_idx = (k_iter + k_offset) % num_k_blocks + current_k = k_idx * BLOCK_SIZE_K +``` + +This formula automatically calculates the current K position and handles wrap-around when exceeding K. + +### 2. Hybrid Pointer Management + +- **Primary**: Use `tl.advance()` for forward movement (efficient) +- **Secondary**: Use `tl.make_block_ptr()` for wrap-around (necessary) + +### 3. Conditional Pointer Recreation + +```python +if k_iter > 0 and current_k == 0: + # Recreate pointers at position 0 +``` + +Only recreate pointers when actually wrapping around to avoid overhead. + +## Workflow + +Follow these steps to apply K-axis offset optimization to your Triton code: + +### Step 1: Analyze Input Code + +- Check if the code contains `tl.dot()` operation +- Identify the K-axis loop structure +- Locate `tl.make_block_ptr()` and `tl.advance()` usage +- Extract matrix dimensions (M, N, K) and BLOCK_SIZE_K + +### Step 2: Extract Parameters + +- Extract K dimension from the code +- Identify the block indexing scheme (e.g., `block_idx`, `pid`, `pgid`) +- Find the current K-loop boundaries + +### Step 3: Apply Optimization + +1. **Calculate K Offset**: Add `num_k_blocks = tl.cdiv(K, BLOCK_SIZE_K)` and `k_offset = (2 * block_idx) % num_k_blocks` +2. **Initialize Accumulator**: Create zero-initialized accumulator +3. **Modify Loop Structure**: Change from simple K-loop to cyclic traversal +4. **Implement Chosen Method**: + - **Method 1 (Fusion Approach)**: Create new pointers per iteration with current_k + - **Method 2 (Two-Phase)**: Use two separate loops with tl.advance() +5. **Handle Wrap-Around**: Ensure complete K-axis coverage + +### Method Selection Guide + +- **Method 1 (Fusion Approach)**: Recommended - optimized for fusion with simplest code structure +- **Method 2 (Two-Phase)**: Alternative - clearer separation when needed + +## Use Cases + +### When to Use K-Axis Offset + +1. **Large K Dimension**: When K is significantly larger than BLOCK_SIZE_K +2. **Memory-Bound Operations**: When memory access is the bottleneck +3. **Multi-Core Systems**: When utilizing multiple NPU cores +4. **Regular GEMM**: Standard matrix multiplication without special patterns + +### When NOT to Use + +1. **Small K Dimension**: When K is close to BLOCK_SIZE_K +2. **Irregular Access Patterns**: When K-axis access is already optimized +3. **Single-Core Execution**: No benefit with single core + +## Implementation Checklist + +- [ ] Calculate `k_offset` using `k_offset = (2 * block_idx) % num_k_blocks` +- [ ] Initialize pointers appropriately based on chosen method +- [ ] Implement cyclic K-axis traversal +- [ ] Handle wrap-around correctly +- [ ] Ensure complete K-axis coverage +- [ ] Verify correctness with allclose test + +### Method-Specific Requirements + +#### Method 1 (Fusion Approach) +- [ ] Create new pointers per iteration +- [ ] Use current_k directly for offsets + +#### Method 2 (Two-Phase) +- [ ] Calculate phase lengths manually +- [ ] Use `tl.advance()` for both phases + +## Common Pitfalls + +### 1. Missing Wrap-Around Logic + +**Wrong**: +```python +for k_iter in range(num_k_blocks): + k_idx = (k_iter + k_offset) % num_k_blocks + current_k = k_idx * BLOCK_SIZE_K + # Always advance, even when wrapping around + a_ptr = tl.advance(a_ptr, (0, BLOCK_SIZE_K)) +``` + +**Correct**: +```python +for k_iter in range(num_k_blocks): + k_idx = (k_iter + k_offset) % num_k_blocks + current_k = k_idx * BLOCK_SIZE_K + + if k_iter > 0 and current_k == 0: + # Recreate pointers at 0 + a_ptr = tl.make_block_ptr(..., offsets=(..., 0), ...) + + # Only advance when not wrapping + if k_iter < num_k_blocks - 1: + a_ptr = tl.advance(a_ptr, (0, BLOCK_SIZE_K)) +``` + +### 2. Incorrect Offset Calculation + +**Wrong**: +```python +k_offset = block_idx * BLOCK_SIZE_K # Can exceed K +``` + +**Correct**: +```python +num_k_blocks = tl.cdiv(K, BLOCK_SIZE_K) +k_offset = (2 * block_idx) % num_k_blocks # Always within [0, num_k_blocks) +``` + +### 3. Not Using tl.advance() + +**Wrong** (violates checklist): +```python +for k_iter in range(num_k_blocks): + k_idx = (k_iter + k_offset) % num_k_blocks + current_k = k_idx * BLOCK_SIZE_K + a_ptr = tl.make_block_ptr(..., offsets=(..., current_k), ...) + # Always recreate pointers +``` + +**Correct** (satisfies checklist): +```python +# Use advance for forward movement +a_ptr = tl.advance(a_ptr, (0, BLOCK_SIZE_K)) +# Only recreate when necessary +if k_iter > 0 and current_k == 0: + a_ptr = tl.make_block_ptr(..., offsets=(..., 0), ...) +``` + +## Integration with Existing Code + +### Step-by-Step Integration + +1. **Identify K-loop**: Find the K-axis loop in your GEMM kernel +2. **Calculate Offset**: Add `num_k_blocks = tl.cdiv(K, BLOCK_SIZE_K)` and `k_offset = (2 * block_idx) % num_k_blocks` +3. **Initialize Accumulator**: Create zero-initialized accumulator +4. **Modify Loop Structure**: Change from simple K-loop to cyclic traversal +5. **Implement Fusion Approach**: Create new pointers per iteration with current_k +6. **Test**: Verify correctness and performance + +### Example Integration + +**Before** (standard GEMM): +```python +for k in range(0, K, BLOCK_SIZE_K): + a_val = tl.load(a_ptr, boundary_check=(0, 1)) + b_val = tl.load(b_ptr, boundary_check=(0, 1)) + acc += tl.dot(a_val, b_val, out_dtype=tl.int32) + a_ptr = tl.advance(a_ptr, (0, BLOCK_SIZE_K)) + b_ptr = tl.advance(b_ptr, (BLOCK_SIZE_K, 0)) +``` + +**After** (K-axis offset - Fusion Approach): +```python +num_k_blocks = tl.cdiv(K, BLOCK_SIZE_K) +k_offset = (2 * block_idx) % num_k_blocks +acc = tl.zeros((BLOCK_SIZE_M, BLOCK_SIZE_N), dtype=tl.int32) + +for k_iter in range(num_k_blocks): + k_idx = (k_iter + k_offset) % num_k_blocks + current_k = k_idx * BLOCK_SIZE_K + + # Create new pointers with current offset each iteration + a_ptr = tl.make_block_ptr( + base=a, + shape=(M, K), + strides=(stride_am, stride_ak), + offsets=(block_m * BLOCK_SIZE_M, current_k), + block_shape=(BLOCK_SIZE_M, BLOCK_SIZE_K), + order=(1, 0), + ) + + b_ptr = tl.make_block_ptr( + base=b, + shape=(K, N), + strides=(stride_bk, stride_bn), + offsets=(current_k, block_n * BLOCK_SIZE_N), + block_shape=(BLOCK_SIZE_K, BLOCK_SIZE_N), + order=(1, 0), + ) + + a_val = tl.load(a_ptr, boundary_check=(0, 1)) + b_val = tl.load(b_ptr, boundary_check=(0, 1)) + acc += tl.dot(a_val, b_val, out_dtype=tl.int32) +``` + +## Advanced Topics + +### Tuning Parameters + +1. **BLOCK_SIZE_K**: Larger values reduce loop iterations but may increase register pressure +2. **CORE_NUM**: Should match hardware core count for optimal parallelism +3. **Offset Granularity**: Can adjust offset calculation for different access patterns + +### Performance Results + +Experimental results on M=128, N=4096, K=7168 matrix multiplication: + +| Configuration | K offset Calculation | Task Duration (us) | Performance Improvement | +|--------------|---------------------|-------------------|------------------------| +| Without K offset | Standard K-loop | 69.98 | Baseline | +| With K offset | `(2 * block_idx) % num_k_blocks` | 62.32 | **11% faster** | + +The modulo operation with multiplier 2 in the offset calculation provides better performance by reducing memory access conflicts. + +### Combining with Other Optimizations + +K-axis offset can be combined with: +- Split-K parallelization +- Double buffering +- Pipeline optimization +- Memory coalescing + +### Debugging Tips + +1. **Print current_k**: Verify wrap-around behavior +2. **Check coverage**: Ensure all K positions are visited +3. **Validate offsets**: Confirm pointer positions are correct +4. **Monitor performance**: Compare with baseline implementation + +## References + +- Triton Programming Guide: https://triton-lang.org/main/index.html +- Ascend NPU Documentation: https://ascend.github.io/triton-ascend/ +- GEMM Optimization Techniques: See `reference/operator_examples/` directory + +## Version History + +- **v1.0** (2026-04-14): Initial version with two-phase approach +- **v1.1** (2026-04-14): Unified loop with hybrid pointer management +- **v1.2** (2026-04-14): Added comprehensive documentation and examples +- **v1.3** (2026-04-14): Updated to use fusion approach as recommended method +- **v1.4** (2026-04-25): Updated to use `(2 * block_idx) % num_k_blocks` formula for offset calculation + +## License + +This optimization technique is provided for use in Triton-Ascend projects. Please refer to the project license for usage terms. \ No newline at end of file diff --git a/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/README.md b/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/README.md new file mode 100644 index 00000000..f8516458 --- /dev/null +++ b/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/README.md @@ -0,0 +1,64 @@ +# Matmul Code Generator + +特别注意,需要环境中事先安装好 `msprof op`(强调不是 `msprof`)。 + +## 使用方法 + +使用方式有 2 种: + +**1. 单shape测试**(单个shape约需20~30分钟,例如 M=128 N=7168 K=4096 性能约为57us): + +直接在终端执行: + +``` +请按照 SKILL.md 生成 M=128 N=7168 K=4096 的 FP16 高性能算子 +或 请按照 SKILL.md 生成 M=128 N=7168 K=4096 的 FP16 ND格式算子 +或 请按照 SKILL.md 生成 M=128 N=7168 K=4096 的 INT8 高性能算子 +或 请按照 SKILL.md 生成 M=128 N=7168 K=4096 的 INT8 ND格式算子 +``` + +**2. 多shape测试**(使用 `shape_list.md` 中的 shape 列表逐一测试): + +直接在终端执行: + +``` +请按照 SKILL.md 生成 FP16 高性能算子,且请使用 shape_list 中的 shape 进行测试 +或 请按照 SKILL.md 生成 FP16 ND格式算子,且请使用 shape_list 中的 shape 进行测试 +或 请按照 SKILL.md 生成 INT8 高性能算子,且请使用 shape_list 中的 shape 进行测试 +或 请按照 SKILL.md 生成 INT8 ND格式算子,且请使用 shape_list 中的 shape 进行测试 +``` + +代码和测试报告会存储在 `output` 文件夹下。 + +## 服务器配置 + +编辑 `script/server_config.json`: + +```json +{ + "ip": "你的服务器IP", + "username": "root", + "auth_method": "key", + "password": "", + "ssh_key_path": "你的密钥文件路径", + "docker_container": "容器名称", + "host_temp_dir": "/tmp/triton_upload", + "docker_working_dir": "/root/MyAICode", + "npu_device": "NPU设备ID" +} +``` + +| 字段 | 说明 | +|------|------| +| `ip` | 服务器 IP 地址 | +| `auth_method` | `"password"` 密码认证 或 `"key"` 密钥认证 | +| `password` | 密码认证时填写 | +| `ssh_key_path` | 密钥认证时填写 .pem 文件路径 | +| `docker_container` | Docker 容器名称 | +| `npu_device` | NPU 设备 ID(0-7) | + +配置完成后运行检测: + +```bash +python script/check_config.py +``` diff --git a/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/SKILL.md b/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/SKILL.md new file mode 100644 index 00000000..cb02c740 --- /dev/null +++ b/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/SKILL.md @@ -0,0 +1,202 @@ +--- +name: "matmul-code-generator" +description: "Generate high-performance Triton matmul kernels (FP16/INT8, standard ND or ND2NZ input format). Invoke when user wants to create or modify matmul kernel code with various optimization strategies (tiling, koffset, diagonal, a_fuse/w_fuse/aw_fuse)." +--- + +# Matmul 代码生成器 + +特别注意,需要环境中事先安装好 `msprof op`(强调不是 `msprof`)。 + +生成高性能 Triton 矩阵乘法 Kernel,支持 FP16/INT8 两种精度 × 标准 ND / ND2NZ 两种输入格式,含 tiling、koffset、diagonal、a_fuse/w_fuse/aw_fuse 等优化策略。 + +## 🔄 Workflow + +严格按顺序执行,每步成功后再进入下一步,失败则重试。 + +``` +Step 0: CONFIG_CHECK (自动检测) + 🔍 **自动检测**: 检查 script/server_config.json 是否存在且有效 + + 检测命令: + ```bash + python script/check_config.py + ``` + + - ✅ 配置已存在且有效 → 跳过配置,直接进入 Step 1 + - ❌ 配置不存在或无效 → 按下方模板配置后重新检测 + + 测试 SSH 连接 (可选): + ```bash + python script/check_config.py --test-connection + ``` + + 配置模板 (仅首次或配置变更时需要): + + 方式1: 密码认证 (推荐新手使用) + ```json + { + "ip": "你的服务器IP", + "username": "root", + "auth_method": "password", + "password": "你的密码", + "docker_container": "容器名称", + "npu_device": "NPU设备ID" + } + ``` + + 方式2: 密钥认证 (推荐生产环境) + ```json + { + "ip": "你的服务器IP", + "username": "root", + "auth_method": "key", + "password": "", + "ssh_key_path": "密钥文件路径", + "docker_container": "容器名称", + "npu_device": "NPU设备ID" + } + ``` + +Step 1: CLEAN + python script/server_check.py clean + 验证: 服务器 /root/MyAICode/batch_verification/ 已删除 + +Step 2: UPLOAD + START + # 启动上传(verify_code.py 在启动时初始化 script/.upload_status.json 为 {"status": "false"}, + # 全部上传+启动完成后自动设为 {"status": "true"}) + python script/verify_code.py --code-subdir --server-config script/server_config.json --shape "" --npu-device + 或 + python script/verify_code.py --code-subdir --server-config script/server_config.json --shape-list shape_list.md --npu-device + + ⚠️ **Repeatedly execute** the following command until the `status` field in `script/.upload_status.json` becomes `"true"`: + + ``` + python script/check_file_exist.py --code-subdir + ``` + + Once `status` is confirmed as `"true"`, proceed with subsequent startup steps. + + **⚠️ CRITICAL: Do NOT perform any other operations during this polling/monitoring process. Focus exclusively on running the command above in a loop until verification succeeds. Repeat this polling cycle no more than 100 times; stop if the limit is reached.** + +Step 3: VERIFY + python script/server_check.py status + 验证: 输出包含 "python.*batch_verification" 进程 + +--- 直接退出,等待用户自行操作 --- +--- 用户自行操作 --- + 查看进度: python script/server_check.py progress + 下载结果: python script/analyze_results.py → output/ +``` + +## 📁 项目结构 + +``` +├── SKILL.md # 本文件 +├── code_lib.zip # 所有 kernel 代码 (上传到服务器) +├── shape_list.md # Shape 列表模板 +└── script/ + ├── verify_code.py # 主入口: clean + 上传 + 启动测试 + ├── batch_verification.py # 服务器端批量测试 (自动运行) + ├── server_check.py # 查看状态/进度/结果/clean/kill + ├── analyze_results.py # 下载最优代码 + 生成 Excel + ├── check_config.py # 配置检查 + ├── check_file_exist.py # 上传状态轮询 + ├── reorder_excel.py # Excel 排序 + ├── server_config.json # 服务器连接配置 + └── .upload_status.json # 上传状态标记 +``` + +> **注意**: `code_lib.zip` 解压后包含 `code-fp16/`、`code-fp16-fuse/`、`code-int8/`、`code-int8-fuse/` 四个子目录,对应四种 kernel 变体。运行时需通过 `--code-subdir` 指定要测试的目录。 + +## 🔧 配置 + +`script/server_config.json`: +```json +{ + "ip": "你的服务器IP", + "username": "root", + "auth_method": "key", + "password": "", + "ssh_key_path": "你的密钥文件路径", + "docker_container": "你的容器名", + "npu_device": "5" +} +``` + +**认证方式说明:** +- `auth_method`: `"password"` 使用密码认证,`"key"` 使用密钥认证 +- `username`: SSH 用户名,默认为 `"root"` +- `password`: 当 `auth_method="password"` 时填写密码 +- `ssh_key_path`: 当 `auth_method="key"` 时填写密钥文件路径 + +测试 SSH: +- 密码方式: `ssh root@你的服务器IP` +- 密钥方式: `ssh -i 你的密钥文件路径 root@你的服务器IP` + +## 🎯 四个任务 → 参数映射 + +| 用户需求 | `--code-subdir` | 精度 | 格式 | 文件 | +|----------|-----------------|------|------|------| +| 生成 FP16 高性能 matmul | `code-fp16` | FP16 | 伪NZ | 36 | +| 生成 FP16 ND 格式 matmul | `code-fp16-fuse` | FP16 | ND + 融合 | 72 | +| 生成 INT8 高性能 matmul | `code-int8` | INT8 | 伪NZ | 36 | +| 生成 INT8 ND 格式 matmul | `code-int8-fuse` | INT8 | ND + 融合 | 72 | + +## 📋 脚本 I/O 说明 + +### verify_code.py — 主入口 + +| 参数 | 必需 | 取值 | +|------|------|------| +| `--code-subdir` | ✅ | `code-fp16` / `code-fp16-fuse` / `code-int8` / `code-int8-fuse` | +| `--server-config` | ✅ | `script/server_config.json` | +| `--shape` | 二选一 | `"M N K"` 如 `"128 4096 7168"` | +| `--shape-list` | 二选一 | `shape_list.md` | +| `--npu-device` | ❌ | 0-7,默认取 config | +| `--pattern` | ❌ | 默认 `*.py`,如 `"gemm*.py"` | + +输入: code_lib.zip + batch_verification.py + (shape_list.md) +输出: 服务器后台启动 batch_verification → 生成 results/ 目录 + +### server_check.py — 状态/进度 + +```bash +python script/server_check.py clean # 删除服务器整个 batch_verification 目录 +python script/server_check.py status # 查看测试进程是否在运行 +python script/server_check.py progress # 查看日志末尾 + 结果目录文件数 +python script/server_check.py results # 列出已生成的结果目录 +python script/server_check.py summary # 查看 summary.json +python script/server_check.py durations # 按性能排序显示所有 kernel +python script/server_check.py kill # 安全停止当前 NPU 上的测试进程 +``` + +### analyze_results.py — 下载结果 + +输入: 服务器 `/root/MyAICode/batch_verification/results/summary.json` +输出 (到本地 `output/`): +- `best_kernels_report.xlsx` — 每个 shape 最优 kernel 一行 (Shape / M/N/K / Duration / Kernel File / Kernel Name) +- `*.py` — 所有最优 kernel 源代码 + +### batch_verification.py — 服务器端 (无需手动调用) + +由 verify_code.py 自动启动。扫描 codes//*.py,用 msprof 逐个测试,生成 AAAA.json / summary.json。 + +## 📝 Shape 列表格式 + +`shape_list.md` 每行一个 shape,空格或逗号分隔,支持 `#` 注释: + +``` +128 4096 7168 +256,8192,14336 +# LLM 推理 +1 4096 4096 +``` + +## ❓ FAQ + +| 问题 | 解决 | +|------|------| +| SSH 连接失败 | `chmod 600 密钥文件路径` | +| code_lib.zip 不存在 | 确保项目根目录有 `code_lib.zip` | +| 测试太慢 | 减少 shape_list 中的 shape 数量;用 `--pattern` 过滤 kernel | +| 中断测试 | `python script/server_check.py kill` | diff --git a/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/code_lib.zip b/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/code_lib.zip new file mode 100644 index 0000000000000000000000000000000000000000..02948284d20a1bc7d2dcf9386c4ad27575000b37 GIT binary patch literal 441482 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ⅇ*i?3H@C+hp4SMc7&1y#iGRQQ_qdsXb32Asm@n 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

wbUP|G}dvoz&_}!$2axB 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 W<|8&&DU|2Le-C3Ql%(<9fBYXVWZK#Q literal 0 HcmV?d00001 diff --git a/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/.upload_status.json b/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/.upload_status.json new file mode 100644 index 00000000..a8a6bbe9 --- /dev/null +++ b/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/.upload_status.json @@ -0,0 +1 @@ +{"status": "true"} \ No newline at end of file diff --git a/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/analyze_results.py b/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/analyze_results.py new file mode 100644 index 00000000..31bf8dbf --- /dev/null +++ b/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/analyze_results.py @@ -0,0 +1,178 @@ +#!/usr/bin/env python3 +""" +分析测试结果 — 单shape / 多shape 通用 +产出到 output/: + - best_kernels_report.xlsx 每个shape最优kernel汇总 + - *.py 所有最优kernel代码 +""" +import paramiko +import json +import os +import shutil +from openpyxl import Workbook +from openpyxl.styles import Font, PatternFill, Alignment + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) +OUTPUT_DIR = os.path.join(os.path.dirname(SCRIPT_DIR), 'output') + +with open(os.path.join(SCRIPT_DIR, 'server_config.json')) as f: + config = json.load(f) + +CONTAINER = config['docker_container'] +RESULTS = '/root/MyAICode/batch_verification/results' +CODES = '/root/MyAICode/batch_verification/codes' + +def ssh_cmd(ssh, cmd): + stdin, stdout, stderr = ssh.exec_command(f'docker exec {CONTAINER} bash -c "{cmd}"', timeout=30) + return stdout.read().decode('utf-8'), stderr.read().decode('utf-8') + +def get_summary(ssh): + out, _ = ssh_cmd(ssh, f'cat {RESULTS}/summary.json 2>/dev/null') + if not out.strip(): + return None + return json.loads(out) + +def get_shape_summary(ssh, shape): + filename = f'summary_M{shape["M"]}_N{shape["N"]}_K{shape["K"]}.json' + out, _ = ssh_cmd(ssh, f'cat {RESULTS}/{filename} 2>/dev/null') + if not out.strip(): + return None + return json.loads(out) + +def download_kernel(ssh, filename): + cmd = f'find {CODES} -name "{filename}" -exec cat {{}} \\;' + out, _ = ssh_cmd(ssh, cmd) + if not out.strip(): + return None + local = os.path.join(OUTPUT_DIR, filename) + with open(local, 'w', encoding='utf-8') as f: + f.write(out) + return local + +def generate_excel(best_kernels): + path = os.path.join(OUTPUT_DIR, 'best_kernels_report.xlsx') + wb = Workbook() + ws = wb.active + ws.title = "Best Kernels" + + headers = ["Shape", "M", "N", "K", "Task Duration (us)", "Passed", "Kernel File", "Kernel Name"] + ws.append(headers) + header_fill = PatternFill(start_color="4472C4", end_color="4472C4", fill_type="solid") + header_font = Font(bold=True, color="FFFFFF") + for cell in ws[1]: + cell.fill = header_fill + cell.font = header_font + cell.alignment = Alignment(horizontal="center", vertical="center") + + for item in best_kernels: + s = item['shape'] + k = item['kernel'] + ws.append([ + f"M={s['M']}, N={s['N']}, K={s['K']}" if s else "default", + s['M'] if s else "", s['N'] if s else "", s['K'] if s else "", + k['duration'], k['passed'], k['file'], k['kernel'] + ]) + + for col in ws.columns: + max_len = max((len(str(c.value or '')) for c in col), default=0) + ws.column_dimensions[col[0].column_letter].width = min(max_len + 2, 50) + + wb.save(path) + return path + +ssh = paramiko.SSHClient() +ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) +ssh.connect(hostname=config['ip'], username='root', key_filename=config['ssh_key_path'], timeout=30) + +try: + summary = get_summary(ssh) + if not summary: + print('No summary.json found on server') + exit(1) + + if os.path.exists(OUTPUT_DIR): + shutil.rmtree(OUTPUT_DIR) + os.makedirs(OUTPUT_DIR, exist_ok=True) + + total_shapes = summary.get('total_shapes', 1) + all_results = summary.get('results', []) + + best_kernels = [] + + if total_shapes == 1 and all_results: + shape = all_results[0].get('shape') if all_results else None + passed = [r for r in all_results if r.get('passed')] + passed.sort(key=lambda r: r['duration']) + best = passed[0] if passed else None + if best: + best_kernels.append({'shape': shape, 'kernel': best}) + + print("=" * 95) + print("测试结果统计") + print("=" * 95) + total = summary.get('total_tests', len(all_results)) + p = summary.get('total_passed', len(passed)) + f = summary.get('total_failed', total - p) + print(f"总共测试kernel数量: {total}") + print(f"通过测试kernel数量: {p}") + print(f"失败测试kernel数量: {f}") + print(f"通过率: {p/total*100:.2f}%" if total else "") + print() + + print("=" * 95) + print("最优Kernel") + print("=" * 95) + print(f"{'Rank':<6} {'File':<70} {'Duration(us)':<15}") + print("=" * 95) + for i, r in enumerate(passed[:1], 1): + print(f"{i:<6} {r['file']:<70} {r['duration']:<15.2f}") + print("=" * 95) + else: + for shape in summary.get('shapes', []): + if shape is None: + continue + ss = get_shape_summary(ssh, shape) + if not ss: + continue + results = ss.get('results', []) + passed = [r for r in results if r.get('passed')] + if not passed: + continue + passed.sort(key=lambda r: r['duration']) + best_kernels.append({'shape': shape, 'kernel': passed[0]}) + + print("=" * 95) + print("多Shape测试结果分析") + print("=" * 95) + print(f"总Shape数: {len(best_kernels)}") + print(f"总测试数: {summary.get('total_tests','?')}") + print(f"总通过数: {summary.get('total_passed','?')}") + print(f"总失败数: {summary.get('total_failed','?')}") + + if not best_kernels: + print("\n没有找到通过测试的kernel") + exit(0) + + print() + print("=" * 95) + print("各Shape最优Kernel") + print("=" * 95) + for item in best_kernels: + s = item['shape'] + k = item['kernel'] + print(f" M={s['M']}, N={s['N']}, K={s['K']} | {k['file']} | {k['duration']:.2f} us") + + print(f"\n正在从服务器下载最优kernel代码到 {OUTPUT_DIR} ...") + for item in best_kernels: + local = download_kernel(ssh, item['kernel']['file']) + if local: + print(f" ✓ {item['kernel']['file']}") + else: + print(f" ✗ {item['kernel']['file']} (failed)") + + excel = generate_excel(best_kernels) + print(f"\n✓ Excel报告: {excel}") + print("✓ 完成") + +finally: + ssh.close() diff --git a/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/batch_verification.py b/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/batch_verification.py new file mode 100644 index 00000000..5f557ca2 --- /dev/null +++ b/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/batch_verification.py @@ -0,0 +1,341 @@ +#!/usr/bin/env python3 +""" +Batch verification script - runs on server +Scans multiple kernel code files and executes msprof op for each one +""" + +import os +import subprocess +import json +import re +import ast +import argparse +import glob +import difflib +from datetime import datetime + + +def extract_kernel_name(code_content, filename): + """Extract kernel name from code using AST parsing""" + kernel_names = [] + try: + tree = ast.parse(code_content) + for node in ast.walk(tree): + if isinstance(node, ast.FunctionDef): + has_triton_jit = False + for decorator in node.decorator_list: + if isinstance(decorator, ast.Attribute): + if decorator.attr == 'jit': + if isinstance(decorator.value, ast.Name) and decorator.value.id == 'triton': + has_triton_jit = True + elif isinstance(decorator, ast.Name) and decorator.id == 'jit': + has_triton_jit = True + elif isinstance(decorator, ast.Call): + if isinstance(decorator.func, ast.Attribute): + if decorator.func.attr == 'jit': + if isinstance(decorator.func.value, ast.Name) and decorator.func.value.id == 'triton': + has_triton_jit = True + if has_triton_jit: + kernel_names.append(node.name) + except SyntaxError as e: + print(f'AST parse error: {e}') + + if not kernel_names: + return None + if len(kernel_names) == 1: + return kernel_names[0] + + base_filename = os.path.splitext(os.path.basename(filename))[0] + best_name = None + best_ratio = -1 + for name in kernel_names: + ratio = difflib.SequenceMatcher(None, base_filename, name).ratio() + if ratio > best_ratio: + best_ratio = ratio + best_name = name + return best_name + + +def replace_shape_in_code(code_content, M, N, K): + """Replace M, N, K values in the main() function""" + patterns = [ + (r'(\n M = )\d+', rf'\g<1>{M}'), + (r'(\n N = )\d+', rf'\g<1>{N}'), + (r'(\n K = )\d+', rf'\g<1>{K}'), + ] + + modified_code = code_content + for pattern, replacement in patterns: + modified_code = re.sub(pattern, replacement, modified_code) + + return modified_code + + +def run_single_kernel(code_file, work_dir, output_dir, npu_device, shape=None): + """Run verification for a single kernel code file""" + filename = os.path.basename(code_file) + kernel_name = os.path.splitext(filename)[0] + + if shape: + M, N, K = shape + result_dirname = f"{kernel_name}_M{M}_N{N}_K{K}" + else: + result_dirname = kernel_name + + result_dir = os.path.join(output_dir, result_dirname) + os.makedirs(result_dir, exist_ok=True) + + stdout_file = os.path.join(result_dir, 'stdout.txt') + stderr_file = os.path.join(result_dir, 'stderr.txt') + aaaa_file = os.path.join(result_dir, 'AAAA.json') + + with open(code_file, 'r') as f: + original_code = f.read() + + extracted_kernel = extract_kernel_name(original_code, code_file) + if extracted_kernel: + kernel_name = extracted_kernel + + code_modified = original_code + + if shape: + M, N, K = shape + code_modified = replace_shape_in_code(code_modified, M, N, K) + + device_setting = f"import torch\ntorch.npu.set_device({npu_device})\n" + code_with_device = code_modified.replace('import torch\n', device_setting, 1) + + temp_code_file = os.path.join(work_dir, f'temp_{filename}') + with open(temp_code_file, 'w') as f: + f.write(code_with_device) + + start_time = datetime.now().strftime('%H:%M:%S') + + with open(aaaa_file, 'w') as f: + aaaa_data = {'status': 'in_progress', 'passed': None, 'start_time': start_time} + if shape: + aaaa_data['shape'] = {'M': shape[0], 'N': shape[1], 'K': shape[2]} + json.dump(aaaa_data, f) + + env = os.environ.copy() + env['ASCEND_VISIBLE_DEVICES'] = npu_device + + cmd = f'PS1=dummy && source /root/.bashrc && export ASCEND_VISIBLE_DEVICES={npu_device} && msprof op --output={result_dir} --kernel-name={kernel_name} python {temp_code_file}' + + shape_str = f" (M={shape[0]}, N={shape[1]}, K={shape[2]})" if shape else "" + print(f'[{start_time}] Running: {filename}{shape_str} (kernel: {kernel_name})') + result = subprocess.run(cmd, shell=True, capture_output=True, text=True, executable='/bin/bash', env=env) + + with open(stdout_file, 'w') as f: + f.write(result.stdout) + with open(stderr_file, 'w') as f: + f.write(result.stderr) + + stdout_content = result.stdout + stderr_content = result.stderr + + passed = 'Test passed!' in stdout_content + + task_duration_match = re.search(r'Task Duration\(us\):\s*([0-9.]+)', stdout_content) + task_duration = float(task_duration_match.group(1)) if task_duration_match else 999999 + + end_time = datetime.now().strftime('%H:%M:%S') + + data = { + 'status': 'completed', + 'passed': passed, + 'start_time': start_time, + 'end_time': end_time, + 'task_duration': task_duration, + 'kernel_name': kernel_name, + 'code_file': filename, + 'stdout': stdout_content, + 'stderr': stderr_content + } + + if shape: + data['shape'] = {'M': shape[0], 'N': shape[1], 'K': shape[2]} + + with open(aaaa_file, 'w') as f: + json.dump(data, f, indent=2) + + status = 'PASSED' if passed else 'FAILED' + print(f'[{end_time}] {status}: {filename}{shape_str} (duration: {task_duration} us)') + + os.remove(temp_code_file) + + return passed, task_duration, kernel_name + + +def parse_shape(shape_str): + """Parse shape string like '128 4096 7168' (or '128,4096,7168') to (M, N, K)""" + if not shape_str: + return None + # Try splitting by space first, then comma for backward compatibility + parts = shape_str.split() + if len(parts) != 3: + parts = shape_str.split(',') + if len(parts) != 3: + raise ValueError(f"Invalid shape format: {shape_str}. Expected 'M N K' or 'M,N,K'") + return (int(parts[0]), int(parts[1]), int(parts[2])) + + +def parse_shape_list_file(file_path): + """Parse shape list from a file, returns list of (M, N, K) tuples""" + shapes = [] + with open(file_path, 'r') as f: + for line in f: + line = line.strip() + # Skip empty lines and comments + if not line or line.startswith('#') or line.startswith('```'): + continue + try: + shape = parse_shape(line) + shapes.append(shape) + except: + continue + return shapes + + +def main(): + parser = argparse.ArgumentParser(description='Batch verification script for multiple kernel codes') + parser.add_argument('--code-dir', required=True, help='Directory containing all kernel code subdirectories') + parser.add_argument('--code-subdir', required=True, help='Which subdirectory to test (e.g., code-fp16, code-fp16-fuse)') + parser.add_argument('--work-dir', default='/root/MyAICode/batch_verification', help='Working directory') + parser.add_argument('--output-dir', default='/root/MyAICode/batch_verification/results', help='Output directory') + parser.add_argument('--npu-device', default='0', help='NPU device ID') + parser.add_argument('--pattern', default='*.py', help='File pattern to match (default: *.py)') + parser.add_argument('--shape', default=None, help='Matrix shape as M N K (e.g., "128 4096 7168")') + parser.add_argument('--shape-list', default=None, help='File containing list of shapes (one per line)') + args = parser.parse_args() + + CODE_DIR = os.path.join(args.code_dir, args.code_subdir) + WORK_DIR = args.work_dir + OUTPUT_DIR = args.output_dir + NPU_DEVICE = args.npu_device + PATTERN = args.pattern + + # Parse shapes: either from --shape or from --shape-list + SHAPES = [] + if args.shape: + SHAPES = [parse_shape(args.shape)] + elif args.shape_list: + SHAPES = parse_shape_list_file(args.shape_list) + + # If no shapes specified, use None (use shape from code) + if not SHAPES: + SHAPES = [None] + + os.makedirs(WORK_DIR, exist_ok=True) + os.makedirs(OUTPUT_DIR, exist_ok=True) + + code_files = sorted(glob.glob(os.path.join(CODE_DIR, PATTERN))) + + if not code_files: + print(f'No code files found in {CODE_DIR} with pattern {PATTERN}') + return + + print(f'Found {len(code_files)} code files in {CODE_DIR}') + print(f'NPU Device: {NPU_DEVICE}') + print(f'Number of shapes to test: {len(SHAPES)}') + for i, shape in enumerate(SHAPES, 1): + if shape: + print(f' Shape {i}: M={shape[0]}, N={shape[1]}, K={shape[2]}') + else: + print(f' Shape {i}: (using shape from code)') + print(f'Output directory: {OUTPUT_DIR}') + print('=' * 60) + + all_results = [] + total_passed = 0 + total_failed = 0 + + for shape_idx, shape in enumerate(SHAPES, 1): + print(f'\n{"=" * 60}') + if shape: + print(f'TESTING SHAPE {shape_idx}/{len(SHAPES)}: M={shape[0]}, N={shape[1]}, K={shape[2]}') + else: + print(f'TESTING SHAPE {shape_idx}/{len(SHAPES)}: (using shape from code)') + print('=' * 60) + + shape_results = [] + shape_passed = 0 + shape_failed = 0 + + for code_idx, code_file in enumerate(code_files, 1): + print(f'\n[{shape_idx}/{len(SHAPES)}][{code_idx}/{len(code_files)}] Processing: {os.path.basename(code_file)}') + passed, duration, kernel_name = run_single_kernel(code_file, WORK_DIR, OUTPUT_DIR, NPU_DEVICE, shape) + + result_entry = { + 'file': os.path.basename(code_file), + 'kernel': kernel_name, + 'passed': passed, + 'duration': duration + } + if shape: + result_entry['shape'] = {'M': shape[0], 'N': shape[1], 'K': shape[2]} + shape_results.append(result_entry) + all_results.append(result_entry) + + if passed: + shape_passed += 1 + total_passed += 1 + else: + shape_failed += 1 + total_failed += 1 + + # Save per-shape summary + if shape: + shape_summary_file = os.path.join(OUTPUT_DIR, f'summary_M{shape[0]}_N{shape[1]}_K{shape[2]}.json') + else: + shape_summary_file = os.path.join(OUTPUT_DIR, 'summary_default.json') + + shape_summary = { + 'total': len(code_files), + 'passed': shape_passed, + 'failed': shape_failed, + 'npu_device': NPU_DEVICE, + 'timestamp': datetime.now().isoformat(), + 'results': shape_results + } + + if shape: + shape_summary['shape'] = {'M': shape[0], 'N': shape[1], 'K': shape[2]} + + with open(shape_summary_file, 'w') as f: + json.dump(shape_summary, f, indent=2) + + print(f'\nShape {shape_idx} summary:') + print(f' Total: {len(code_files)}') + print(f' Passed: {shape_passed}') + print(f' Failed: {shape_failed}') + print(f' Summary saved to: {shape_summary_file}') + + # Save overall summary + summary_file = os.path.join(OUTPUT_DIR, 'summary.json') + summary = { + 'total_shapes': len(SHAPES), + 'shapes': [{'M': s[0], 'N': s[1], 'K': s[2]} if s else None for s in SHAPES], + 'total_tests': len(SHAPES) * len(code_files), + 'total_passed': total_passed, + 'total_failed': total_failed, + 'npu_device': NPU_DEVICE, + 'timestamp': datetime.now().isoformat(), + 'results': all_results + } + + with open(summary_file, 'w') as f: + json.dump(summary, f, indent=2) + + print('\n' + '=' * 60) + print('BATCH VERIFICATION SUMMARY (ALL SHAPES)') + print('=' * 60) + print(f'Total shapes: {len(SHAPES)}') + print(f'Total tests: {len(SHAPES) * len(code_files)}') + print(f'Total passed: {total_passed}') + print(f'Total failed: {total_failed}') + print(f'Overall summary saved to: {summary_file}') + + +if __name__ == '__main__': + main() diff --git a/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/check_config.py b/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/check_config.py new file mode 100644 index 00000000..45ac7dad --- /dev/null +++ b/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/check_config.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python3 +""" +配置检查脚本 - 检测服务器配置文件是否存在且有效 + +使用方法: +python script/check_config.py # 检查配置文件 +python script/check_config.py --test-connection # 测试 SSH 连接 +""" + +import json +import sys +import os +import argparse +from pathlib import Path + +REQUIRED_FIELDS = ['ip', 'username', 'auth_method', 'docker_container', 'npu_device'] + +def check_config_exists(config_path): + """检查配置文件是否存在""" + return os.path.exists(config_path) + +def validate_config(config): + """验证配置文件内容""" + errors = [] + + for field in REQUIRED_FIELDS: + if field not in config: + errors.append(f"缺少必填字段: {field}") + + if 'auth_method' in config: + auth_method = config['auth_method'] + if auth_method == 'password': + if not config.get('password'): + errors.append("密码认证方式需要填写 'password' 字段") + elif auth_method == 'key': + if not config.get('ssh_key_path'): + errors.append("密钥认证方式需要填写 'ssh_key_path' 字段") + elif not os.path.exists(config['ssh_key_path']): + errors.append(f"密钥文件不存在: {config['ssh_key_path']}") + else: + errors.append(f"不支持的认证方式: {auth_method} (应为 'password' 或 'key')") + + return errors + +def test_connection(config): + """测试 SSH 连接""" + try: + import paramiko + except ImportError: + print("❌ 错误: 未安装 paramiko 库,请运行: pip install paramiko") + return False + + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + + try: + auth_method = config.get('auth_method', 'key') + username = config.get('username', 'root') + + print(f"正在连接 {config['ip']}...") + + if auth_method == 'password': + ssh.connect( + hostname=config['ip'], + username=username, + password=config.get('password'), + port=22, + timeout=15 + ) + else: + ssh.connect( + hostname=config['ip'], + username=username, + key_filename=config['ssh_key_path'], + port=22, + timeout=15 + ) + + print("✅ SSH 连接成功!") + + if config.get('docker_container'): + stdin, stdout, stderr = ssh.exec_command( + f"docker inspect {config['docker_container']}", + timeout=10 + ) + if stdout.read(): + print(f"✅ Docker 容器 '{config['docker_container']}' 存在") + else: + print(f"⚠️ 警告: Docker 容器 '{config['docker_container']}' 不存在或无法访问") + + ssh.close() + return True + + except paramiko.AuthenticationException: + print("❌ 认证失败: 请检查用户名和密码/密钥") + return False + except paramiko.SSHException as e: + print(f"❌ SSH 连接错误: {e}") + return False + except Exception as e: + print(f"❌ 连接失败: {e}") + return False + +def print_config_template(): + """打印配置模板""" + print("\n📋 配置模板 (保存到 script/server_config.json):") + print(""" +{ + "ip": "你的服务器IP", + "username": "root", + "auth_method": "password", + "password": "你的密码", + "docker_container": "容器名称", + "npu_device": "NPU设备ID" +} + +或使用密钥认证: +{ + "ip": "你的服务器IP", + "username": "root", + "auth_method": "key", + "password": "", + "ssh_key_path": "密钥文件路径", + "docker_container": "容器名称", + "npu_device": "NPU设备ID" +} +""") + +def main(): + parser = argparse.ArgumentParser(description='检查服务器配置文件') + parser.add_argument('--test-connection', action='store_true', + help='测试 SSH 连接') + parser.add_argument('--config', default='script/server_config.json', + help='配置文件路径 (默认: script/server_config.json)') + args = parser.parse_args() + + config_path = args.config + + print("=" * 50) + print("🔍 配置检查") + print("=" * 50) + + if not check_config_exists(config_path): + print(f"❌ 配置文件不存在: {config_path}") + print_config_template() + sys.exit(1) + + print(f"✅ 配置文件存在: {config_path}") + + try: + with open(config_path, 'r', encoding='utf-8') as f: + config = json.load(f) + except json.JSONDecodeError as e: + print(f"❌ 配置文件格式错误: {e}") + sys.exit(1) + + errors = validate_config(config) + if errors: + print("\n❌ 配置验证失败:") + for error in errors: + print(f" - {error}") + print_config_template() + sys.exit(1) + + print("✅ 配置验证通过") + print(f" - 服务器: {config['ip']}") + print(f" - 用户: {config['username']}") + print(f" - 认证方式: {config['auth_method']}") + print(f" - Docker 容器: {config['docker_container']}") + print(f" - NPU 设备: {config['npu_device']}") + + if args.test_connection: + print("\n" + "=" * 50) + print("🔌 测试连接") + print("=" * 50) + if not test_connection(config): + sys.exit(1) + + print("\n✅ 所有检查通过,可以开始使用!") + +if __name__ == '__main__': + main() diff --git a/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/check_file_exist.py b/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/check_file_exist.py new file mode 100644 index 00000000..f5610f92 --- /dev/null +++ b/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/check_file_exist.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 +import paramiko +import json +import os +import sys +import argparse + +PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +STATUS_FILE = os.path.join(PROJECT_ROOT, 'script', '.upload_status.json') + +WORK_DIR = '/root/MyAICode/batch_verification' +CODE_REMOTE_DIR = WORK_DIR + '/codes' +SCRIPT_PATH = WORK_DIR + '/batch_verification.py' + +CODE_SUBDIRS = ['code-fp16', 'code-fp16-fuse', 'code-int8', 'code-int8-fuse'] + + +def create_ssh_client(config): + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ssh.connect( + hostname=config['ip'], + username='root', + key_filename=config['ssh_key_path'], + port=22, + timeout=15 + ) + return ssh + + +def run_command(ssh, container, command): + full_cmd = f'docker exec {container} bash -c "{command}"' + stdin, stdout, stderr = ssh.exec_command(full_cmd, timeout=30) + return stdout.read().decode('utf-8'), stderr.read().decode('utf-8') + + +def write_status(value): + os.makedirs(os.path.dirname(STATUS_FILE), exist_ok=True) + with open(STATUS_FILE, 'w', encoding='utf-8') as f: + json.dump({"status": value}, f) + + +def main(): + parser = argparse.ArgumentParser(description='Check if code files and batch script exist on server') + parser.add_argument('--code-subdir', required=True, choices=CODE_SUBDIRS, + help='Code subdirectory to check') + parser.add_argument('--server-config', default=os.path.join(PROJECT_ROOT, 'script', 'server_config.json'), + help='Path to server_config.json') + args = parser.parse_args() + + code_subdir = args.code_subdir + code_subdir_path = f'{CODE_REMOTE_DIR}/{code_subdir}' + + config_path = args.server_config + try: + with open(config_path, 'r', encoding='utf-8') as f: + config = json.load(f) + except FileNotFoundError: + print(f'check_file_exist: config not found -> status=false') + write_status("false") + sys.exit(1) + + container = config['docker_container'] + ssh = create_ssh_client(config) + + try: + py_count_output, _ = run_command(ssh, container, + f'ls {code_subdir_path}/*.py 2>/dev/null | wc -l') + py_count = int(py_count_output.strip()) if py_count_output.strip().isdigit() else 0 + + script_output, _ = run_command(ssh, container, + f'test -f {SCRIPT_PATH} && echo EXISTS') + script_exists = 'EXISTS' in script_output + + if py_count >= 1 and script_exists: + print(f'check_file_exist: {code_subdir}({py_count} .py files) + batch_verification.py -> status=true') + write_status("true") + else: + print(f'check_file_exist: {code_subdir}={py_count} .py scripts={"YES" if script_exists else "NO"} -> status=false') + write_status("false") + + except Exception as e: + print(f'check_file_exist: error -> status=false ({e})') + write_status("false") + finally: + ssh.close() + + +if __name__ == '__main__': + main() diff --git a/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/reorder_excel.py b/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/reorder_excel.py new file mode 100644 index 00000000..fab91572 --- /dev/null +++ b/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/reorder_excel.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +import os +from openpyxl import load_workbook, Workbook +from openpyxl.styles import Font, PatternFill, Alignment + +# Read merged_results_all.xlsx to get shape order +print("Reading merged_results_all.xlsx...") +wb1 = load_workbook(r'D:\AI-Triton\AICoding\matmul_skill_for_any_shape\output\merged_results_all.xlsx') +ws1 = wb1.active + +merged_shapes = [] +for row_idx, row in enumerate(ws1.iter_rows(min_row=2, values_only=True), 2): + if len(row) >= 3: + m, n, k = row[0], row[1], row[2] + merged_shapes.append((m, n, k)) + print(" Shape %d: M=%s, N=%s, K=%s" % (len(merged_shapes), m, n, k)) + +# Read best_kernels_report.xlsx +print("\nReading best_kernels_report.xlsx...") +wb2 = load_workbook(r'D:\AI-Triton\AICoding\matmul_skill_for_any_shape\output\best_kernels_report.xlsx') +ws2 = wb2.active + +best_kernels_data = {} +for row_idx, row in enumerate(ws2.iter_rows(min_row=2, values_only=True), 2): + if len(row) >= 7: + m, n, k = row[1], row[2], row[3] + key = (m, n, k) + best_kernels_data[key] = row + print(" Found: M=%s, N=%s, K=%s" % (m, n, k)) + +# Create new Excel file +print("\nCreating reordered Excel...") +wb_new = Workbook() +ws_new = wb_new.active +ws_new.title = "Best Kernels" + +# Add header +headers = ["Shape", "M", "N", "K", "Task Duration (us)", "Passed", "Kernel File", "Kernel Name"] +ws_new.append(headers) + +# Apply header styling +header_fill = PatternFill(start_color="4472C4", end_color="4472C4", fill_type="solid") +header_font = Font(bold=True, color="FFFFFF") +for col_idx, cell in enumerate(ws_new[1], 1): + cell.fill = header_fill + cell.font = header_font + cell.alignment = Alignment(horizontal="center", vertical="center") + +# Add data in merged_results_all order +count = 0 +for (m, n, k) in merged_shapes: + key = (m, n, k) + if key in best_kernels_data: + row = best_kernels_data[key] + ws_new.append(row) + count += 1 + print(" Added: M=%s, N=%s, K=%s" % (m, n, k)) + else: + print(" Warning: M=%s, N=%s, K=%s not found in best_kernels_report" % (m, n, k)) + +# Adjust column widths +for col in ws_new.columns: + max_length = 0 + column = col[0].column_letter + for cell in col: + try: + if len(str(cell.value)) > max_length: + max_length = len(str(cell.value)) + except: + pass + adjusted_width = (max_length + 2) + ws_new.column_dimensions[column].width = adjusted_width + +# Save +output_path = r'D:\AI-Triton\AICoding\matmul_skill_for_any_shape\output\best_kernels_report_reordered.xlsx' +wb_new.save(output_path) +print("\nSuccess! Reordered Excel saved to: %s" % output_path) +print("Total shapes added: %d/%d" % (count, len(merged_shapes))) diff --git a/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/server_check.py b/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/server_check.py new file mode 100644 index 00000000..171dde10 --- /dev/null +++ b/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/server_check.py @@ -0,0 +1,275 @@ +#!/usr/bin/env python3 +""" +通用服务器检查脚本 - 用于检查测试进度、状态和结果 + +使用方法: +python script/server_check.py status # 检查测试状态 +python script/server_check.py progress # 检查测试进度 +python script/server_check.py results # 检查测试结果 +python script/server_check.py summary # 查看汇总结果 +python script/server_check.py clean # 清理服务器 +python script/server_check.py kill # 清除指定NPU上的进程 +""" + +import paramiko +import json +import sys + +def create_ssh_client(config): + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + + auth_method = config.get('auth_method', 'key') + username = config.get('username', 'root') + + if auth_method == 'password': + ssh.connect( + hostname=config['ip'], + username=username, + password=config.get('password'), + port=22, + timeout=15 + ) + else: + ssh.connect( + hostname=config['ip'], + username=username, + key_filename=config['ssh_key_path'], + port=22, + timeout=15 + ) + + return ssh + +def run_command(ssh, container, command): + full_cmd = f'docker exec {container} bash -c "{command}"' + stdin, stdout, stderr = ssh.exec_command(full_cmd, timeout=30) + return stdout.read().decode('utf-8'), stderr.read().decode('utf-8') + +def check_status(config): + """检查服务器上的测试状态""" + ssh = create_ssh_client(config) + try: + output, error = run_command(ssh, config['docker_container'], + "ps aux | grep -E 'python.*batch_verification|msprof' | grep -v grep || echo 'No running verification processes'") + print("=== 运行状态 ===") + print(output) + if error: + print(f"Error: {error}") + finally: + ssh.close() + +def check_progress(config): + """检查测试进度""" + ssh = create_ssh_client(config) + try: + # 检查日志 + output, error = run_command(ssh, config['docker_container'], + 'if [ -f /root/MyAICode/batch_verification/batch_verification.log ]; then tail -30 /root/MyAICode/batch_verification/batch_verification.log; else echo "Log file not found"; fi') + print("=== 测试进度 ===") + print(output) + + # 检查结果目录 + output, error = run_command(ssh, config['docker_container'], + 'ls -la /root/MyAICode/batch_verification/results/ 2>/dev/null | wc -l') + print(f"\n结果目录文件数: {output.strip()}") + + finally: + ssh.close() + +def check_results(config): + """检查测试结果""" + ssh = create_ssh_client(config) + try: + output, error = run_command(ssh, config['docker_container'], + 'ls -la /root/MyAICode/batch_verification/results/ 2>/dev/null | head -20') + print("=== 结果目录 ===") + print(output) + finally: + ssh.close() + +def check_summary(config): + """查看汇总结果""" + ssh = create_ssh_client(config) + try: + output, error = run_command(ssh, config['docker_container'], + 'cat /root/MyAICode/batch_verification/results/summary.json 2>/dev/null || echo "summary.json not found"') + print("=== 汇总结果 ===") + print(output) + finally: + ssh.close() + +def check_all_durations(config): + """查看所有kernel的task_duration(从summary.json读取)""" + import json as json_module + ssh = create_ssh_client(config) + try: + output, error = run_command(ssh, config['docker_container'], + 'cat /root/MyAICode/batch_verification/results/summary.json 2>/dev/null || echo "SUMMARY_NOT_FOUND"') + + if not output or "SUMMARY_NOT_FOUND" in output: + print("summary.json not found") + return + + try: + summary = json_module.loads(output) + except json_module.JSONDecodeError as e: + print(f"Error parsing summary.json: {e}") + return + + durations = [] + for item in summary.get('results', []): + durations.append({ + 'kernel': item.get('kernel', 'unknown'), + 'file': item.get('file', 'unknown'), + 'duration': item.get('duration', 999999), + 'passed': item.get('passed', False), + 'shape': item.get('shape', {}) + }) + + if durations: + print("=== 所有Kernel性能 ===") + print(f"{'Kernel':<60} {'Shape':<25} {'Duration(us)':<15} {'Passed'}") + print("=" * 115) + for item in sorted(durations, key=lambda x: x['duration']): + status = "✓" if item['passed'] else "✗" + shape = item.get('shape', {}) + shape_str = f"M={shape.get('M','?')} N={shape.get('N','?')} K={shape.get('K','?')}" + print(f"{item['kernel']:<60} {shape_str:<25} {item['duration']:<15.2f} {status}") + print("=" * 115) + print(f"Total: {len(durations)} kernels") + else: + print("No results found in summary.json") + + finally: + ssh.close() + +def check_detail(config, kernel_name): + """查看单个kernel的详细结果""" + ssh = create_ssh_client(config) + try: + output, error = run_command(ssh, config['docker_container'], + f'cat /root/MyAICode/batch_verification/results/{kernel_name}/AAAA.json 2>/dev/null || echo "AAAA.json not found"') + print("=== 详细结果 ===") + print(output) + finally: + ssh.close() + +def clean_server(config): + """清理服务器(删除整个batch_verification工作目录)""" + ssh = create_ssh_client(config) + try: + output, error = run_command(ssh, config['docker_container'], + 'rm -rf /root/MyAICode/batch_verification && echo "Cleanup completed: /root/MyAICode/batch_verification removed"') + print("=== 清理结果 ===") + print(output) + if error: + print(f"Error: {error}") + finally: + ssh.close() + +def kill_npu_processes(config): + """清除指定NPU上的相关进程""" + npu_device = config.get('npu_device', 'unknown') + ssh = create_ssh_client(config) + try: + print(f"=== 正在清除 NPU {npu_device} 上的进程 ===") + + # 步骤1: 找到指定NPU的batch_verification主进程PID + find_main_cmd = f"ps aux | grep 'python.*batch_verification.*--npu-device {npu_device}' | grep -v grep | awk '{{print $2}}'" + main_pids_output, _ = run_command(ssh, config['docker_container'], find_main_cmd) + main_pids = [pid.strip() for pid in main_pids_output.split('\n') if pid.strip()] + + if not main_pids: + print(f"未找到 NPU {npu_device} 上的运行进程") + return + + print(f"找到主进程 PID: {', '.join(main_pids)}") + + # 步骤2: 显示将要清除的进程 + print("\n将要清除的进程:") + for pid in main_pids: + show_cmd = f"ps aux | grep -E 'PID|{pid}' | head -5" + output, _ = run_command(ssh, config['docker_container'], show_cmd) + print(output) + + # 步骤3: 找到这些主进程的所有子进程(msprof, msopprof等) + all_pids_to_kill = main_pids.copy() + for main_pid in main_pids: + find_children_cmd = f"pgrep -P {main_pid}" + children_output, _ = run_command(ssh, config['docker_container'], find_children_cmd) + child_pids = [pid.strip() for pid in children_output.split('\n') if pid.strip()] + all_pids_to_kill.extend(child_pids) + + # 递归查找孙子进程 + for child_pid in child_pids: + find_grandchildren_cmd = f"pgrep -P {child_pid}" + grandchildren_output, _ = run_command(ssh, config['docker_container'], find_grandchildren_cmd) + grandchild_pids = [pid.strip() for pid in grandchildren_output.split('\n') if pid.strip()] + all_pids_to_kill.extend(grandchild_pids) + + if len(all_pids_to_kill) > len(main_pids): + print(f"\n包含子进程 PID: {', '.join(all_pids_to_kill[len(main_pids):])}") + + # 步骤4: 执行kill + pids_str = ' '.join(all_pids_to_kill) + kill_cmd = f"kill -9 {pids_str} 2>/dev/null || true" + run_command(ssh, config['docker_container'], kill_cmd) + + # 步骤5: 检查是否清除成功 + import time + time.sleep(1) + + check_cmd = f"ps aux | grep 'python.*batch_verification.*--npu-device {npu_device}' | grep -v grep || echo '已清除'" + output, _ = run_command(ssh, config['docker_container'], check_cmd) + print("\n当前进程状态:") + print(output) + + if '已清除' in output: + print(f"\n✅ NPU {npu_device} 进程清除完成!") + else: + print(f"\n⚠️ 部分进程可能未清除,请手动检查") + + finally: + ssh.close() + +def main(): + if len(sys.argv) < 2: + print(__doc__) + return + + try: + with open('script/server_config.json', 'r', encoding='utf-8') as f: + config = json.load(f) + except FileNotFoundError: + print("Error: script/server_config.json not found") + return + + action = sys.argv[1].lower() + + if action == 'status': + check_status(config) + elif action == 'progress': + check_progress(config) + elif action == 'results': + check_results(config) + elif action == 'summary': + check_summary(config) + elif action == 'clean': + clean_server(config) + elif action == 'kill': + kill_npu_processes(config) + elif action == 'detail': + if len(sys.argv) < 3: + print("Usage: python script/server_check.py detail ") + return + kernel_name = sys.argv[2] + check_detail(config, kernel_name) + elif action == 'durations': + check_all_durations(config) + else: + print(f"Unknown action: {action}") + print(__doc__) + +if __name__ == '__main__': + main() diff --git a/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/server_config.json b/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/server_config.json new file mode 100644 index 00000000..7b769c8e --- /dev/null +++ b/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/server_config.json @@ -0,0 +1,11 @@ +{ + "ip": "你的服务器IP", + "username": "root", + "auth_method": "key", + "password": "", + "ssh_key_path": "你的密钥文件路径", + "docker_container": "你的容器名称", + "host_temp_dir": "/tmp/triton_upload", + "docker_working_dir": "/root/MyAICode", + "npu_device": "0" +} diff --git a/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/verify_code.py b/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/verify_code.py new file mode 100644 index 00000000..ddcdbd21 --- /dev/null +++ b/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/script/verify_code.py @@ -0,0 +1,275 @@ +import os +import sys +import time +import argparse +import json +import paramiko +import posixpath +from datetime import datetime + +PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +UPLOAD_TIMEOUT = 120 +UPLOAD_STATUS_FILE = os.path.join(PROJECT_ROOT, 'script', '.upload_status.json') + + +def create_ssh_client(host, port, user, password=None, key_path=None): + client = paramiko.SSHClient() + client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + + if password: + client.connect(host, port=port, username=user, password=password, timeout=30) + elif key_path and os.path.exists(key_path): + client.connect(host, port=port, username=user, key_filename=key_path, timeout=30) + else: + raise ValueError("Either password or key_path must be provided") + + return client + + +def run_ssh_command(client, command, max_retries=3, timeout=300): + for attempt in range(max_retries): + try: + stdin, stdout, stderr = client.exec_command(command, timeout=timeout) + stdout_content = stdout.read().decode('utf-8', errors='replace') + stderr_content = stderr.read().decode('utf-8', errors='replace') + returncode = stdout.channel.recv_exit_status() + return returncode, stdout_content, stderr_content + except Exception as e: + if attempt < max_retries - 1: + time.sleep(2) + else: + return -1, '', str(e) + + +def poll_verify(client, container, check_cmd, label, interval=5): + """Poll until check_cmd succeeds or UPLOAD_TIMEOUT expires""" + deadline = time.time() + UPLOAD_TIMEOUT + while time.time() < deadline: + rc, out, _ = run_ssh_command(client, + f'docker exec {container} bash -c "{check_cmd}"', timeout=15) + if rc == 0 and out.strip(): + print(f' [{label}] verified OK after {int(time.time() - (deadline - UPLOAD_TIMEOUT))}s', flush=True) + return True + time.sleep(interval) + print(f' [{label}] verify FAILED after {UPLOAD_TIMEOUT}s', flush=True) + return False + + +def upload_file_to_docker(client, container, local_path, remote_tmp_name, docker_dest, label): + """Upload a file via SFTP, then poll-verify until it appears or timeout""" + remote_tmp = posixpath.join('/tmp', remote_tmp_name) + + deadline = time.time() + UPLOAD_TIMEOUT + attempt = 0 + while time.time() < deadline: + attempt += 1 + print(f' [{label}] upload attempt {attempt} ...', flush=True) + + sftp = client.open_sftp() + sftp.put(local_path, remote_tmp) + sftp.close() + + rc, _, err = run_ssh_command(client, + f'docker cp {remote_tmp} {container}:{docker_dest}', timeout=60) + run_ssh_command(client, f'rm -f {remote_tmp}', timeout=10) + + if rc != 0: + print(f' [{label}] docker cp failed: {err[:200]}', flush=True) + continue + + print(f' [{label}] docker cp done, polling for {docker_dest} ...', flush=True) + if poll_verify(client, container, + f'test -e {docker_dest} && echo OK', label): + return True + + print(f' [{label}] retrying upload ...', flush=True) + + print(f' [{label}] FATAL after {UPLOAD_TIMEOUT}s', flush=True) + return False + + +def upload_code_lib(client, container, zip_path, remote_dir): + """Upload code_lib.zip, extract, poll-verify .py files exist""" + if not os.path.isfile(zip_path): + print(f'code_lib.zip not found: {zip_path}', flush=True) + return False + + zip_name = os.path.basename(zip_path) + deadline = time.time() + UPLOAD_TIMEOUT + attempt = 0 + + while time.time() < deadline: + attempt += 1 + print(f' [code_lib.zip] upload attempt {attempt} ...', flush=True) + + remote_tmp = posixpath.join('/tmp', zip_name) + sftp = client.open_sftp() + sftp.put(zip_path, remote_tmp) + sftp.close() + + unzip_cmd = ( + f'docker exec {container} mkdir -p {remote_dir} && ' + f'docker cp {remote_tmp} {container}:{remote_dir}/ && ' + f'docker exec {container} bash -c "cd {remote_dir} && unzip -o {zip_name} && rm -f {zip_name}"' + ) + rc, out, err = run_ssh_command(client, unzip_cmd, timeout=120) + run_ssh_command(client, f'rm -f {remote_tmp}', timeout=10) + + if rc != 0: + print(f' [code_lib.zip] unzip error (rc={rc}): {err[:500]}', flush=True) + time.sleep(5) + continue + + print(f' [code_lib.zip] unzip output: {out[:200]}', flush=True) + + print(f' [code_lib.zip] extract done, polling for .py files ...', flush=True) + if poll_verify(client, container, + f'ls {remote_dir}/code-fp16/*.py 2>/dev/null | wc -l', + 'code_lib.zip'): + return True + + print(f' [code_lib.zip] retrying ...', flush=True) + + print(f' [code_lib.zip] FATAL after {UPLOAD_TIMEOUT}s', flush=True) + return False + + +def main(): + os.makedirs(os.path.dirname(UPLOAD_STATUS_FILE), exist_ok=True) + with open(UPLOAD_STATUS_FILE, 'w', encoding='utf-8') as f: + json.dump({"status": "false"}, f) + + parser = argparse.ArgumentParser(description='Generate and test Triton matmul kernels') + parser.add_argument('--code-subdir', required=True, + choices=['code-fp16', 'code-fp16-fuse', 'code-int8', 'code-int8-fuse']) + parser.add_argument('--server-config', required=True) + parser.add_argument('--npu-device', default=None) + parser.add_argument('--pattern', default='*.py') + parser.add_argument('--shape', default=None) + parser.add_argument('--shape-list', default=None) + args = parser.parse_args() + + code_lib_path = os.path.join(PROJECT_ROOT, 'code_lib.zip') + if not os.path.isfile(code_lib_path): + print(f'Error: code_lib.zip not found at {code_lib_path}') + sys.exit(1) + + with open(args.server_config, 'r', encoding='utf-8') as f: + server_config = json.load(f) + + host = server_config['ip'] + username = server_config.get('username', 'root') + auth_method = server_config.get('auth_method', 'key') + key_path = server_config.get('ssh_key_path') + password = server_config.get('password') + container = server_config['docker_container'] + npu_device = args.npu_device or server_config.get('npu_device', '0') + + if not all([host, container]): + print('Error: Missing server config fields') + sys.exit(1) + + work_dir = '/root/MyAICode/batch_verification' + code_remote_dir = posixpath.join(work_dir, 'codes') + output_dir = posixpath.join(work_dir, 'results') + script_path = posixpath.join(work_dir, 'batch_verification.py') + log_file = posixpath.join(work_dir, 'batch_verification.log') + + shape_list_remote = None + if args.shape_list: + if not os.path.isfile(args.shape_list): + print(f'Error: Shape list file not found: {args.shape_list}') + sys.exit(1) + shape_list_remote = posixpath.join(work_dir, 'shape_list.txt') + + print(f'Connecting to server: {host}') + print(f'Auth method: {auth_method}') + print(f'Username: {username}') + print(f'Docker container: {container}') + print(f'Code subdirectory: {args.code_subdir}') + print(f'NPU device: {npu_device}') + if args.shape: + print(f'Shape: {args.shape}') + if args.shape_list: + print(f'Shape list: {args.shape_list}') + print() + + if auth_method == 'password': + client = create_ssh_client(host, 22, username, password=password) + else: + client = create_ssh_client(host, 22, username, key_path=key_path) + + try: + print('=== Step 1: Clean server ===') + run_ssh_command(client, + f'docker exec {container} bash -c "rm -rf {work_dir}"', timeout=30) + run_ssh_command(client, + f'docker exec {container} mkdir -p {work_dir} {code_remote_dir} {output_dir}', + timeout=15) + print('Server cleanup OK') + print() + + print('=== Step 2a: Upload code_lib.zip ===') + if not upload_code_lib(client, container, code_lib_path, code_remote_dir): + print('FATAL: Failed to upload code_lib.zip') + sys.exit(1) + print() + + script_dir = os.path.dirname(os.path.abspath(__file__)) + local_batch = os.path.join(script_dir, 'batch_verification.py') + + print('=== Step 2b: Upload batch_verification.py ===') + if not upload_file_to_docker(client, container, local_batch, + 'batch_verification_tmp.py', script_path, + 'batch_verification.py'): + print('FATAL: Failed to upload batch_verification.py') + sys.exit(1) + run_ssh_command(client, + f'docker exec {container} chmod +x {script_path}', timeout=10) + print() + + if args.shape_list: + print('=== Step 2c: Upload shape_list ===') + if not upload_file_to_docker(client, container, args.shape_list, + 'shape_list_tmp.txt', shape_list_remote, + 'shape_list'): + print('FATAL: Failed to upload shape_list') + sys.exit(1) + print() + + print('=== Step 3: Start batch verification ===') + start_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + + shape_arg = f"--shape '{args.shape}'" if args.shape else '' + shape_list_arg = f'--shape-list {shape_list_remote}' if args.shape_list else '' + + exec_cmd = ( + f'docker exec {container} bash -c ' + f'"nohup python3 {script_path} ' + f'--code-dir {code_remote_dir} ' + f'--code-subdir {args.code_subdir} ' + f'--work-dir {work_dir} ' + f'--output-dir {output_dir} ' + f'--npu-device {npu_device} ' + f'--pattern {args.pattern} ' + f'{shape_arg} {shape_list_arg} ' + f'> {log_file} 2>&1 &"' + ) + run_ssh_command(client, exec_cmd, timeout=30) + + print(f'Batch verification started at {start_time}') + print(f'Log: {log_file}') + print(f'Results: {output_dir}') + print() + print('Monitor: python script/server_check.py status') + print('Monitor: python script/server_check.py progress') + + with open(UPLOAD_STATUS_FILE, 'w', encoding='utf-8') as f: + json.dump({"status": "true"}, f) + + finally: + client.close() + + +if __name__ == '__main__': + main() diff --git a/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/shape_list.md b/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/shape_list.md new file mode 100644 index 00000000..0ea44b16 --- /dev/null +++ b/skills/triton/matmul-related-gen/matmul_skill_for_any_shape/shape_list.md @@ -0,0 +1,94 @@ +# Shape List for Batch Testing + +这个文件用于批量测试多个shape的矩阵乘法kernel。 + +## 格式说明 + +每行一个shape,格式为:`M N K` + +## Shape 列表 + +``` +128 4096 7168 +1024 4096 7168 +128 7168 2048 +1024 7168 2048 +1 131072 6144 +1024 36 6144 +1024 768 6144 +1024 96 6144 +16384 48 1536 +16384 1024 2048 +16384 6144 2048 +16384 36 6144 +16384 96 6144 +128 8192 6144 +64 384 1024 +64 8192 6144 +8 768 6144 +1 5120 1280 +1 13824 5120 +1 1792 5120 +1 37936 5120 +1 5120 6912 +5 5120 1280 +5 13824 5120 +5 1792 5120 +5 5120 6912 +140236 128 6912 +15 5120 10240 +240 9696 5120 +720 9696 5120 +15 128 5120 +45 128 5120 +17940 1280 1280 +17940 1280 3420 +17940 3840 1280 +17940 6480 1280 +4485 3584 5120 +4485 5120 5120 +17940 1280 1176 +75 152064 3584 +76 152064 3584 +77 152064 3584 +78 152064 3584 +79 152064 3584 +80 152064 3584 +4525 3584 18944 +4525 3584 3584 +4525 37888 3584 +4525 4608 3584 +4826 3584 18944 +4826 3584 3584 +4826 37888 3584 +4826 4608 3584 +15 5120 2048 +15 12800 5120 +15 2560 5120 +15 5120 6400 +18 5120 2048 +18 12800 5120 +18 2560 5120 +18 5120 6400 +19 5120 2048 +19 12800 5120 +19 2560 5120 +19 5120 6400 +21 5120 2048 +21 12800 5120 +21 2560 5120 +21 5120 6400 +3000 5120 2048 +3000 12800 5120 +3000 2560 5120 +3000 5120 6400 +6 37984 5120 +7 37984 5120 +8 37984 5120 +``` + +## 说明 + +- 每行一个shape,使用空格分隔M、N、K +- 支持空行和注释(以#开头) +- 会自动跳过无效行 diff --git a/skills/triton/matmul-related-gen/skills_overview.md b/skills/triton/matmul-related-gen/skills_overview.md new file mode 100644 index 00000000..cc4a31ce --- /dev/null +++ b/skills/triton/matmul-related-gen/skills_overview.md @@ -0,0 +1,175 @@ +# Triton Matmul 相关 Skill 体系说明 + +本目录包含 4 个 Skill,它们构成了一套完整的 Triton 矩阵乘法(GEMM)算子自动生成体系。 + +特别注意,需要环境中事先安装好 `msprof op`(强调不是 `msprof`)。 + +## 架构概览 + +``` +matmul_skill_for_any_shape (终端用户入口 Skill) + │ + │ 离线阶段:通过以下 3 个原子 Skill 生成 code_lib.zip + │ + ├── triton_w_nd2nz (原子 Skill ①: B 矩阵伪NZ格式优化) + ├── tiling_diagonal (原子 Skill ②: 对角 Tiling 核心映射) + └── k_axis_offset (原子 Skill ③: K 轴偏移优化) +``` + +## 1. matmul_skill_for_any_shape — 终端用户入口 Skill + +### 定位 + +这是一个 **可直接生成 matmul 算子的完整 Skill**,面向最终用户。用户无需手动组合各种优化策略,只需传入 shape 参数即可自动从预生成的代码库中筛选最优 Kernel 并完成测试验证。 + +### 使用前准备:服务器配置 + +该 Skill 的运行需要远程 NPU 服务器来编译和性能测试 Kernel,因此 **必须先配置服务器连接信息**。 + +编辑 `script/server_config.json`: + +```json +{ + "ip": "你的服务器IP", + "username": "root", + "auth_method": "key", + "password": "", + "ssh_key_path": "你的密钥文件路径", + "docker_container": "容器名称", + "npu_device": "NPU设备ID" +} +``` + +| 字段 | 说明 | +|------|------| +| `ip` | NPU 服务器 IP 地址 | +| `auth_method` | `"password"` 密码认证 或 `"key"` 密钥认证 | +| `password` | 密码认证时填写 | +| `ssh_key_path` | 密钥认证时填写 .pem 文件路径 | +| `docker_container` | Docker 容器名称 | +| `npu_device` | NPU 设备 ID(0-7) | + +配置完成后运行检测: + +```bash +python script/check_config.py +``` + +### 使用方式 + +**单 shape 测试**(例如 M=128 N=7168 K=4096): + +``` +请按照 SKILL.md 生成 M=128 N=7168 K=4096 的 FP16 高性能算子 +或 请按照 SKILL.md 生成 M=128 N=7168 K=4096 的 FP16 ND格式算子 +或 请按照 SKILL.md 生成 M=128 N=7168 K=4096 的 INT8 高性能算子 +或 请按照 SKILL.md 生成 M=128 N=7168 K=4096 的 INT8 ND格式算子 +``` + +**多 shape 批量测试**(使用 `shape_list.md` 中预定义的 shape): + +``` +请按照 SKILL.md 生成 FP16 高性能算子,且请使用 shape_list 中的 shape 进行测试 +或 请按照 SKILL.md 生成 FP16 ND格式算子,且请使用 shape_list 中的 shape 进行测试 +或 请按照 SKILL.md 生成 INT8 高性能算子,且请使用 shape_list 中的 shape 进行测试 +或 请按照 SKILL.md 生成 INT8 ND格式算子,且请使用 shape_list 中的 shape 进行测试 +``` + +### 支持的任务类型 + +| 用户需求 | `--code-subdir` | 精度 | 输入格式 | Kernel 数量 | +|----------|-----------------|------|----------|-------------| +| FP16 高性能 matmul | `code-fp16` | FP16 | 伪NZ | 36 | +| FP16 ND 格式 matmul | `code-fp16-fuse` | FP16 | ND + 融合 | 72 | +| INT8 高性能 matmul | `code-int8` | INT8 | 伪NZ | 36 | +| INT8 ND 格式 matmul | `code-int8-fuse` | INT8 | ND + 融合 | 72 | + +### 完整工作流 + +``` +Step 0: CONFIG_CHECK — 自动检测服务器配置是否有效 + ↓ +Step 1: CLEAN — 清理服务器端旧测试数据 + ↓ +Step 2: UPLOAD + START — 上传 code_lib.zip + 启动远程批量测试 + ↓ +Step 3: VERIFY — 确认远程测试进程已启动 + ↓ +用户自行等待并查看进度 / 下载结果 +``` + +### 输出 + +测试完成后,通过 `python script/analyze_results.py` 下载结果到本地 `output/` 目录: +- `best_kernels_report.xlsx` — 每个 shape 的最优 Kernel 性能报告 +- `*.py` — 所有最优 Kernel 的源代码 + +--- + +## 2. 三个原子 Skill + +以下三个 Skill 是构成 matmul_skill_for_any_shape 的底层基础。它们各自独立可用,专注于单一的优化维度。**matmul_skill_for_any_shape 中的 `code_lib.zip` 正是通过组合这三个原子 Skill 离线生成的。** + +### 2.1 triton_w_nd2nz — B 矩阵伪NZ格式优化 + +**文件**: [triton_w_nd2nz/SKILL.md](file:///d:/AscendICT/AscendOpGenAgent/skills/triton/matmul-related-gen/triton_w_nd2nz/SKILL.md) + +--- + +### 2.2 tiling_diagonal — 对角 Tiling 核心映射 + +**文件**: [tiling_diagonal/skill.md](file:///d:/AscendICT/AscendOpGenAgent/skills/triton/matmul-related-gen/tiling_diagonal/skill.md) + +--- + +### 2.3 k_axis_offset — K 轴偏移优化 + +**文件**: [k_axis_offset/skill.md](file:///d:/AscendICT/AscendOpGenAgent/skills/triton/matmul-related-gen/k_axis_offset/skill.md) + +--- + +## 3. 整体关系总结 + +``` +┌────────────────────────────────────────────────────────────────┐ +│ matmul_skill_for_any_shape │ +│ ┌──────────────────────────────────────────────────────────┐ │ +│ │ code_lib.zip │ │ +│ │ ┌─────────────┐ ┌──────────────┐ ┌───────────────┐ │ │ +│ │ │ code-fp16/ │ │ code-fp16- │ │ code-int8/ │ │ │ +│ │ │ (36 kernels) │ │ fuse/ (72) │ │ code-int8-fuse/│ │ │ +│ │ └─────────────┘ └──────────────┘ └───────────────┘ │ │ +│ └──────────────────────────────────────────────────────────┘ │ +│ │ │ +│ 离线阶段:通过组合 3 个原子 Skill 生成 code_lib.zip │ +│ │ │ +│ ┌─────────────────────────┼─────────────────────────┐ │ +│ │ │ │ │ +│ ▼ ▼ ▼ │ +│ triton_w_nd2nz tiling_diagonal k_axis_offset │ +│ (B矩阵格式优化) (对角Tiling映射) (K轴偏移) │ +│ │ │ +│ ┌────────────────────────────────────────────────────┘ │ +│ │ 运行时:根据用户 shape 从 code_lib 中筛选最优 Kernel │ +│ │ 上传 → 远程编译 → 性能测试 → 输出最优 Kernel 和报告 │ +│ └───────────────────────────────────────────────────────── │ +└────────────────────────────────────────────────────────────────┘ +``` + +### 三个原子 Skill 的职责分工 + +| Skill | 优化维度 | 影响范围 | +|-------|---------|---------| +| **triton_w_nd2nz** | 内存布局 | B 矩阵数据排布,Host 端预处理 + Kernel 端加载模式 | +| **tiling_diagonal** | Core 调度 | 计算块的分配策略,多核负载均衡 | +| **k_axis_offset** | 内存访问 | K 轴遍历顺序,减少多核内存访问冲突 | + +### 运行时流程 + +1. 用户指定 shape 和精度要求 +2. 系统从 `code_lib.zip` 中提取对应子目录的所有 Kernel +3. 上传至 NPU 服务器 +4. 远程逐一编译并执行性能测试(使用 `msprof`) +5. 收集性能数据,输出每个 shape 的最优 Kernel 和对应的源代码 + +生成的代码和测试报告存储在本地 `output/` 文件夹下。 diff --git a/skills/triton/matmul-related-gen/tiling_diagonal/skill.md b/skills/triton/matmul-related-gen/tiling_diagonal/skill.md new file mode 100644 index 00000000..d3561df0 --- /dev/null +++ b/skills/triton/matmul-related-gen/tiling_diagonal/skill.md @@ -0,0 +1,104 @@ +--- +name: Matrix Multiplication (matmul) Diagonal Tiling Core Logic Algorithm +description: Achieve efficient memory access through diagonal core mapping rules +--- + +## Code Generation Requirements: +1. Core mapping rule: Ensure adjacent block_id access different M, N blocks; tl.swizzle2d is not allowed +2. Generated code must satisfy CORE_Load_Balancing +3. Generated code must satisfy Coding_Rules +4. The algorithm must include at least 4 autotune parameters: BLOCK_M, BLOCK_N, BLOCK_K, and GROUP_SIZE + +## Autotune Config Generation Rules: +1. Keep all original BLOCK_M, BLOCK_N, BLOCK_K configurations from the base code +2. For each original configuration, generate variants with GROUP_SIZE=4 and GROUP_SIZE=8 +3. Total configs = original_configs × len(GROUP_SIZE_values) +4. GROUP_SIZE values: [4, 8] + +### Example: +Original configs (3): +- Config A: {'BLOCK_M': 128, 'BLOCK_N': 128, 'BLOCK_K': 256} +- Config B: {'BLOCK_M': 128, 'BLOCK_N': 256, 'BLOCK_K': 256} +- Config C: {'BLOCK_M': 256, 'BLOCK_N': 128, 'BLOCK_K': 256} + +After applying diagonal tiling (6 configs): +- Config A + GROUP_SIZE=4: {'BLOCK_M': 128, 'BLOCK_N': 128, 'BLOCK_K': 256, 'GROUP_SIZE': 4} +- Config A + GROUP_SIZE=8: {'BLOCK_M': 128, 'BLOCK_N': 128, 'BLOCK_K': 256, 'GROUP_SIZE': 8} +- Config B + GROUP_SIZE=4: {'BLOCK_M': 128, 'BLOCK_N': 256, 'BLOCK_K': 256, 'GROUP_SIZE': 4} +- Config B + GROUP_SIZE=8: {'BLOCK_M': 128, 'BLOCK_N': 256, 'BLOCK_K': 256, 'GROUP_SIZE': 8} +- Config C + GROUP_SIZE=4: {'BLOCK_M': 256, 'BLOCK_N': 128, 'BLOCK_K': 256, 'GROUP_SIZE': 4} +- Config C + GROUP_SIZE=8: {'BLOCK_M': 256, 'BLOCK_N': 128, 'BLOCK_K': 256, 'GROUP_SIZE': 8} + +## Related Variable Definitions: + +### block_id Mapping Rule +- block_id=idx means block_id is assigned to a Core ID, for example: block_id=tl.program_id(0) +- (M,N) represents the 2D Tile block index in M and N directions +- block_id=0 → (0,1) means Core 0 processes the Tile block at position (0,1) + +### GROUP_2D Definition +- GROUP_2D contains GROUP_SIZE rows, each row has GROUP_SIZE data blocks +- The total number of data blocks in a GROUP_2D is: tiles_per_group = GROUP_SIZE * GROUP_SIZE + +## Algorithm Flow +1. Each group has GROUP_2D small data blocks; diagonal tiling within each group, taking GROUP_SIZE=4 as an example: + - First 4*4 diagonal tiling group: + block_id=0 → (0,0), block_id=1 → (1,1), block_id=2 → (2,2), block_id=3 → (3,3) + block_id=4 → (0,1), block_id=5 → (1,2), block_id=6 → (2,3), block_id=7 → (3,0) + block_id=8 → (0,2), block_id=9 → (1,3), block_id=10 → (2,0), block_id=11 → (3,1) + block_id=12 → (0,3), block_id=13 → (1,0), block_id=14 → (2,1), block_id=15 → (3,2) + - Second 4*4 diagonal tiling group: + block_id=16 → (0,4), block_id=17 → (1,5), block_id=18 → (2,6), block_id=19 → (3,7) + +## Reference Implementation +```python +# Get current program ID (Core ID) +pid = tl.program_id(0) + +# Calculate grid dimensions +num_pid_m = tl.cdiv(M, BLOCK_M) +num_pid_n = tl.cdiv(N, BLOCK_N) + +# Calculate total virtual blocks, padded by Group +# To implement diagonal tiling, we divide the grid into GROUP_SIZE x GROUP_SIZE SuperBlocks +groups_m = tl.cdiv(num_pid_m, GROUP_SIZE) +groups_n = tl.cdiv(num_pid_n, GROUP_SIZE) +num_groups = groups_m * groups_n + +# Number of blocks per Group +tiles_per_group = GROUP_SIZE * GROUP_SIZE + +# Total virtual tasks (including padded blocks) +total_virtual_tiles = num_groups * tiles_per_group + +# Loop through tasks assigned to current Core +for v_idx in range(pid, total_virtual_tiles, CORE_NUM): + # 1. Decode v_idx into Group ID and in-Group ID + group_idx = v_idx // tiles_per_group + in_group_idx = v_idx % tiles_per_group + + # 2. Calculate Group coordinates (grid of groups) + group_m = group_idx // groups_n + group_n = group_idx % groups_n + + # 3. Calculate in-Group coordinates (Diagonal Tiling) + # Mapping rule: + # block_id=0 -> (0,0), block_id=1 -> (1,1) ... + # i = local_id % GROUP_SIZE + # j = local_id // GROUP_SIZE + # m = i + # n = (i + j) % GROUP_SIZE + + i = in_group_idx % GROUP_SIZE + j = in_group_idx // GROUP_SIZE + local_m = i + local_n = (i + j) % GROUP_SIZE + + # 4. Calculate global coordinates + block_m = group_m * GROUP_SIZE + local_m + block_n = group_n * GROUP_SIZE + local_n + + # 5. Boundary check: use if instead of continue, as Triton compiler may not support continue + if block_m < num_pid_m and block_n < num_pid_n: + # --- Start matrix multiplication calculation --- +``` diff --git a/skills/triton/matmul-related-gen/triton_w_nd2nz/SKILL.md b/skills/triton/matmul-related-gen/triton_w_nd2nz/SKILL.md new file mode 100644 index 00000000..7b65e639 --- /dev/null +++ b/skills/triton/matmul-related-gen/triton_w_nd2nz/SKILL.md @@ -0,0 +1,361 @@ +--- +name: "b_matrix_format_optimization" +description: "Optimizes B matrix memory layout for GEMM operations with dot instructions. Invoke when code contains tl.dot() and needs matrix multiplication performance optimization." +--- + +# B Matrix Format Optimization + +## 1. Skill Overview + +### 1.1 What This Skill Does +This skill optimizes the memory layout of the B matrix in GEMM (General Matrix Multiply) operations by reorganizing data into a block-based format. This optimization improves memory access patterns and cache utilization, particularly effective on NPU hardware. + +### 1.2 When to Invoke This Skill +Invoke this skill when: +- The code contains `tl.dot()` instructions (this is a **prerequisite**) +- You need to optimize matrix multiplication performance +- The B matrix dimensions are compatible with the tile sizes used in the kernel + +## 2. Prerequisites + +**Step 1: Check for dot instruction** + +Before applying this optimization, verify that the code contains a dot instruction: + +```python +# Example of dot instruction in Triton +acc += tl.dot(a_val, b_val, out_dtype=tl.int32) +``` + +If no dot instruction is present, this optimization is not applicable. + +## 3. Implementation Steps + +### Step 2: Identify Tile Variables + +Identify the N-axis and K-axis tile variables in the code. These are typically defined as constants in the kernel function signature: + +```python +@triton.jit +def gemm_kernel( + # ... + BLOCK_SIZE_M: tl.constexpr, + BLOCK_SIZE_N: tl.constexpr, # This is the N-axis tile variable + BLOCK_SIZE_K: tl.constexpr, # This is the K-axis tile variable + # ... +): + # ... +``` + +Common naming conventions: +- N-axis: `BLOCK_SIZE_N`, `BLOCK_N`, `TILE_N` +- K-axis: `BLOCK_SIZE_K`, `BLOCK_K`, `TILE_K` + +### Step 3: Convert B Matrix Format + +Use the identified tile variables to convert the B matrix: + +```python +def convert_b_matrix(b: torch.Tensor, block_k: int, block_n: int): + """ + Convert B matrix to optimized block format. + + Args: + b: Original B matrix with shape (K, N) + block_k: K-axis tile size (e.g., BLOCK_SIZE_K) + block_n: N-axis tile size (e.g., BLOCK_SIZE_N) + + Returns: + Optimized B matrix with shape (k_div_block_k, n_div_block_n, block_k, block_n) + """ + K, N = b.shape + assert K % block_k == 0, f'K ({K}) must be divisible by block_k ({block_k})' + assert N % block_n == 0, f'N ({N}) must be divisible by block_n ({block_n})' + + k_div_block_k = K // block_k + n_div_block_n = N // block_n + + # Reshape and permute for optimized memory layout + b_reshaped = b.view(k_div_block_k, block_k, n_div_block_n, block_n) + b_optimized = b_reshaped.permute(0, 2, 1, 3).contiguous() + + return b_optimized +``` + +### Step 4: Update Kernel Access Pattern + +Modify the kernel to access the optimized B matrix: + +**⚠️ CRITICAL: Load A MUST be executed before Load B in the kernel loop.** + +```python +# Inside the kernel +k_div_block_k = k // block_k +n_div_block_n = (block_n * BLOCK_SIZE_N) // block_n + +# Calculate offset for the current block +b_offset = k_div_block_k * stride_b_k_div_block_k + n_div_block_n * stride_b_n_div_block_n + +# IMPORTANT: Load A first (before loading B) +a_val = tl.load(a_ptr, boundary_check=(0, 1)) + +# Then load B +block_elements = block_k * block_n +b_raw = tl.load(b + b_offset + tl.arange(0, block_elements)) + +# Reshape to the required dimensions +b_val = b_raw.reshape(block_k, block_n) +``` + +## 4. Complete Example + +### 4.1 Kernel Definition + +```python +@triton.jit +def gemm_kernel( + a, b, c, M, N, K, + stride_am, stride_ak, + stride_b_k_div_block_k, stride_b_n_div_block_n, + stride_cm, stride_cn, + BLOCK_SIZE_M: tl.constexpr, + BLOCK_SIZE_N: tl.constexpr, + BLOCK_SIZE_K: tl.constexpr, +): + pid = tl.program_id(0) + + # ... (block calculation logic) + + for k in range(0, K, BLOCK_SIZE_K): + # ⚠️ CRITICAL: Load A MUST be before Load B + a_val = tl.load(a_ptr, boundary_check=(0, 1)) + + # Optimized B matrix access (after loading A) + k_div_block_k = k // BLOCK_SIZE_K + n_div_block_n = (block_n * BLOCK_SIZE_N) // BLOCK_SIZE_N + + b_offset = k_div_block_k * stride_b_k_div_block_k + n_div_block_n * stride_b_n_div_block_n + b_raw = tl.load(b + b_offset + tl.arange(0, BLOCK_SIZE_K * BLOCK_SIZE_N)) + b_val = b_raw.reshape(BLOCK_SIZE_K, BLOCK_SIZE_N) + + # Dot instruction (prerequisite) + acc += tl.dot(a_val, b_val, out_dtype=tl.int32) + + a_ptr = tl.advance(a_ptr, (0, BLOCK_SIZE_K)) +``` + +### 4.2 Host Code with Autotune Config + +**⚠️ CRITICAL: When calling `convert_b_matrix`, you MUST add a comment immediately before the function call to specify the actual tile variable names from the autotune config.** + +```python +AUTOTUNE_CONFIGS = [ + triton.Config({'BLOCK_SIZE_M': 128, 'BLOCK_SIZE_N': 256, 'BLOCK_SIZE_K': 256}), +] + +def gemm(a: torch.Tensor, b: torch.Tensor): + M, K = a.shape + K_from_b, N = b.shape + + # ========== CRITICAL: Must use this exact config structure ========== + # Get the selected config from autotune + # In practice, this would be determined by the autotuner + config = AUTOTUNE_CONFIGS[0] # Example: using first config + BLOCK_SIZE_N = config.kwargs['BLOCK_SIZE_N'] # TileN = 256 + BLOCK_SIZE_K = config.kwargs['BLOCK_SIZE_K'] # TileK = 256 + # ================================================================ + + # ========== CRITICAL: Add comment before convert_b_matrix ========== + b_optimized = convert_b_matrix(b, block_k=BLOCK_SIZE_K, block_n=BLOCK_SIZE_N) + # ==================================================================== + + # Calculate strides for the optimized format + k_div_block_k = K // BLOCK_SIZE_K + n_div_block_n = N // BLOCK_SIZE_N + + stride_b_n_div_block_n = BLOCK_SIZE_K * BLOCK_SIZE_N + stride_b_k_div_block_k = n_div_block_n * stride_b_n_div_block_n + + # Launch kernel + grid = (CORE_NUM,) + gemm_kernel[grid]( + a, b_optimized, c, M, N, K, + a.stride(0), a.stride(1), + stride_b_k_div_block_k, stride_b_n_div_block_n, + c.stride(0), c.stride(1), + BLOCK_SIZE_M=config.kwargs['BLOCK_SIZE_M'], + BLOCK_SIZE_N=BLOCK_SIZE_N, + BLOCK_SIZE_K=BLOCK_SIZE_K, + ) + + return c +``` + +### 4.3 Example with Multiple Autotune Configs + +When using multiple autotune configurations, the comment becomes even more important: + +```python +AUTOTUNE_CONFIGS = [ + triton.Config({'BLOCK_SIZE_M': 128, 'BLOCK_SIZE_N': 256, 'BLOCK_SIZE_K': 256}), + triton.Config({'BLOCK_SIZE_M': 64, 'BLOCK_SIZE_N': 128, 'BLOCK_SIZE_K': 128}), + triton.Config({'BLOCK_SIZE_M': 256, 'BLOCK_SIZE_N': 512, 'BLOCK_SIZE_K': 256}), +] + +@triton.autotune(configs=AUTOTUNE_CONFIGS, key=['M', 'N', 'K']) +@triton.jit +def gemm_kernel(...): + # ... kernel implementation + +def gemm(a: torch.Tensor, b: torch.Tensor): + M, K = a.shape + K_from_b, N = b.shape + + # ========== CRITICAL: Must use this exact config structure ========== + # After autotune selects a config, extract the tile sizes + # Note: In practice, you would get the selected config from the autotuner + # For demonstration, we use a specific config + config = AUTOTUNE_CONFIGS[0] + BLOCK_SIZE_N = config.kwargs['BLOCK_SIZE_N'] # TileN = 256 + BLOCK_SIZE_K = config.kwargs['BLOCK_SIZE_K'] # TileK = 256 + # ================================================================ + + # ========== CRITICAL: Comment format ========== + b_optimized = convert_b_matrix(b, block_k=BLOCK_SIZE_K, block_n=BLOCK_SIZE_N) + # ============================================== + + # ... rest of the implementation +``` + +## 5. Key Benefits + +### 5.1 Memory Access Efficiency +- **Contiguous memory access**: Loads entire blocks in a single operation +- **Improved cache utilization**: Block-based layout matches access patterns +- **Reduced memory transactions**: Fewer load operations for the same data + +### 5.2 Hardware Optimization +- **NPU-friendly**: Matches hardware memory access patterns +- **Reduced addressing overhead**: Simplified offset calculations +- **Better parallelism**: Efficient data loading supports higher computational throughput + +### 5.3 Flexibility +- **Dynamic tile sizes**: Adapts to any tile size defined in the kernel +- **No hardcoded constants**: Works with various block configurations +- **AutoTune compatible**: Can be combined with Triton's autotuning + +## 6. Important Considerations + +### 6.1 **⚠️ CRITICAL: Load Order Requirement** +**Load A MUST be executed before Load B in the kernel loop.** + +This ordering is essential for: +- **Memory access optimization**: Ensures proper memory access patterns +- **Hardware efficiency**: Matches NPU hardware expectations +- **Correct execution**: Prevents potential race conditions or undefined behavior + +**Correct order:** +```python +# ✓ CORRECT: Load A first +a_val = tl.load(a_ptr, boundary_check=(0, 1)) +# Then load B +b_raw = tl.load(b + b_offset + tl.arange(0, BLOCK_SIZE_K * BLOCK_SIZE_N)) +``` + +**Incorrect order:** +```python +# ✗ INCORRECT: Load B before A +b_raw = tl.load(b + b_offset + tl.arange(0, BLOCK_SIZE_K * BLOCK_SIZE_N)) +a_val = tl.load(a_ptr, boundary_check=(0, 1)) # WRONG! +``` + +### 6.2 Dimension Requirements +- K must be divisible by the K-axis tile size (block_k) +- N must be divisible by the N-axis tile size (block_n) +- If dimensions don't meet requirements, consider padding + +### 6.3 Memory Overhead +- The converted B matrix requires the same amount of memory +- Additional memory is needed during the conversion process +- Consider caching converted matrices for repeated use + +### 6.4 Performance Trade-offs +- **One-time conversion cost**: Initial conversion takes time +- **Best for repeated operations**: Most beneficial when B matrix is reused +- **Batch processing**: Ideal for scenarios with multiple GEMM operations + +### 6.5 **⚠️ CRITICAL: Comment Requirement** +**You MUST add a comment immediately before calling `convert_b_matrix` to specify:** +1. The actual variable name for `block_k` from the autotune config (e.g., `BLOCK_SIZE_K`) +2. The actual variable name for `block_n` from the autotune config (e.g., `BLOCK_SIZE_N`) + +**Format:** +```python +# ========== CRITICAL: Comment format ========== +b_optimized = convert_b_matrix(b, block_k=, block_n=) +``` + +**Why this is important:** +- Ensures traceability between the conversion and the kernel configuration +- Makes it clear which autotune config is being used +- Helps with debugging and maintenance +- Prevents mismatched tile sizes between conversion and kernel execution + +## 7. Troubleshooting + +### 7.1 Common Issues + +**Issue**: "K must be divisible by block_k" +- **Cause**: Matrix dimension doesn't match tile size +- **Solution**: Pad the matrix or adjust tile size + +**Issue**: Incorrect results after optimization +- **Cause**: Incorrect stride calculations or mismatched tile sizes +- **Solution**: Verify stride formulas and ensure tile sizes match between conversion and kernel + +**Issue**: No performance improvement +- **Cause**: Matrix too small or conversion overhead dominates +- **Solution**: Profile to identify bottleneck; consider matrix size + +**Issue**: Missing comment before convert_b_matrix call +- **Cause**: Forgot to add the required comment +- **Solution**: Add comment specifying the autotune config variable names + +**Issue**: Load B before Load A in kernel +- **Cause**: Incorrect load order in the kernel loop +- **Solution**: Ensure `tl.load(a_ptr)` is executed BEFORE `tl.load(b + b_offset + ...)` + +### 7.2 Validation + +Always validate the optimization produces correct results: + +```python +# Test with small example +c_optimized = gemm(a, b_optimized, block_k=BLOCK_K, block_n=BLOCK_N) +c_reference = torch.matmul(a.float(), b.float()).half() + +assert torch.allclose(c_optimized, c_reference, rtol=1e-3), "Results mismatch!" +``` + +## 8. Summary + +This skill optimizes B matrix memory layout for GEMM operations by: +1. **Checking prerequisite**: Ensures code contains dot instruction +2. **Identifying tile variables**: Finds BLOCK_K and BLOCK_N from kernel definition +3. **Converting format**: Reorganizes B matrix to block-based layout +4. **Adding required comment**: Specifies autotune config variable names before conversion +5. **Updating access pattern**: Modifies kernel to use optimized loading +6. **Ensuring correct load order**: Load A MUST be executed before Load B in the kernel loop + +The optimization is most effective when: +- Code contains `tl.dot()` instructions +- Matrix dimensions align with tile sizes +- B matrix is reused across multiple operations +- Running on hardware with specific memory access patterns (e.g., NPU) +- **Load A is executed before Load B in the kernel** + +## 9. References + +- [Triton Documentation](https://triton-lang.org/docs/) +- [Matrix Multiplication Optimization Guide](https://triton-lang.org/programming-guide.html) +- [NPU Programming Best Practices](https://developer.huawei.com/ict/en/site-type/docs)