已合并
Feat: 新增 TrsmBatched(StrsmBatched / CtrsmBatched)批量三角求解算子 #243
jingdemeng创建于 7月1日
Feat: 新增 TrsmBatched(StrsmBatched / CtrsmBatched)批量三角求解算子 #243
已合并
共 45 个文件变更+8961-0
| @@ -0,0 +1,10 @@ | |||
| 1 | +cmake_minimum_required(VERSION 3.16) | ||
| 2 | +find_package(ASC REQUIRED) | ||
| 3 | + | ||
| 4 | +project(ctrsm_batched LANGUAGES ASC CXX) | ||
| 5 | +set(CMAKE_CXX_STANDARD 17) | ||
| 6 | + | ||
| 7 | +set(ACL_INCLUDE_DIR "$ENV{ASCEND_HOME_PATH}/aarch64-linux/include") | ||
| 8 | +set(ACL_LIB_DIR "$ENV{ASCEND_HOME_PATH}/lib64") | ||
| 9 | + | ||
| 10 | +add_subdirectory(test) | ||
| @@ -0,0 +1,204 @@ | |||
| 1 | +# aclblasCtrsmBatched | ||
| 2 | + | ||
| 3 | +批量复数三角矩阵求解算子(complex64),基于 Ascend C 实现,对标 cuBLAS `cublasCtrsmBatched`。 | ||
| 4 | + | ||
| 5 | +## 功能描述 | ||
| 6 | + | ||
| 7 | +求解批量复数三角线性方程组: | ||
| 8 | + | ||
| 9 | +- `op(A) * X = alpha * B`(side='L') | ||
| 10 | +- `X * op(A) = alpha * B`(side='R') | ||
| 11 | + | ||
| 12 | +其中 A 为复数三角矩阵,alpha 为复数标量,支持: | ||
| 13 | +- Left/Right 左右乘模式 | ||
| 14 | +- Upper/Lower 上下三角 | ||
| 15 | +- NoTrans/Trans/ConjTrans 转置模式 | ||
| 16 | +- Unit/NonUnit 单位三角矩阵 | ||
| 17 | + | ||
| 18 | +## 接口定义 | ||
| 19 | + | ||
| 20 | +```c | ||
| 21 | +aclblasStatus_t aclblasCtrsmBatched( | ||
| 22 | + aclblasHandle_t handle, | ||
| 23 | + aclblasSideMode_t side, | ||
| 24 | + aclblasFillMode_t uplo, | ||
| 25 | + aclblasOperation_t transa, | ||
| 26 | + aclblasDiagType_t diag, | ||
| 27 | + int64_t m, int64_t n, | ||
| 28 | + const std::complex<float>* alpha, | ||
| 29 | + const std::complex<float>* const aArray[], int64_t lda, | ||
| 30 | + std::complex<float>* const bArray[], int64_t ldb, | ||
| 31 | + int64_t batchCount) | ||
| 32 | +``` | ||
| 33 | + | ||
| 34 | +## 架构设计 | ||
| 35 | + | ||
| 36 | +采用 MIX_AIC_1_2 混合核架构(1 Cube核 + 2 Vector核): | ||
| 37 | + | ||
| 38 | +``` | ||
| 39 | +AIV (Vector核): Panel 内三角求解(前代/回代)+ 数据格式转换(AoS<->SoA 转置) | ||
| 40 | +AIC (Cube核): Trail 区域 GEMM 更新(Matmul 库调用) | ||
| 41 | +同步机制: CrossCoreSetFlag/WaitFlag 跨核事件同步 | ||
| 42 | +``` | ||
| 43 | + | ||
| 44 | +**核心算法流程:** | ||
| 45 | +``` | ||
| 46 | +for each panel: | ||
| 47 | + [AIV] LoadPanelA -> SolveInner(nb*nb) -> WriteBack Xneg | ||
| 48 | + [AIV->AIC] CrossCoreSetFlag(TRSV) | ||
| 49 | + [AIC] DirectRankK(GEMM) -> SetFlag(GEMM) | ||
| 50 | + [AIV] WaitFlag(GEMM) -> WriteBackPanelRows -> LoadPanelA(next) -> 下一 panel | ||
| 51 | +``` | ||
| 52 | + | ||
| 53 | +**双 AIV 分列优化:** | ||
| 54 | + | ||
| 55 | +大矩阵场景(kDim>=128 且 nColsAligned>=128)自动启用双 AIV 分列模式: | ||
| 56 | +- 两个 AIV 核协同处理同一矩阵,各处理一半列 | ||
| 57 | +- 消除 AIV 空转,提升 AIV 利用率 | ||
| 58 | +- Panel solve 和 WriteBack 按列并行 | ||
| 59 | + | ||
| 60 | +**多核拆分优化:** | ||
| 61 | + | ||
| 62 | +小 batch 场景(batch <= AI Core 数/2)自动启用多核拆分: | ||
| 63 | +- 每个 batch 的列方向拆分到多个 AI Core 并行处理 | ||
| 64 | +- minSplitNCols=64,充分利用空闲核心 | ||
| 65 | + | ||
| 66 | +**转置优化:** | ||
| 67 | + | ||
| 68 | +AoS<->SoA 格式转换采用 3 块 buffer 轮转设计: | ||
| 69 | +- 动态 tileCols(根据可用 UB 空间计算,大矩阵 240~280 列/tile) | ||
| 70 | +- Gather 偏移表解交织(支持任意非对齐尺寸) | ||
| 71 | +- Duplicate 预清零 + dstStride 控制行步长(绕过 rightPadding < 32B 限制) | ||
| 72 | +- padOn=false 时跳过清零,减少 PipeBarrier 开销 | ||
| 73 | + | ||
| 74 | +## 目录结构 | ||
| 75 | + | ||
| 76 | +``` | ||
| 77 | +aclblasCtrsmBatched2/ | ||
| 78 | +├── CMakeLists.txt | ||
| 79 | +├── README.md | ||
| 80 | +├── run.sh # 单用例快捷脚本(编译+生成+运行+校验) | ||
| 81 | +├── op_host/ | ||
| 82 | +│ ├── ctrsm_batched_host.cpp # Host 侧:参数校验、Tiling、Kernel 启动 | ||
| 83 | +│ └── ctrsm_batched_kernel_do.h # Kernel 启动包装声明 | ||
| 84 | +├── op_kernel/ | ||
| 85 | +│ ├── ctrsm_batched_kernel.cpp # Kernel 入口(MIX 模式,按 side/uplo/transa 分派四路径) | ||
| 86 | +│ ├── ctrsm_batched_kernel_aic.h # AIC Cube核实现(GEMM trail 更新) | ||
| 87 | +│ ├── ctrsm_batched_kernel_common.h # 公共常量和工具函数 | ||
| 88 | +│ ├── ctrsm_batched_tiling_data.h # Tiling 数据结构定义 | ||
| 89 | +│ │ # ---- AIV 向量核按职责拆分的协作类 ---- | ||
| 90 | +│ ├── ctrsm_batched_kernel_aiv.h # 编排类 CtrsmMixAivImpl<FORWARD,RIGHT>(含四路径别名) | ||
| 91 | +│ ├── ctrsm_batched_kernel_aiv_cfg.h # 共享派生配置 + UB buffer 指针 | ||
| 92 | +│ ├── ctrsm_batched_kernel_aiv_convert.h # 复数 AoS<->SoA 转换/分块转置工具(路径无关) | ||
| 93 | +│ ├── ctrsm_batched_kernel_aiv_canon_a.h # A 矩阵规范化(补零/转置/共轭) | ||
| 94 | +│ ├── ctrsm_batched_kernel_aiv_canon_b.h # B 矩阵规范化与回写(左/右乘,模板 RIGHT) | ||
| 95 | +│ ├── ctrsm_batched_kernel_aiv_canon_b_deinterleave.h # B 矩阵 AoS 解交织实现 | ||
| 96 | +│ └── ctrsm_batched_kernel_aiv_solver.h # Panel 三角求解(前代/回代,模板 FORWARD) | ||
| 97 | +├── test/ | ||
| 98 | +│ ├── CMakeLists.txt | ||
| 99 | +│ ├── ctrsm_batched_test.cpp # 测试主程序 | ||
| 100 | +│ └── data/ | ||
| 101 | +│ ├── gen_data.py # 测试数据生成(输入矩阵 + golden 参考结果) | ||
| 102 | +│ └── verify_result.py # 精度验证 | ||
| 103 | +└── docs/ | ||
| 104 | + ├── GPU_TEST # cuBLAS GPU 性能基准数据(320 case) | ||
| 105 | + └── perf_report_320cases_new.md # NPU 性能报告(对标 GPU) | ||
| 106 | +``` | ||
| 107 | + | ||
| 108 | +> AIV 实现按计算路径模板化为四个类型:`CtrsmLowerLeft` / `CtrsmLowerRight` / | ||
| 109 | +> `CtrsmUpperLeft` / `CtrsmUpperRight`(`CtrsmMixAivImpl<FORWARD,RIGHT>` 的别名), | ||
| 110 | +> 编译期消除 forward/right 分支;各职责类通过共享 cfg 与 UB buffer 指针协作。 | ||
| 111 | + | ||
| 112 | +## 编译运行 | ||
| 113 | + | ||
| 114 | +在本样例根目录下执行如下步骤,编译并执行算子。 | ||
| 115 | + | ||
| 116 | +- 配置环境变量 | ||
| 117 | + | ||
| 118 | + 请根据当前环境上CANN开发套件包的安装方式,选择对应配置环境变量的命令。 | ||
| 119 | + ```bash | ||
| 120 | + source ${ASCEND_HOME_PATH}/set_env.sh | ||
| 121 | + ``` | ||
| 122 | + | ||
| 123 | +- 构建 | ||
| 124 | + ```bash | ||
| 125 | + mkdir -p build && cd build | ||
| 126 | + cmake .. | ||
| 127 | + make -j8 | ||
| 128 | + cd .. | ||
| 129 | + ``` | ||
| 130 | + | ||
| 131 | +- 样例执行 | ||
| 132 | + ```bash | ||
| 133 | + # Step 1: 生成测试数据(输入矩阵 + golden 参考结果) | ||
| 134 | + python3 test/data/gen_data.py 64 64 32 0 0 0 0 1.0 0.0 | ||
| 135 | + | ||
| 136 | + # Step 2: 运行算子 | ||
| 137 | + # 参数: deviceId m n batch side uplo transa diag [alpha_re] [alpha_im] | ||
| 138 | + ./build/test/ctrsm_batched_test 0 64 64 32 0 0 0 0 1.0 0.0 | ||
| 139 | + | ||
| 140 | + # Step 3: 验证精度 | ||
| 141 | + python3 test/data/verify_result.py 64 64 32 | ||
| 142 | + ``` | ||
| 143 | + | ||
| 144 | + 执行结果如下,说明精度对比成功: | ||
| 145 | + ``` | ||
| 146 | + [Success] Case accuracy verification passed. | ||
| 147 | + ``` | ||
| 148 | + | ||
| 149 | + 也可用 `run.sh` 一键完成上述三步(编译+生成+运行+校验): | ||
| 150 | + ```bash | ||
| 151 | + # 参数: m n batch side uplo transa diag [alpha_re] [alpha_im] [--skip-build] | ||
| 152 | + bash run.sh 64 64 32 0 0 0 0 1.0 0.0 | ||
| 153 | + ``` | ||
| 154 | + | ||
| 155 | +## 参数说明 | ||
| 156 | + | ||
| 157 | +gen_data.py / ctrsm_batched_test 参数顺序: | ||
| 158 | +``` | ||
| 159 | +m n batch side uplo transa diag [alpha_re] [alpha_im] | ||
| 160 | +``` | ||
| 161 | + | ||
| 162 | +| 参数 | 取值 | 说明 | | ||
| 163 | +|------|------|------| | ||
| 164 | +| side | 0/1 | 0=Left, 1=Right | | ||
| 165 | +| uplo | 0/1 | 0=Upper, 1=Lower | | ||
| 166 | +| transa | 0/1/2 | 0=NoTrans, 1=Trans, 2=ConjTrans | | ||
| 167 | +| diag | 0/1 | 0=NonUnit, 1=Unit | | ||
| 168 | +| alpha_re | float | alpha 实部(默认 1.0) | | ||
| 169 | +| alpha_im | float | alpha 虚部(默认 0.0) | | ||
| 170 | + | ||
| 171 | +## 关键参数 | ||
| 172 | + | ||
| 173 | +| 参数 | 值 | 说明 | | ||
| 174 | +|------|------|------| | ||
| 175 | +| MIX_NB_SMALL | 16 | Panel 分块大小(kDim<=1024) | | ||
| 176 | +| MIX_NB_LARGE | 32 | Panel 分块大小(kDim>1024) | | ||
| 177 | +| LIM_GROUP | 16 | Xneg 分组大小 | | ||
| 178 | +| FLOAT_ALIGN | 8 | 向量对齐宽度(float32,8 元素 = 32B) | | ||
| 179 | +| TOTAL_AICORES | 20 | AI Core 总数(Ascend910B4) | | ||
| 180 | +| minSplitNCols | 64 | 多核拆分最小列数 | | ||
| 181 | +| SOC_VERSION | Ascend910B4 | 目标硬件 | | ||
| 182 | +| dualAivMode | auto | kDim>=128 且 nColsAligned>=128 时自动启用 | | ||
| 183 | + | ||
| 184 | +## 性能数据 | ||
| 185 | + | ||
| 186 | +320 Case 全量测试(对标 cuBLAS cublasCtrsmBatched): | ||
| 187 | + | ||
| 188 | +- 平均 GPU/NPU: **0.800** | ||
| 189 | +- NPU 更快(GPU/NPU >= 1.0): 109/320 个 case(34%) | ||
| 190 | +- GPU/NPU 最大: 1.776(大矩阵场景 NPU 最多快 78%) | ||
| 191 | + | ||
| 192 | +详见 `docs/perf_report_320cases_new.md`。 | ||
| 193 | + | ||
| 194 | +## 精度标准 | ||
| 195 | + | ||
| 196 | +相对误差阈值:`MERE < 2^-13 * 10 = 1.22e-3` | ||
| 197 | + | ||
| 198 | +精度验证覆盖: | ||
| 199 | +- 16 种 side*uplo*transa*diag 模式组合 | ||
| 200 | +- 矩阵尺寸 16~8192 | ||
| 201 | +- batch 数 1~248 | ||
| 202 | +- 复数 alpha 缩放 | ||
| 203 | +- 非对齐尺寸(17, 20, 31, 33, 227 等) | ||
| 204 | +- 320 Case 全量精度通过 | ||
| @@ -0,0 +1,334 @@ | |||
| 1 | +# Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 2 | +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 3 | +# CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 4 | +# Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 5 | +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 6 | +# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 7 | +# See LICENSE in the root of the software repository for the full text of the License. | ||
| 8 | + | ||
| 9 | +Compiling with nvcc... | ||
| 10 | +Running cuBLAS cublasCtrsmBatched benchmark (per-case process, device=7)... | ||
| 11 | + | ||
| 12 | + # m n bat mode algn alpha kernel(us) | ||
| 13 | +------------------------------------------------------ | ||
| 14 | + 1 16 16 118 L/U/N/N A 1.0 21.22 | ||
| 15 | + 2 16 16 118 L/U/N/U A 1.0 18.24 | ||
| 16 | + 3 16 16 118 L/U/T/N A 1.0 11.97 | ||
| 17 | + 4 16 16 118 L/U/T/U A 1.0 9.73 | ||
| 18 | + 5 16 16 118 L/L/N/N A 1.0 12.26 | ||
| 19 | + 6 16 16 118 L/L/N/U A 1.0 9.95 | ||
| 20 | + 7 16 16 118 L/L/T/N A 1.0 21.47 | ||
| 21 | + 8 16 16 118 L/L/T/U A 1.0 18.46 | ||
| 22 | + 9 16 16 118 R/U/N/N A 1.0 11.65 | ||
| 23 | + 10 16 16 118 R/U/N/U A 1.0 9.41 | ||
| 24 | + 11 16 16 118 R/U/T/N A 1.0 11.52 | ||
| 25 | + 12 16 16 118 R/U/T/U A 1.0 9.28 | ||
| 26 | + 13 16 16 118 R/L/N/N A 1.0 11.52 | ||
| 27 | + 14 16 16 118 R/L/N/U A 1.0 9.28 | ||
| 28 | + 15 16 16 118 R/L/T/N A 1.0 11.78 | ||
| 29 | + 16 16 16 118 R/L/T/U A 1.0 9.47 | ||
| 30 | + 17 224 64 87 L/U/N/N A 1.0 285.09 | ||
| 31 | + 18 224 64 87 L/U/N/U A 1.0 252.83 | ||
| 32 | + 19 224 64 87 L/U/T/N A 1.0 299.39 | ||
| 33 | + 20 224 64 87 L/U/T/U A 1.0 267.74 | ||
| 34 | + 21 224 64 87 L/L/N/N A 1.0 310.46 | ||
| 35 | + 22 224 64 87 L/L/N/U A 1.0 278.85 | ||
| 36 | + 23 224 64 87 L/L/T/N A 1.0 284.80 | ||
| 37 | + 24 224 64 87 L/L/T/U A 1.0 251.42 | ||
| 38 | + 25 224 64 87 R/U/N/N A 1.0 97.41 | ||
| 39 | + 26 224 64 87 R/U/N/U A 1.0 86.08 | ||
| 40 | + 27 224 64 87 R/U/T/N A 1.0 97.28 | ||
| 41 | + 28 224 64 87 R/U/T/U A 1.0 86.08 | ||
| 42 | + 29 224 64 87 R/L/N/N A 1.0 97.18 | ||
| 43 | + 30 224 64 87 R/L/N/U A 1.0 86.05 | ||
| 44 | + 31 224 64 87 R/L/T/N A 1.0 97.57 | ||
| 45 | + 32 224 64 87 R/L/T/U A 1.0 86.30 | ||
| 46 | + 33 224 112 71 L/U/N/N A 1.0 342.27 | ||
| 47 | + 34 224 112 71 L/U/N/U A 1.0 305.38 | ||
| 48 | + 35 224 112 71 L/U/T/N A 1.0 364.80 | ||
| 49 | + 36 224 112 71 L/U/T/U A 1.0 326.91 | ||
| 50 | + 37 224 112 71 L/L/N/N A 1.0 375.71 | ||
| 51 | + 38 224 112 71 L/L/N/U A 1.0 336.80 | ||
| 52 | + 39 224 112 71 L/L/T/N A 1.0 346.62 | ||
| 53 | + 40 224 112 71 L/L/T/U A 1.0 308.19 | ||
| 54 | + 41 224 112 71 R/U/N/N A 1.0 188.83 | ||
| 55 | + 42 224 112 71 R/U/N/U A 1.0 169.31 | ||
| 56 | + 43 224 112 71 R/U/T/N A 1.0 178.14 | ||
| 57 | + 44 224 112 71 R/U/T/U A 1.0 160.22 | ||
| 58 | + 45 224 112 71 R/L/N/N A 1.0 178.88 | ||
| 59 | + 46 224 112 71 R/L/N/U A 1.0 160.83 | ||
| 60 | + 47 224 112 71 R/L/T/N A 1.0 188.45 | ||
| 61 | + 48 224 112 71 R/L/T/U A 1.0 169.41 | ||
| 62 | + 49 227 210 248 L/U/N/N N 1.0 1542.30 | ||
| 63 | + 50 227 210 248 L/U/N/U N 1.0 1446.53 | ||
| 64 | + 51 227 210 248 L/U/T/N N 1.0 1673.98 | ||
| 65 | + 52 227 210 248 L/U/T/U N 1.0 1573.18 | ||
| 66 | + 53 227 210 248 L/L/N/N N 1.0 1721.12 | ||
| 67 | + 54 227 210 248 L/L/N/U N 1.0 1621.02 | ||
| 68 | + 55 227 210 248 L/L/T/N N 1.0 1631.62 | ||
| 69 | + 56 227 210 248 L/L/T/U N 1.0 1509.60 | ||
| 70 | + 57 227 210 248 R/U/N/N N 1.0 1636.16 | ||
| 71 | + 58 227 210 248 R/U/N/U N 1.0 1559.14 | ||
| 72 | + 59 227 210 248 R/U/T/N N 1.0 1492.74 | ||
| 73 | + 60 227 210 248 R/U/T/U N 1.0 1417.34 | ||
| 74 | + 61 227 210 248 R/L/N/N N 1.0 1508.67 | ||
| 75 | + 62 227 210 248 R/L/N/U N 1.0 1434.37 | ||
| 76 | + 63 227 210 248 R/L/T/N N 1.0 1628.16 | ||
| 77 | + 64 227 210 248 R/L/T/U N 1.0 1551.46 | ||
| 78 | + 65 184 212 10 L/U/N/N N 1.0 165.95 | ||
| 79 | + 66 184 212 10 L/U/N/U N 1.0 138.91 | ||
| 80 | + 67 184 212 10 L/U/T/N N 1.0 177.25 | ||
| 81 | + 68 184 212 10 L/U/T/U N 1.0 152.26 | ||
| 82 | + 69 184 212 10 L/L/N/N N 1.0 187.55 | ||
| 83 | + 70 184 212 10 L/L/N/U N 1.0 161.54 | ||
| 84 | + 71 184 212 10 L/L/T/N N 1.0 164.13 | ||
| 85 | + 72 184 212 10 L/L/T/U N 1.0 139.68 | ||
| 86 | + 73 184 212 10 R/U/N/N N 1.0 215.39 | ||
| 87 | + 74 184 212 10 R/U/N/U N 1.0 187.01 | ||
| 88 | + 75 184 212 10 R/U/T/N N 1.0 203.87 | ||
| 89 | + 76 184 212 10 R/U/T/U N 1.0 174.50 | ||
| 90 | + 77 184 212 10 R/L/N/N N 1.0 207.94 | ||
| 91 | + 78 184 212 10 R/L/N/U N 1.0 177.02 | ||
| 92 | + 79 184 212 10 R/L/T/N N 1.0 216.64 | ||
| 93 | + 80 184 212 10 R/L/T/U N 1.0 186.11 | ||
| 94 | + 81 896 512 1 L/U/N/N A 1.0 865.22 | ||
| 95 | + 82 896 512 1 L/U/N/U A 1.0 743.07 | ||
| 96 | + 83 896 512 1 L/U/T/N A 1.0 895.01 | ||
| 97 | + 84 896 512 1 L/U/T/U A 1.0 772.00 | ||
| 98 | + 85 896 512 1 L/L/N/N A 1.0 940.64 | ||
| 99 | + 86 896 512 1 L/L/N/U A 1.0 819.97 | ||
| 100 | + 87 896 512 1 L/L/T/N A 1.0 857.38 | ||
| 101 | + 88 896 512 1 L/L/T/U A 1.0 734.14 | ||
| 102 | + 89 896 512 1 R/U/N/N A 1.0 471.39 | ||
| 103 | + 90 896 512 1 R/U/N/U A 1.0 403.78 | ||
| 104 | + 91 896 512 1 R/U/T/N A 1.0 471.62 | ||
| 105 | + 92 896 512 1 R/U/T/U A 1.0 403.10 | ||
| 106 | + 93 896 512 1 R/L/N/N A 1.0 473.34 | ||
| 107 | + 94 896 512 1 R/L/N/U A 1.0 399.94 | ||
| 108 | + 95 896 512 1 R/L/T/N A 1.0 477.44 | ||
| 109 | + 96 896 512 1 R/L/T/U A 1.0 404.61 | ||
| 110 | + 97 464 896 124 L/U/N/N A 1.0 8589.06 | ||
| 111 | + 98 464 896 124 L/U/N/U A 1.0 8243.23 | ||
| 112 | + 99 464 896 124 L/U/T/N A 1.0 9506.37 | ||
| 113 | +100 464 896 124 L/U/T/U A 1.0 9214.62 | ||
| 114 | +101 464 896 124 L/L/N/N A 1.0 9542.43 | ||
| 115 | +102 464 896 124 L/L/N/U A 1.0 9234.88 | ||
| 116 | +103 464 896 124 L/L/T/N A 1.0 8825.70 | ||
| 117 | +104 464 896 124 L/L/T/U A 1.0 8404.32 | ||
| 118 | +105 464 896 124 R/U/N/N A 1.0 14619.07 | ||
| 119 | +106 464 896 124 R/U/N/U A 1.0 14401.86 | ||
| 120 | +107 464 896 124 R/U/T/N A 1.0 14479.42 | ||
| 121 | +108 464 896 124 R/U/T/U A 1.0 14122.98 | ||
| 122 | +109 464 896 124 R/L/N/N A 1.0 14513.22 | ||
| 123 | +110 464 896 124 R/L/N/U A 1.0 14307.62 | ||
| 124 | +111 464 896 124 R/L/T/N A 1.0 14805.22 | ||
| 125 | +112 464 896 124 R/L/T/U A 1.0 14351.30 | ||
| 126 | +113 441 345 82 L/U/N/N N 1.0 2420.45 | ||
| 127 | +114 441 345 82 L/U/N/U N 1.0 2303.07 | ||
| 128 | +115 441 345 82 L/U/T/N N 1.0 2419.55 | ||
| 129 | +116 441 345 82 L/U/T/U N 1.0 2280.96 | ||
| 130 | +117 441 345 82 L/L/N/N N 1.0 2481.50 | ||
| 131 | +118 441 345 82 L/L/N/U N 1.0 2364.90 | ||
| 132 | +119 441 345 82 L/L/T/N N 1.0 2467.10 | ||
| 133 | +120 441 345 82 L/L/T/U N 1.0 2323.62 | ||
| 134 | +121 441 345 82 R/U/N/N N 1.0 2128.64 | ||
| 135 | +122 441 345 82 R/U/N/U N 1.0 2041.44 | ||
| 136 | +123 441 345 82 R/U/T/N N 1.0 1998.56 | ||
| 137 | +124 441 345 82 R/U/T/U N 1.0 1904.48 | ||
| 138 | +125 441 345 82 R/L/N/N N 1.0 2015.87 | ||
| 139 | +126 441 345 82 R/L/N/U N 1.0 1917.54 | ||
| 140 | +127 441 345 82 R/L/T/N N 1.0 2119.20 | ||
| 141 | +128 441 345 82 R/L/T/U N 1.0 2035.58 | ||
| 142 | +129 425 999 22 L/U/N/N N 1.0 1876.32 | ||
| 143 | +130 425 999 22 L/U/N/U N 1.0 1770.11 | ||
| 144 | +131 425 999 22 L/U/T/N N 1.0 1960.51 | ||
| 145 | +132 425 999 22 L/U/T/U N 1.0 1843.07 | ||
| 146 | +133 425 999 22 L/L/N/N N 1.0 1992.06 | ||
| 147 | +134 425 999 22 L/L/N/U N 1.0 1878.27 | ||
| 148 | +135 425 999 22 L/L/T/N N 1.0 1954.27 | ||
| 149 | +136 425 999 22 L/L/T/U N 1.0 1822.66 | ||
| 150 | +137 425 999 22 R/U/N/N N 1.0 3449.76 | ||
| 151 | +138 425 999 22 R/U/N/U N 1.0 3312.48 | ||
| 152 | +139 425 999 22 R/U/T/N N 1.0 3321.57 | ||
| 153 | +140 425 999 22 R/U/T/U N 1.0 3181.70 | ||
| 154 | +141 425 999 22 R/L/N/N N 1.0 3336.22 | ||
| 155 | +142 425 999 22 R/L/N/U N 1.0 3192.70 | ||
| 156 | +143 425 999 22 R/L/T/N N 1.0 3449.15 | ||
| 157 | +144 425 999 22 R/L/T/U N 1.0 3301.15 | ||
| 158 | +145 529 1005 103 L/U/N/N N 1.0 10673.82 | ||
| 159 | +146 529 1005 103 L/U/N/U N 1.0 10375.90 | ||
| 160 | +147 529 1005 103 L/U/T/N N 1.0 10623.97 | ||
| 161 | +148 529 1005 103 L/U/T/U N 1.0 10417.50 | ||
| 162 | +149 529 1005 103 L/L/N/N N 1.0 10769.31 | ||
| 163 | +150 529 1005 103 L/L/N/U N 1.0 10536.93 | ||
| 164 | +151 529 1005 103 L/L/T/N N 1.0 10774.34 | ||
| 165 | +152 529 1005 103 L/L/T/U N 1.0 10451.23 | ||
| 166 | +153 529 1005 103 R/U/N/N N 1.0 17596.87 | ||
| 167 | +154 529 1005 103 R/U/N/U N 1.0 17370.11 | ||
| 168 | +155 529 1005 103 R/U/T/N N 1.0 16902.18 | ||
| 169 | +156 529 1005 103 R/U/T/U N 1.0 16689.47 | ||
| 170 | +157 529 1005 103 R/L/N/N N 1.0 16971.46 | ||
| 171 | +158 529 1005 103 R/L/N/U N 1.0 16820.61 | ||
| 172 | +159 529 1005 103 R/L/T/N N 1.0 17355.10 | ||
| 173 | +160 529 1005 103 R/L/T/U N 1.0 17318.85 | ||
| 174 | +161 3696 2240 12 L/U/N/N A 1.0 85648.55 | ||
| 175 | +162 3696 2240 12 L/U/N/U A 1.0 84656.73 | ||
| 176 | +163 3696 2240 12 L/U/T/N A 1.0 86929.63 | ||
| 177 | +164 3696 2240 12 L/U/T/U A 1.0 85933.25 | ||
| 178 | +165 3696 2240 12 L/L/N/N A 1.0 86920.39 | ||
| 179 | +166 3696 2240 12 L/L/N/U A 1.0 85809.28 | ||
| 180 | +167 3696 2240 12 L/L/T/N A 1.0 85672.64 | ||
| 181 | +168 3696 2240 12 L/L/T/U A 1.0 84589.66 | ||
| 182 | +169 3696 2240 12 R/U/N/N A 1.0 55261.25 | ||
| 183 | +170 3696 2240 12 R/U/N/U A 1.0 55712.99 | ||
| 184 | +171 3696 2240 12 R/U/T/N A 1.0 54912.93 | ||
| 185 | +172 3696 2240 12 R/U/T/U A 1.0 55213.66 | ||
| 186 | +173 3696 2240 12 R/L/N/N A 1.0 54937.92 | ||
| 187 | +174 3696 2240 12 R/L/N/U A 1.0 55848.32 | ||
| 188 | +175 3696 2240 12 R/L/T/N A 1.0 55224.99 | ||
| 189 | +176 3696 2240 12 R/L/T/U A 1.0 55633.92 | ||
| 190 | +177 2048 3056 10 L/U/N/N A 1.0 32265.89 | ||
| 191 | +178 2048 3056 10 L/U/N/U A 1.0 31689.50 | ||
| 192 | +179 2048 3056 10 L/U/T/N A 1.0 32545.57 | ||
| 193 | +180 2048 3056 10 L/U/T/U A 1.0 32237.60 | ||
| 194 | +181 2048 3056 10 L/L/N/N A 1.0 32572.48 | ||
| 195 | +182 2048 3056 10 L/L/N/U A 1.0 31961.09 | ||
| 196 | +183 2048 3056 10 L/L/T/N A 1.0 32625.28 | ||
| 197 | +184 2048 3056 10 L/L/T/U A 1.0 31882.78 | ||
| 198 | +185 2048 3056 10 R/U/N/N A 1.0 47118.34 | ||
| 199 | +186 2048 3056 10 R/U/N/U A 1.0 47349.31 | ||
| 200 | +187 2048 3056 10 R/U/T/N A 1.0 46164.19 | ||
| 201 | +188 2048 3056 10 R/U/T/U A 1.0 46005.15 | ||
| 202 | +189 2048 3056 10 R/L/N/N A 1.0 46353.95 | ||
| 203 | +190 2048 3056 10 R/L/N/U A 1.0 46460.64 | ||
| 204 | +191 2048 3056 10 R/L/T/N A 1.0 46901.60 | ||
| 205 | +192 2048 3056 10 R/L/T/U A 1.0 47032.19 | ||
| 206 | +193 3488 3984 9 L/U/N/N A 1.0 102527.39 | ||
| 207 | +194 3488 3984 9 L/U/N/U A 1.0 102334.84 | ||
| 208 | +195 3488 3984 9 L/U/T/N A 1.0 104808.80 | ||
| 209 | +196 3488 3984 9 L/U/T/U A 1.0 104526.69 | ||
| 210 | +197 3488 3984 9 L/L/N/N A 1.0 104968.73 | ||
| 211 | +198 3488 3984 9 L/L/N/U A 1.0 104753.92 | ||
| 212 | +199 3488 3984 9 L/L/T/N A 1.0 103577.12 | ||
| 213 | +200 3488 3984 9 L/L/T/U A 1.0 104086.05 | ||
| 214 | +201 3488 3984 9 R/U/N/N A 1.0 120291.20 | ||
| 215 | +202 3488 3984 9 R/U/N/U A 1.0 122157.89 | ||
| 216 | +203 3488 3984 9 R/U/T/N A 1.0 116856.28 | ||
| 217 | +204 3488 3984 9 R/U/T/U A 1.0 118841.98 | ||
| 218 | +205 3488 3984 9 R/L/N/N A 1.0 117833.80 | ||
| 219 | +206 3488 3984 9 R/L/N/U A 1.0 119511.97 | ||
| 220 | +207 3488 3984 9 R/L/T/N A 1.0 120376.45 | ||
| 221 | +208 3488 3984 9 R/L/T/U A 1.0 121777.77 | ||
| 222 | +209 1667 1941 38 L/U/N/N N 1.0 53272.04 | ||
| 223 | +210 1667 1941 38 L/U/N/U N 1.0 53484.42 | ||
| 224 | +211 1667 1941 38 L/U/T/N N 1.0 56210.95 | ||
| 225 | +212 1667 1941 38 L/U/T/U N 1.0 56814.66 | ||
| 226 | +213 1667 1941 38 L/L/N/N N 1.0 56410.79 | ||
| 227 | +214 1667 1941 38 L/L/N/U N 1.0 56884.64 | ||
| 228 | +215 1667 1941 38 L/L/T/N N 1.0 53830.72 | ||
| 229 | +216 1667 1941 38 L/L/T/U N 1.0 54005.79 | ||
| 230 | +217 1667 1941 38 R/U/N/N N 1.0 64610.88 | ||
| 231 | +218 1667 1941 38 R/U/N/U N 1.0 65375.65 | ||
| 232 | +219 1667 1941 38 R/U/T/N N 1.0 61704.00 | ||
| 233 | +220 1667 1941 38 R/U/T/U N 1.0 62640.89 | ||
| 234 | +221 1667 1941 38 R/L/N/N N 1.0 62579.90 | ||
| 235 | +222 1667 1941 38 R/L/N/U N 1.0 63028.45 | ||
| 236 | +223 1667 1941 38 R/L/T/N N 1.0 63981.18 | ||
| 237 | +224 1667 1941 38 R/L/T/U N 1.0 65156.29 | ||
| 238 | +225 3516 1213 16 L/U/N/N N 1.0 56914.18 | ||
| 239 | +226 3516 1213 16 L/U/N/U N 1.0 56911.55 | ||
| 240 | +227 3516 1213 16 L/U/T/N N 1.0 57184.26 | ||
| 241 | +228 3516 1213 16 L/U/T/U N 1.0 57743.90 | ||
| 242 | +229 3516 1213 16 L/L/N/N N 1.0 56918.59 | ||
| 243 | +230 3516 1213 16 L/L/N/U N 1.0 56856.70 | ||
| 244 | +231 3516 1213 16 L/L/T/N N 1.0 58438.56 | ||
| 245 | +232 3516 1213 16 L/L/T/U N 1.0 58054.75 | ||
| 246 | +233 3516 1213 16 R/U/N/N N 1.0 23256.61 | ||
| 247 | +234 3516 1213 16 R/U/N/U N 1.0 23204.54 | ||
| 248 | +235 3516 1213 16 R/U/T/N N 1.0 22865.31 | ||
| 249 | +236 3516 1213 16 R/U/T/U N 1.0 23085.50 | ||
| 250 | +237 3516 1213 16 R/L/N/N N 1.0 22929.92 | ||
| 251 | +238 3516 1213 16 R/L/N/U N 1.0 23164.13 | ||
| 252 | +239 3516 1213 16 R/L/T/N N 1.0 22955.01 | ||
| 253 | +240 3516 1213 16 R/L/T/U N 1.0 23150.85 | ||
| 254 | +241 4848 5456 4 L/U/N/N A 1.0 118500.10 | ||
| 255 | +242 4848 5456 4 L/U/N/U A 1.0 118494.50 | ||
| 256 | +243 4848 5456 4 L/U/T/N A 1.0 120393.02 | ||
| 257 | +244 4848 5456 4 L/U/T/U A 1.0 121084.89 | ||
| 258 | +245 4848 5456 4 L/L/N/N A 1.0 120566.66 | ||
| 259 | +246 4848 5456 4 L/L/N/U A 1.0 121182.56 | ||
| 260 | +247 4848 5456 4 L/L/T/N A 1.0 119625.53 | ||
| 261 | +248 4848 5456 4 L/L/T/U A 1.0 120280.86 | ||
| 262 | +249 4848 5456 4 R/U/N/N A 1.0 135500.12 | ||
| 263 | +250 4848 5456 4 R/U/N/U A 1.0 138115.73 | ||
| 264 | +251 4848 5456 4 R/U/T/N A 1.0 132898.78 | ||
| 265 | +252 4848 5456 4 R/U/T/U A 1.0 135684.19 | ||
| 266 | +253 4848 5456 4 R/L/N/N A 1.0 134287.00 | ||
| 267 | +254 4848 5456 4 R/L/N/U A 1.0 136519.11 | ||
| 268 | +255 4848 5456 4 R/L/T/N A 1.0 135868.95 | ||
| 269 | +256 4848 5456 4 R/L/T/U A 1.0 138065.50 | ||
| 270 | +257 4512 4416 6 L/U/N/N A 1.0 125041.05 | ||
| 271 | +258 4512 4416 6 L/U/N/U A 1.0 126066.66 | ||
| 272 | +259 4512 4416 6 L/U/T/N A 1.0 127903.39 | ||
| 273 | +260 4512 4416 6 L/U/T/U A 1.0 129417.86 | ||
| 274 | +261 4512 4416 6 L/L/N/N A 1.0 127579.77 | ||
| 275 | +262 4512 4416 6 L/L/N/U A 1.0 128757.02 | ||
| 276 | +263 4512 4416 6 L/L/T/N A 1.0 125818.27 | ||
| 277 | +264 4512 4416 6 L/L/T/U A 1.0 127075.94 | ||
| 278 | +265 4512 4416 6 R/U/N/N A 1.0 126647.13 | ||
| 279 | +266 4512 4416 6 R/U/N/U A 1.0 129172.93 | ||
| 280 | +267 4512 4416 6 R/U/T/N A 1.0 125424.12 | ||
| 281 | +268 4512 4416 6 R/U/T/U A 1.0 127995.01 | ||
| 282 | +269 4512 4416 6 R/L/N/N A 1.0 126038.56 | ||
| 283 | +270 4512 4416 6 R/L/N/U A 1.0 128781.16 | ||
| 284 | +271 4512 4416 6 R/L/T/N A 1.0 125690.37 | ||
| 285 | +272 4512 4416 6 R/L/T/U A 1.0 128672.77 | ||
| 286 | +273 5266 5889 4 L/U/N/N N 1.0 152843.03 | ||
| 287 | +274 5266 5889 4 L/U/N/U N 1.0 154440.73 | ||
| 288 | +275 5266 5889 4 L/U/T/N N 1.0 156797.83 | ||
| 289 | +276 5266 5889 4 L/U/T/U N 1.0 159061.45 | ||
| 290 | +277 5266 5889 4 L/L/N/N N 1.0 156095.94 | ||
| 291 | +278 5266 5889 4 L/L/N/U N 1.0 157649.39 | ||
| 292 | +279 5266 5889 4 L/L/T/N N 1.0 155538.84 | ||
| 293 | +280 5266 5889 4 L/L/T/U N 1.0 157420.17 | ||
| 294 | +281 5266 5889 4 R/U/N/N N 1.0 178707.81 | ||
| 295 | +282 5266 5889 4 R/U/N/U N 1.0 182535.81 | ||
| 296 | +283 5266 5889 4 R/U/T/N N 1.0 174600.80 | ||
| 297 | +284 5266 5889 4 R/U/T/U N 1.0 177594.75 | ||
| 298 | +285 5266 5889 4 R/L/N/N N 1.0 175695.17 | ||
| 299 | +286 5266 5889 4 R/L/N/U N 1.0 179542.17 | ||
| 300 | +287 5266 5889 4 R/L/T/N N 1.0 178823.88 | ||
| 301 | +288 5266 5889 4 R/L/T/U N 1.0 182232.75 | ||
| 302 | +289 5133 5564 4 L/U/N/N N 1.0 138911.86 | ||
| 303 | +290 5133 5564 4 L/U/N/U N 1.0 140006.05 | ||
| 304 | +291 5133 5564 4 L/U/T/N N 1.0 141711.58 | ||
| 305 | +292 5133 5564 4 L/U/T/U N 1.0 143658.11 | ||
| 306 | +293 5133 5564 4 L/L/N/N N 1.0 141402.88 | ||
| 307 | +294 5133 5564 4 L/L/N/U N 1.0 142816.95 | ||
| 308 | +295 5133 5564 4 L/L/T/N N 1.0 141330.42 | ||
| 309 | +296 5133 5564 4 L/L/T/U N 1.0 142665.55 | ||
| 310 | +297 5133 5564 4 R/U/N/N N 1.0 151550.28 | ||
| 311 | +298 5133 5564 4 R/U/N/U N 1.0 155652.09 | ||
| 312 | +299 5133 5564 4 R/U/T/N N 1.0 150478.97 | ||
| 313 | +300 5133 5564 4 R/U/T/U N 1.0 154308.95 | ||
| 314 | +301 5133 5564 4 R/L/N/N N 1.0 155072.42 | ||
| 315 | +302 5133 5564 4 R/L/N/U N 1.0 158661.28 | ||
| 316 | +303 5133 5564 4 R/L/T/N N 1.0 156274.28 | ||
| 317 | +304 5133 5564 4 R/L/T/U N 1.0 157852.00 | ||
| 318 | +305 6182 6412 3 L/U/N/N N 1.0 180365.95 | ||
| 319 | +306 6182 6412 3 L/U/N/U N 1.0 185667.42 | ||
| 320 | +307 6182 6412 3 L/U/T/N N 1.0 185798.17 | ||
| 321 | +308 6182 6412 3 L/U/T/U N 1.0 193007.11 | ||
| 322 | +309 6182 6412 3 L/L/N/N N 1.0 185935.45 | ||
| 323 | +310 6182 6412 3 L/L/N/U N 1.0 190123.81 | ||
| 324 | +311 6182 6412 3 L/L/T/N N 1.0 192106.59 | ||
| 325 | +312 6182 6412 3 L/L/T/U N 1.0 189200.45 | ||
| 326 | +313 6182 6412 3 R/U/N/N N 1.0 201003.58 | ||
| 327 | +314 6182 6412 3 R/U/N/U N 1.0 214975.00 | ||
| 328 | +315 6182 6412 3 R/U/T/N N 1.0 198764.48 | ||
| 329 | +316 6182 6412 3 R/U/T/U N 1.0 204046.08 | ||
| 330 | +317 6182 6412 3 R/L/N/N N 1.0 201021.09 | ||
| 331 | +318 6182 6412 3 R/L/N/U N 1.0 207048.50 | ||
| 332 | +319 6182 6412 3 R/L/T/N N 1.0 202174.27 | ||
| 333 | +320 6182 6412 3 R/L/T/U N 1.0 209951.39 | ||
| 334 | +------------------------------------------------------ | ||
| @@ -0,0 +1,437 @@ | |||
| 1 | +# CtrsmBatched 性能报告(320 Case 全量) | ||
| 2 | + | ||
| 3 | +## 测试环境 | ||
| 4 | + | ||
| 5 | +- **NPU**: Ascend910B4, 频率 1650MHz | ||
| 6 | +- **GPU**: cuBLAS cublasCtrsmBatched (对标参考) | ||
| 7 | +- **CANN**: 9.0.0-beta.2 | ||
| 8 | +- **Profiling**: msprof op, warm-up=3 | ||
| 9 | + | ||
| 10 | +## 总览 | ||
| 11 | + | ||
| 12 | +- 总用例数: 320 | ||
| 13 | +- GPU/NPU >= 1.0 (NPU更快): 109 个 | ||
| 14 | +- GPU/NPU 平均: 0.800 | ||
| 15 | +- GPU/NPU 最大: 1.776 | ||
| 16 | +- GPU/NPU 最小: 0.118 | ||
| 17 | + | ||
| 18 | +## Case 1-16(m=16, n=16, batch=118) | ||
| 19 | + | ||
| 20 | +| # | mode | NPU(us) | GPU(us) | GPU/NPU | | ||
| 21 | +|---|------|---------|---------|--------| | ||
| 22 | +| 1 | L/U/N/N | 64.96 | 21.22 | 0.3267 | | ||
| 23 | +| 2 | L/U/N/U | 63.28 | 18.24 | 0.2882 | | ||
| 24 | +| 3 | L/U/T/N | 71.52 | 11.97 | 0.1674 | | ||
| 25 | +| 4 | L/U/T/U | 73.00 | 9.73 | 0.1333 | | ||
| 26 | +| 5 | L/L/N/N | 64.62 | 12.26 | 0.1897 | | ||
| 27 | +| 6 | L/L/N/U | 64.66 | 9.95 | 0.1539 | | ||
| 28 | +| 7 | L/L/T/N | 72.02 | 21.47 | 0.2981 | | ||
| 29 | +| 8 | L/L/T/U | 72.20 | 18.46 | 0.2557 | | ||
| 30 | +| 9 | R/U/N/N | 71.08 | 11.65 | 0.1639 | | ||
| 31 | +| 10 | R/U/N/U | 79.50 | 9.41 | 0.1184 | | ||
| 32 | +| 11 | R/U/T/N | 60.06 | 11.52 | 0.1918 | | ||
| 33 | +| 12 | R/U/T/U | 63.36 | 9.28 | 0.1465 | | ||
| 34 | +| 13 | R/L/N/N | 70.34 | 11.52 | 0.1638 | | ||
| 35 | +| 14 | R/L/N/U | 71.04 | 9.28 | 0.1306 | | ||
| 36 | +| 15 | R/L/T/N | 67.04 | 11.78 | 0.1757 | | ||
| 37 | +| 16 | R/L/T/U | 70.48 | 9.47 | 0.1344 | | ||
| 38 | + | ||
| 39 | +## Case 17-32(m=224, n=64, batch=87) | ||
| 40 | + | ||
| 41 | +| # | mode | NPU(us) | GPU(us) | GPU/NPU | | ||
| 42 | +|---|------|---------|---------|--------| | ||
| 43 | +| 17 | L/U/N/N | 683.71 | 285.09 | 0.4170 | | ||
| 44 | +| 18 | L/U/N/U | 645.29 | 252.83 | 0.3918 | | ||
| 45 | +| 19 | L/U/T/N | 925.62 | 299.39 | 0.3234 | | ||
| 46 | +| 20 | L/U/T/U | 878.92 | 267.74 | 0.3046 | | ||
| 47 | +| 21 | L/L/N/N | 689.27 | 310.46 | 0.4504 | | ||
| 48 | +| 22 | L/L/N/U | 653.27 | 278.85 | 0.4269 | | ||
| 49 | +| 23 | L/L/T/N | 919.30 | 284.80 | 0.3098 | | ||
| 50 | +| 24 | L/L/T/U | 880.40 | 251.42 | 0.2856 | | ||
| 51 | +| 25 | R/U/N/N | 361.55 | 97.41 | 0.2694 | | ||
| 52 | +| 26 | R/U/N/U | 348.69 | 86.08 | 0.2469 | | ||
| 53 | +| 27 | R/U/T/N | 342.85 | 97.28 | 0.2837 | | ||
| 54 | +| 28 | R/U/T/U | 324.99 | 86.08 | 0.2649 | | ||
| 55 | +| 29 | R/L/N/N | 363.71 | 97.18 | 0.2672 | | ||
| 56 | +| 30 | R/L/N/U | 346.55 | 86.05 | 0.2483 | | ||
| 57 | +| 31 | R/L/T/N | 345.61 | 97.57 | 0.2823 | | ||
| 58 | +| 32 | R/L/T/U | 332.67 | 86.30 | 0.2594 | | ||
| 59 | + | ||
| 60 | +## Case 33-48(m=224, n=112, batch=71) | ||
| 61 | + | ||
| 62 | +| # | mode | NPU(us) | GPU(us) | GPU/NPU | | ||
| 63 | +|---|------|---------|---------|--------| | ||
| 64 | +| 33 | L/U/N/N | 835.62 | 342.27 | 0.4096 | | ||
| 65 | +| 34 | L/U/N/U | 797.24 | 305.38 | 0.3830 | | ||
| 66 | +| 35 | L/U/T/N | 977.58 | 364.80 | 0.3732 | | ||
| 67 | +| 36 | L/U/T/U | 937.18 | 326.91 | 0.3488 | | ||
| 68 | +| 37 | L/L/N/N | 822.94 | 375.71 | 0.4565 | | ||
| 69 | +| 38 | L/L/N/U | 791.52 | 336.80 | 0.4255 | | ||
| 70 | +| 39 | L/L/T/N | 956.14 | 346.62 | 0.3625 | | ||
| 71 | +| 40 | L/L/T/U | 933.98 | 308.19 | 0.3300 | | ||
| 72 | +| 41 | R/U/N/N | 441.23 | 188.83 | 0.4280 | | ||
| 73 | +| 42 | R/U/N/U | 423.39 | 169.31 | 0.3999 | | ||
| 74 | +| 43 | R/U/T/N | 402.49 | 178.14 | 0.4426 | | ||
| 75 | +| 44 | R/U/T/U | 382.59 | 160.22 | 0.4188 | | ||
| 76 | +| 45 | R/L/N/N | 432.55 | 178.88 | 0.4135 | | ||
| 77 | +| 46 | R/L/N/U | 412.59 | 160.83 | 0.3898 | | ||
| 78 | +| 47 | R/L/T/N | 411.69 | 188.45 | 0.4577 | | ||
| 79 | +| 48 | R/L/T/U | 396.27 | 169.41 | 0.4275 | | ||
| 80 | + | ||
| 81 | +## Case 49-64(m=227, n=210, batch=248) | ||
| 82 | + | ||
| 83 | +| # | mode | NPU(us) | GPU(us) | GPU/NPU | | ||
| 84 | +|---|------|---------|---------|--------| | ||
| 85 | +| 49 | L/U/N/N | 4811.02 | 1542.30 | 0.3206 | | ||
| 86 | +| 50 | L/U/N/U | 4752.32 | 1446.53 | 0.3044 | | ||
| 87 | +| 51 | L/U/T/N | 4775.48 | 1673.98 | 0.3505 | | ||
| 88 | +| 52 | L/U/T/U | 4737.53 | 1573.18 | 0.3321 | | ||
| 89 | +| 53 | L/L/N/N | 4727.49 | 1721.12 | 0.3641 | | ||
| 90 | +| 54 | L/L/N/U | 4677.69 | 1621.02 | 0.3465 | | ||
| 91 | +| 55 | L/L/T/N | 4875.74 | 1631.62 | 0.3346 | | ||
| 92 | +| 56 | L/L/T/U | 4824.86 | 1509.60 | 0.3129 | | ||
| 93 | +| 57 | R/U/N/N | 4892.30 | 1636.16 | 0.3344 | | ||
| 94 | +| 58 | R/U/N/U | 4820.38 | 1559.14 | 0.3234 | | ||
| 95 | +| 59 | R/U/T/N | 4925.66 | 1492.74 | 0.3031 | | ||
| 96 | +| 60 | R/U/T/U | 4879.70 | 1417.34 | 0.2905 | | ||
| 97 | +| 61 | R/L/N/N | 4976.40 | 1508.67 | 0.3032 | | ||
| 98 | +| 62 | R/L/N/U | 4939.74 | 1434.37 | 0.2904 | | ||
| 99 | +| 63 | R/L/T/N | 4837.76 | 1628.16 | 0.3366 | | ||
| 100 | +| 64 | R/L/T/U | 4786.12 | 1551.46 | 0.3242 | | ||
| 101 | + | ||
| 102 | +## Case 65-80(m=184, n=212, batch=10) | ||
| 103 | + | ||
| 104 | +| # | mode | NPU(us) | GPU(us) | GPU/NPU | | ||
| 105 | +|---|------|---------|---------|--------| | ||
| 106 | +| 65 | L/U/N/N | 213.14 | 165.95 | 0.7786 | | ||
| 107 | +| 66 | L/U/N/U | 211.94 | 138.91 | 0.6554 | | ||
| 108 | +| 67 | L/U/T/N | 216.24 | 177.25 | 0.8197 | | ||
| 109 | +| 68 | L/U/T/U | 213.38 | 152.26 | 0.7135 | | ||
| 110 | +| 69 | L/L/N/N | 212.56 | 187.55 | 0.8823 | | ||
| 111 | +| 70 | L/L/N/U | 208.62 | 161.54 | 0.7743 | | ||
| 112 | +| 71 | L/L/T/N | 216.62 | 164.13 | 0.7577 | | ||
| 113 | +| 72 | L/L/T/U | 218.12 | 139.68 | 0.6404 | | ||
| 114 | +| 73 | R/U/N/N | 259.71 | 215.39 | 0.8294 | | ||
| 115 | +| 74 | R/U/N/U | 258.37 | 187.01 | 0.7238 | | ||
| 116 | +| 75 | R/U/T/N | 260.59 | 203.87 | 0.7824 | | ||
| 117 | +| 76 | R/U/T/U | 264.71 | 174.50 | 0.6592 | | ||
| 118 | +| 77 | R/L/N/N | 261.13 | 207.94 | 0.7963 | | ||
| 119 | +| 78 | R/L/N/U | 260.37 | 177.02 | 0.6799 | | ||
| 120 | +| 79 | R/L/T/N | 264.05 | 216.64 | 0.8205 | | ||
| 121 | +| 80 | R/L/T/U | 258.45 | 186.11 | 0.7201 | | ||
| 122 | + | ||
| 123 | +## Case 81-96(m=896, n=512, batch=1) | ||
| 124 | + | ||
| 125 | +| # | mode | NPU(us) | GPU(us) | GPU/NPU | | ||
| 126 | +|---|------|---------|---------|--------| | ||
| 127 | +| 81 | L/U/N/N | 683.67 | 865.22 | 1.2655 | | ||
| 128 | +| 82 | L/U/N/U | 637.43 | 743.07 | 1.1657 | | ||
| 129 | +| 83 | L/U/T/N | 1035.02 | 895.01 | 0.8647 | | ||
| 130 | +| 84 | L/U/T/U | 976.12 | 772.00 | 0.7909 | | ||
| 131 | +| 85 | L/L/N/N | 692.23 | 940.64 | 1.3588 | | ||
| 132 | +| 86 | L/L/N/U | 640.89 | 819.97 | 1.2794 | | ||
| 133 | +| 87 | L/L/T/N | 1025.70 | 857.38 | 0.8359 | | ||
| 134 | +| 88 | L/L/T/U | 992.24 | 734.14 | 0.7399 | | ||
| 135 | +| 89 | R/U/N/N | 514.25 | 471.39 | 0.9167 | | ||
| 136 | +| 90 | R/U/N/U | 493.61 | 403.78 | 0.8180 | | ||
| 137 | +| 91 | R/U/T/N | 395.97 | 471.62 | 1.1911 | | ||
| 138 | +| 92 | R/U/T/U | 371.97 | 403.10 | 1.0837 | | ||
| 139 | +| 93 | R/L/N/N | 503.01 | 473.34 | 0.9410 | | ||
| 140 | +| 94 | R/L/N/U | 484.37 | 399.94 | 0.8257 | | ||
| 141 | +| 95 | R/L/T/N | 397.45 | 477.44 | 1.2013 | | ||
| 142 | +| 96 | R/L/T/U | 371.27 | 404.61 | 1.0898 | | ||
| 143 | + | ||
| 144 | +## Case 97-112(m=464, n=896, batch=124) | ||
| 145 | + | ||
| 146 | +| # | mode | NPU(us) | GPU(us) | GPU/NPU | | ||
| 147 | +|---|------|---------|---------|--------| | ||
| 148 | +| 97 | L/U/N/N | 8759.88 | 8589.06 | 0.9805 | | ||
| 149 | +| 98 | L/U/N/U | 8277.81 | 8243.23 | 0.9958 | | ||
| 150 | +| 99 | L/U/T/N | 10024.32 | 9506.37 | 0.9483 | | ||
| 151 | +| 100 | L/U/T/U | 9635.69 | 9214.62 | 0.9563 | | ||
| 152 | +| 101 | L/L/N/N | 8810.82 | 9542.43 | 1.0830 | | ||
| 153 | +| 102 | L/L/N/U | 8480.23 | 9234.88 | 1.0890 | | ||
| 154 | +| 103 | L/L/T/N | 9827.86 | 8825.70 | 0.8980 | | ||
| 155 | +| 104 | L/L/T/U | 9486.99 | 8404.32 | 0.8859 | | ||
| 156 | +| 105 | R/U/N/N | 23799.22 | 14619.07 | 0.6143 | | ||
| 157 | +| 106 | R/U/N/U | 23524.83 | 14401.86 | 0.6122 | | ||
| 158 | +| 107 | R/U/T/N | 19042.10 | 14479.42 | 0.7604 | | ||
| 159 | +| 108 | R/U/T/U | 18927.24 | 14122.98 | 0.7462 | | ||
| 160 | +| 109 | R/L/N/N | 23522.09 | 14513.22 | 0.6170 | | ||
| 161 | +| 110 | R/L/N/U | 23270.43 | 14307.62 | 0.6148 | | ||
| 162 | +| 111 | R/L/T/N | 19356.05 | 14805.22 | 0.7649 | | ||
| 163 | +| 112 | R/L/T/U | 19231.74 | 14351.30 | 0.7462 | | ||
| 164 | + | ||
| 165 | +## Case 113-128(m=441, n=345, batch=82) | ||
| 166 | + | ||
| 167 | +| # | mode | NPU(us) | GPU(us) | GPU/NPU | | ||
| 168 | +|---|------|---------|---------|--------| | ||
| 169 | +| 113 | L/U/N/N | 3613.95 | 2420.45 | 0.6698 | | ||
| 170 | +| 114 | L/U/N/U | 3585.35 | 2303.07 | 0.6424 | | ||
| 171 | +| 115 | L/U/T/N | 3829.46 | 2419.55 | 0.6318 | | ||
| 172 | +| 116 | L/U/T/U | 3798.28 | 2280.96 | 0.6005 | | ||
| 173 | +| 117 | L/L/N/N | 3640.13 | 2481.50 | 0.6817 | | ||
| 174 | +| 118 | L/L/N/U | 3580.63 | 2364.90 | 0.6605 | | ||
| 175 | +| 119 | L/L/T/N | 3869.54 | 2467.10 | 0.6376 | | ||
| 176 | +| 120 | L/L/T/U | 3798.22 | 2323.62 | 0.6118 | | ||
| 177 | +| 121 | R/U/N/N | 4335.09 | 2128.64 | 0.4910 | | ||
| 178 | +| 122 | R/U/N/U | 4297.27 | 2041.44 | 0.4751 | | ||
| 179 | +| 123 | R/U/T/N | 4158.42 | 1998.56 | 0.4806 | | ||
| 180 | +| 124 | R/U/T/U | 4140.56 | 1904.48 | 0.4600 | | ||
| 181 | +| 125 | R/L/N/N | 4353.01 | 2015.87 | 0.4631 | | ||
| 182 | +| 126 | R/L/N/U | 4302.55 | 1917.54 | 0.4457 | | ||
| 183 | +| 127 | R/L/T/N | 4160.42 | 2119.20 | 0.5094 | | ||
| 184 | +| 128 | R/L/T/U | 4115.16 | 2035.58 | 0.4947 | | ||
| 185 | + | ||
| 186 | +## Case 129-144(m=425, n=999, batch=22) | ||
| 187 | + | ||
| 188 | +| # | mode | NPU(us) | GPU(us) | GPU/NPU | | ||
| 189 | +|---|------|---------|---------|--------| | ||
| 190 | +| 129 | L/U/N/N | 4271.73 | 1876.32 | 0.4392 | | ||
| 191 | +| 130 | L/U/N/U | 4173.84 | 1770.11 | 0.4241 | | ||
| 192 | +| 131 | L/U/T/N | 4309.29 | 1960.51 | 0.4550 | | ||
| 193 | +| 132 | L/U/T/U | 4296.35 | 1843.07 | 0.4290 | | ||
| 194 | +| 133 | L/L/N/N | 4302.99 | 1992.06 | 0.4629 | | ||
| 195 | +| 134 | L/L/N/U | 4206.58 | 1878.27 | 0.4465 | | ||
| 196 | +| 135 | L/L/T/N | 4483.21 | 1954.27 | 0.4359 | | ||
| 197 | +| 136 | L/L/T/U | 4298.03 | 1822.66 | 0.4241 | | ||
| 198 | +| 137 | R/U/N/N | 7125.36 | 3449.76 | 0.4842 | | ||
| 199 | +| 138 | R/U/N/U | 7141.76 | 3312.48 | 0.4638 | | ||
| 200 | +| 139 | R/U/T/N | 7013.26 | 3321.57 | 0.4736 | | ||
| 201 | +| 140 | R/U/T/U | 7023.56 | 3181.70 | 0.4530 | | ||
| 202 | +| 141 | R/L/N/N | 7155.60 | 3336.22 | 0.4662 | | ||
| 203 | +| 142 | R/L/N/U | 7116.20 | 3192.70 | 0.4487 | | ||
| 204 | +| 143 | R/L/T/N | 7046.22 | 3449.15 | 0.4895 | | ||
| 205 | +| 144 | R/L/T/U | 7093.70 | 3301.15 | 0.4654 | | ||
| 206 | + | ||
| 207 | +## Case 145-160(m=529, n=1005, batch=103) | ||
| 208 | + | ||
| 209 | +| # | mode | NPU(us) | GPU(us) | GPU/NPU | | ||
| 210 | +|---|------|---------|---------|--------| | ||
| 211 | +| 145 | L/U/N/N | 19050.24 | 10673.82 | 0.5603 | | ||
| 212 | +| 146 | L/U/N/U | 18436.57 | 10375.90 | 0.5628 | | ||
| 213 | +| 147 | L/U/T/N | 19159.42 | 10623.97 | 0.5545 | | ||
| 214 | +| 148 | L/U/T/U | 18417.89 | 10417.50 | 0.5656 | | ||
| 215 | +| 149 | L/L/N/N | 18985.74 | 10769.31 | 0.5672 | | ||
| 216 | +| 150 | L/L/N/U | 18710.07 | 10536.93 | 0.5632 | | ||
| 217 | +| 151 | L/L/T/N | 19025.66 | 10774.34 | 0.5663 | | ||
| 218 | +| 152 | L/L/T/U | 19062.54 | 10451.23 | 0.5483 | | ||
| 219 | +| 153 | R/U/N/N | 31525.31 | 17596.87 | 0.5582 | | ||
| 220 | +| 154 | R/U/N/U | 31695.25 | 17370.11 | 0.5480 | | ||
| 221 | +| 155 | R/U/T/N | 30567.01 | 16902.18 | 0.5530 | | ||
| 222 | +| 156 | R/U/T/U | 30659.99 | 16689.47 | 0.5443 | | ||
| 223 | +| 157 | R/L/N/N | 31533.33 | 16971.46 | 0.5382 | | ||
| 224 | +| 158 | R/L/N/U | 31140.62 | 16820.61 | 0.5402 | | ||
| 225 | +| 159 | R/L/T/N | 30774.94 | 17355.10 | 0.5639 | | ||
| 226 | +| 160 | R/L/T/U | 30830.52 | 17318.85 | 0.5617 | | ||
| 227 | + | ||
| 228 | +## Case 161-176(m=3696, n=2240, batch=12) | ||
| 229 | + | ||
| 230 | +| # | mode | NPU(us) | GPU(us) | GPU/NPU | | ||
| 231 | +|---|------|---------|---------|--------| | ||
| 232 | +| 161 | L/U/N/N | 108705.04 | 85648.55 | 0.7879 | | ||
| 233 | +| 162 | L/U/N/U | 108400.92 | 84656.73 | 0.7810 | | ||
| 234 | +| 163 | L/U/T/N | 116389.91 | 86929.63 | 0.7469 | | ||
| 235 | +| 164 | L/U/T/U | 116128.60 | 85933.25 | 0.7400 | | ||
| 236 | +| 165 | L/L/N/N | 108674.97 | 86920.39 | 0.7998 | | ||
| 237 | +| 166 | L/L/N/U | 108279.69 | 85809.28 | 0.7925 | | ||
| 238 | +| 167 | L/L/T/N | 116851.12 | 85672.64 | 0.7332 | | ||
| 239 | +| 168 | L/L/T/U | 116539.83 | 84589.66 | 0.7258 | | ||
| 240 | +| 169 | R/U/N/N | 83776.91 | 55261.25 | 0.6596 | | ||
| 241 | +| 170 | R/U/N/U | 83865.24 | 55712.99 | 0.6643 | | ||
| 242 | +| 171 | R/U/T/N | 80450.39 | 54912.93 | 0.6826 | | ||
| 243 | +| 172 | R/U/T/U | 80031.18 | 55213.66 | 0.6899 | | ||
| 244 | +| 173 | R/L/N/N | 83469.43 | 54937.92 | 0.6582 | | ||
| 245 | +| 174 | R/L/N/U | 82893.95 | 55848.32 | 0.6737 | | ||
| 246 | +| 175 | R/L/T/N | 80235.48 | 55224.99 | 0.6883 | | ||
| 247 | +| 176 | R/L/T/U | 80503.53 | 55633.92 | 0.6911 | | ||
| 248 | + | ||
| 249 | +## Case 177-192(m=2048, n=3056, batch=10) | ||
| 250 | + | ||
| 251 | +| # | mode | NPU(us) | GPU(us) | GPU/NPU | | ||
| 252 | +|---|------|---------|---------|--------| | ||
| 253 | +| 177 | L/U/N/N | 29891.98 | 32265.89 | 1.0794 | | ||
| 254 | +| 178 | L/U/N/U | 30037.66 | 31689.50 | 1.0550 | | ||
| 255 | +| 179 | L/U/T/N | 32874.24 | 32545.57 | 0.9900 | | ||
| 256 | +| 180 | L/U/T/U | 32515.45 | 32237.60 | 0.9915 | | ||
| 257 | +| 181 | L/L/N/N | 30155.08 | 32572.48 | 1.0802 | | ||
| 258 | +| 182 | L/L/N/U | 30605.03 | 31961.09 | 1.0443 | | ||
| 259 | +| 183 | L/L/T/N | 33065.76 | 32625.28 | 0.9867 | | ||
| 260 | +| 184 | L/L/T/U | 33206.52 | 31882.78 | 0.9601 | | ||
| 261 | +| 185 | R/U/N/N | 40298.14 | 47118.34 | 1.1692 | | ||
| 262 | +| 186 | R/U/N/U | 39908.06 | 47349.31 | 1.1865 | | ||
| 263 | +| 187 | R/U/T/N | 38696.65 | 46164.19 | 1.1930 | | ||
| 264 | +| 188 | R/U/T/U | 39369.29 | 46005.15 | 1.1686 | | ||
| 265 | +| 189 | R/L/N/N | 39527.49 | 46353.95 | 1.1727 | | ||
| 266 | +| 190 | R/L/N/U | 40951.90 | 46460.64 | 1.1345 | | ||
| 267 | +| 191 | R/L/T/N | 38748.84 | 46901.60 | 1.2104 | | ||
| 268 | +| 192 | R/L/T/U | 39428.35 | 47032.19 | 1.1929 | | ||
| 269 | + | ||
| 270 | +## Case 193-208(m=3488, n=3984, batch=9) | ||
| 271 | + | ||
| 272 | +| # | mode | NPU(us) | GPU(us) | GPU/NPU | | ||
| 273 | +|---|------|---------|---------|--------| | ||
| 274 | +| 193 | L/U/N/N | 93007.46 | 102527.39 | 1.1024 | | ||
| 275 | +| 194 | L/U/N/U | 92805.36 | 102334.84 | 1.1027 | | ||
| 276 | +| 195 | L/U/T/N | 99214.47 | 104808.80 | 1.0564 | | ||
| 277 | +| 196 | L/U/T/U | 97832.26 | 104526.69 | 1.0684 | | ||
| 278 | +| 197 | L/L/N/N | 92915.52 | 104968.73 | 1.1297 | | ||
| 279 | +| 198 | L/L/N/U | 93123.27 | 104753.92 | 1.1249 | | ||
| 280 | +| 199 | L/L/T/N | 98907.30 | 103577.12 | 1.0472 | | ||
| 281 | +| 200 | L/L/T/U | 97859.53 | 104086.05 | 1.0636 | | ||
| 282 | +| 201 | R/U/N/N | 116736.07 | 120291.20 | 1.0305 | | ||
| 283 | +| 202 | R/U/N/U | 116631.91 | 122157.89 | 1.0474 | | ||
| 284 | +| 203 | R/U/T/N | 109762.22 | 116856.28 | 1.0646 | | ||
| 285 | +| 204 | R/U/T/U | 109452.91 | 118841.98 | 1.0858 | | ||
| 286 | +| 205 | R/L/N/N | 117081.55 | 117833.80 | 1.0064 | | ||
| 287 | +| 206 | R/L/N/U | 118062.12 | 119511.97 | 1.0123 | | ||
| 288 | +| 207 | R/L/T/N | 110903.90 | 120376.45 | 1.0854 | | ||
| 289 | +| 208 | R/L/T/U | 110267.28 | 121777.77 | 1.1044 | | ||
| 290 | + | ||
| 291 | +## Case 209-224(m=1667, n=1941, batch=38) | ||
| 292 | + | ||
| 293 | +| # | mode | NPU(us) | GPU(us) | GPU/NPU | | ||
| 294 | +|---|------|---------|---------|--------| | ||
| 295 | +| 209 | L/U/N/N | 79000.72 | 53272.04 | 0.6743 | | ||
| 296 | +| 210 | L/U/N/U | 78737.73 | 53484.42 | 0.6793 | | ||
| 297 | +| 211 | L/U/T/N | 79340.84 | 56210.95 | 0.7085 | | ||
| 298 | +| 212 | L/U/T/U | 79296.59 | 56814.66 | 0.7165 | | ||
| 299 | +| 213 | L/L/N/N | 79233.56 | 56410.79 | 0.7120 | | ||
| 300 | +| 214 | L/L/N/U | 78596.79 | 56884.64 | 0.7238 | | ||
| 301 | +| 215 | L/L/T/N | 79604.02 | 53830.72 | 0.6762 | | ||
| 302 | +| 216 | L/L/T/U | 79325.41 | 54005.79 | 0.6808 | | ||
| 303 | +| 217 | R/U/N/N | 88158.83 | 64610.88 | 0.7329 | | ||
| 304 | +| 218 | R/U/N/U | 87163.38 | 65375.65 | 0.7500 | | ||
| 305 | +| 219 | R/U/T/N | 87104.15 | 61704.00 | 0.7084 | | ||
| 306 | +| 220 | R/U/T/U | 86926.27 | 62640.89 | 0.7206 | | ||
| 307 | +| 221 | R/L/N/N | 87710.23 | 62579.90 | 0.7135 | | ||
| 308 | +| 222 | R/L/N/U | 87472.35 | 63028.45 | 0.7206 | | ||
| 309 | +| 223 | R/L/T/N | 86978.04 | 63981.18 | 0.7356 | | ||
| 310 | +| 224 | R/L/T/U | 86819.44 | 65156.29 | 0.7505 | | ||
| 311 | + | ||
| 312 | +## Case 225-240(m=3516, n=1213, batch=16) | ||
| 313 | + | ||
| 314 | +| # | mode | NPU(us) | GPU(us) | GPU/NPU | | ||
| 315 | +|---|------|---------|---------|--------| | ||
| 316 | +| 225 | L/U/N/N | 62293.62 | 56914.18 | 0.9136 | | ||
| 317 | +| 226 | L/U/N/U | 62002.94 | 56911.55 | 0.9179 | | ||
| 318 | +| 227 | L/U/T/N | 63726.60 | 57184.26 | 0.8973 | | ||
| 319 | +| 228 | L/U/T/U | 63304.05 | 57743.90 | 0.9122 | | ||
| 320 | +| 229 | L/L/N/N | 62338.63 | 56918.59 | 0.9131 | | ||
| 321 | +| 230 | L/L/N/U | 61966.52 | 56856.70 | 0.9175 | | ||
| 322 | +| 231 | L/L/T/N | 63607.03 | 58438.56 | 0.9187 | | ||
| 323 | +| 232 | L/L/T/U | 63238.64 | 58054.75 | 0.9180 | | ||
| 324 | +| 233 | R/U/N/N | 38153.45 | 23256.61 | 0.6096 | | ||
| 325 | +| 234 | R/U/N/U | 37913.22 | 23204.54 | 0.6120 | | ||
| 326 | +| 235 | R/U/T/N | 37835.94 | 22865.31 | 0.6043 | | ||
| 327 | +| 236 | R/U/T/U | 37593.61 | 23085.50 | 0.6141 | | ||
| 328 | +| 237 | R/L/N/N | 38182.57 | 22929.92 | 0.6005 | | ||
| 329 | +| 238 | R/L/N/U | 37845.76 | 23164.13 | 0.6121 | | ||
| 330 | +| 239 | R/L/T/N | 38033.00 | 22955.01 | 0.6036 | | ||
| 331 | +| 240 | R/L/T/U | 37780.66 | 23150.85 | 0.6128 | | ||
| 332 | + | ||
| 333 | +## Case 241-256(m=4848, n=5456, batch=4) | ||
| 334 | + | ||
| 335 | +| # | mode | NPU(us) | GPU(us) | GPU/NPU | | ||
| 336 | +|---|------|---------|---------|--------| | ||
| 337 | +| 241 | L/U/N/N | 83442.57 | 118500.10 | 1.4201 | | ||
| 338 | +| 242 | L/U/N/U | 83031.56 | 118494.50 | 1.4271 | | ||
| 339 | +| 243 | L/U/T/N | 94877.18 | 120393.02 | 1.2689 | | ||
| 340 | +| 244 | L/U/T/U | 93521.21 | 121084.89 | 1.2947 | | ||
| 341 | +| 245 | L/L/N/N | 83689.22 | 120566.66 | 1.4406 | | ||
| 342 | +| 246 | L/L/N/U | 82815.76 | 121182.56 | 1.4633 | | ||
| 343 | +| 247 | L/L/T/N | 94624.47 | 119625.53 | 1.2642 | | ||
| 344 | +| 248 | L/L/T/U | 94035.18 | 120280.86 | 1.2791 | | ||
| 345 | +| 249 | R/U/N/N | 125892.02 | 135500.12 | 1.0763 | | ||
| 346 | +| 250 | R/U/N/U | 123677.90 | 138115.73 | 1.1167 | | ||
| 347 | +| 251 | R/U/T/N | 111958.86 | 132898.78 | 1.1870 | | ||
| 348 | +| 252 | R/U/T/U | 111020.67 | 135684.19 | 1.2222 | | ||
| 349 | +| 253 | R/L/N/N | 123240.63 | 134287.00 | 1.0896 | | ||
| 350 | +| 254 | R/L/N/U | 121098.24 | 136519.11 | 1.1273 | | ||
| 351 | +| 255 | R/L/T/N | 112001.80 | 135868.95 | 1.2131 | | ||
| 352 | +| 256 | R/L/T/U | 111814.04 | 138065.50 | 1.2348 | | ||
| 353 | + | ||
| 354 | +## Case 257-272(m=4512, n=4416, batch=6) | ||
| 355 | + | ||
| 356 | +| # | mode | NPU(us) | GPU(us) | GPU/NPU | | ||
| 357 | +|---|------|---------|---------|--------| | ||
| 358 | +| 257 | L/U/N/N | 73219.48 | 125041.05 | 1.7078 | | ||
| 359 | +| 258 | L/U/N/U | 71267.91 | 126066.66 | 1.7689 | | ||
| 360 | +| 259 | L/U/T/N | 82676.27 | 127903.39 | 1.5470 | | ||
| 361 | +| 260 | L/U/T/U | 80556.41 | 129417.86 | 1.6065 | | ||
| 362 | +| 261 | L/L/N/N | 75692.72 | 127579.77 | 1.6855 | | ||
| 363 | +| 262 | L/L/N/U | 72496.25 | 128757.02 | 1.7761 | | ||
| 364 | +| 263 | L/L/T/N | 81572.05 | 125818.27 | 1.5424 | | ||
| 365 | +| 264 | L/L/T/U | 80581.05 | 127075.94 | 1.5770 | | ||
| 366 | +| 265 | R/U/N/N | 97407.85 | 126647.13 | 1.3002 | | ||
| 367 | +| 266 | R/U/N/U | 95839.46 | 129172.93 | 1.3478 | | ||
| 368 | +| 267 | R/U/T/N | 89266.02 | 125424.12 | 1.4051 | | ||
| 369 | +| 268 | R/U/T/U | 88244.97 | 127995.01 | 1.4505 | | ||
| 370 | +| 269 | R/L/N/N | 96906.80 | 126038.56 | 1.3006 | | ||
| 371 | +| 270 | R/L/N/U | 97011.48 | 128781.16 | 1.3275 | | ||
| 372 | +| 271 | R/L/T/N | 89448.11 | 125690.37 | 1.4052 | | ||
| 373 | +| 272 | R/L/T/U | 87919.59 | 128672.77 | 1.4635 | | ||
| 374 | + | ||
| 375 | +## Case 273-288(m=5266, n=5889, batch=4) | ||
| 376 | + | ||
| 377 | +| # | mode | NPU(us) | GPU(us) | GPU/NPU | | ||
| 378 | +|---|------|---------|---------|--------| | ||
| 379 | +| 273 | L/U/N/N | 153232.61 | 152843.03 | 0.9975 | | ||
| 380 | +| 274 | L/U/N/U | 152707.30 | 154440.73 | 1.0114 | | ||
| 381 | +| 275 | L/U/T/N | 159815.80 | 156797.83 | 0.9811 | | ||
| 382 | +| 276 | L/U/T/U | 158290.69 | 159061.45 | 1.0049 | | ||
| 383 | +| 277 | L/L/N/N | 154259.88 | 156095.94 | 1.0119 | | ||
| 384 | +| 278 | L/L/N/U | 153038.80 | 157649.39 | 1.0301 | | ||
| 385 | +| 279 | L/L/T/N | 158804.88 | 155538.84 | 0.9794 | | ||
| 386 | +| 280 | L/L/T/U | 157511.81 | 157420.17 | 0.9994 | | ||
| 387 | +| 281 | R/U/N/N | 188856.52 | 178707.81 | 0.9463 | | ||
| 388 | +| 282 | R/U/N/U | 179054.98 | 182535.81 | 1.0194 | | ||
| 389 | +| 283 | R/U/T/N | 179061.14 | 174600.80 | 0.9751 | | ||
| 390 | +| 284 | R/U/T/U | 176154.28 | 177594.75 | 1.0082 | | ||
| 391 | +| 285 | R/L/N/N | 185246.12 | 175695.17 | 0.9484 | | ||
| 392 | +| 286 | R/L/N/U | 182008.16 | 179542.17 | 0.9865 | | ||
| 393 | +| 287 | R/L/T/N | 179401.34 | 178823.88 | 0.9968 | | ||
| 394 | +| 288 | R/L/T/U | 177440.86 | 182232.75 | 1.0270 | | ||
| 395 | + | ||
| 396 | +## Case 289-304(m=5133, n=5564, batch=4) | ||
| 397 | + | ||
| 398 | +| # | mode | NPU(us) | GPU(us) | GPU/NPU | | ||
| 399 | +|---|------|---------|---------|--------| | ||
| 400 | +| 289 | L/U/N/N | 99430.16 | 138911.86 | 1.3971 | | ||
| 401 | +| 290 | L/U/N/U | 99111.10 | 140006.05 | 1.4126 | | ||
| 402 | +| 291 | L/U/T/N | 104059.66 | 141711.58 | 1.3618 | | ||
| 403 | +| 292 | L/U/T/U | 103931.62 | 143658.11 | 1.3822 | | ||
| 404 | +| 293 | L/L/N/N | 99614.95 | 141402.88 | 1.4195 | | ||
| 405 | +| 294 | L/L/N/U | 99115.46 | 142816.95 | 1.4409 | | ||
| 406 | +| 295 | L/L/T/N | 104259.80 | 141330.42 | 1.3556 | | ||
| 407 | +| 296 | L/L/T/U | 104770.75 | 142665.55 | 1.3617 | | ||
| 408 | +| 297 | R/U/N/N | 133338.41 | 151550.28 | 1.1366 | | ||
| 409 | +| 298 | R/U/N/U | 131676.81 | 155652.09 | 1.1821 | | ||
| 410 | +| 299 | R/U/T/N | 128973.58 | 150478.97 | 1.1667 | | ||
| 411 | +| 300 | R/U/T/U | 126657.95 | 154308.95 | 1.2183 | | ||
| 412 | +| 301 | R/L/N/N | 131687.80 | 155072.42 | 1.1776 | | ||
| 413 | +| 302 | R/L/N/U | 132118.81 | 158661.28 | 1.2009 | | ||
| 414 | +| 303 | R/L/T/N | 129066.41 | 156274.28 | 1.2108 | | ||
| 415 | +| 304 | R/L/T/U | 127261.64 | 157852.00 | 1.2404 | | ||
| 416 | + | ||
| 417 | +## Case 305-320(m=6182, n=6412, batch=3) | ||
| 418 | + | ||
| 419 | +| # | mode | NPU(us) | GPU(us) | GPU/NPU | | ||
| 420 | +|---|------|---------|---------|--------| | ||
| 421 | +| 305 | L/U/N/N | 158133.31 | 180365.95 | 1.1406 | | ||
| 422 | +| 306 | L/U/N/U | 156182.28 | 185667.42 | 1.1888 | | ||
| 423 | +| 307 | L/U/T/N | 165453.86 | 185798.17 | 1.1230 | | ||
| 424 | +| 308 | L/U/T/U | 162821.73 | 193007.11 | 1.1854 | | ||
| 425 | +| 309 | L/L/N/N | 157943.94 | 185935.45 | 1.1772 | | ||
| 426 | +| 310 | L/L/N/U | 155997.34 | 190123.81 | 1.2188 | | ||
| 427 | +| 311 | L/L/T/N | 165274.48 | 192106.59 | 1.1623 | | ||
| 428 | +| 312 | L/L/T/U | 161949.34 | 189200.45 | 1.1683 | | ||
| 429 | +| 313 | R/U/N/N | 181439.33 | 201003.58 | 1.1078 | | ||
| 430 | +| 314 | R/U/N/U | 176329.42 | 214975.00 | 1.2192 | | ||
| 431 | +| 315 | R/U/T/N | 172595.03 | 198764.48 | 1.1516 | | ||
| 432 | +| 316 | R/U/T/U | 167758.52 | 204046.08 | 1.2163 | | ||
| 433 | +| 317 | R/L/N/N | 180619.98 | 201021.09 | 1.1130 | | ||
| 434 | +| 318 | R/L/N/U | 176612.11 | 207048.50 | 1.1723 | | ||
| 435 | +| 319 | R/L/T/N | 174678.91 | 202174.27 | 1.1574 | | ||
| 436 | +| 320 | R/L/T/U | 167844.05 | 209951.39 | 1.2509 | | ||
| 437 | + | ||
| @@ -0,0 +1,324 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + do { \ | ||
| 26 | + if (!(cond)) { \ | ||
| 27 | + return_expr; \ | ||
| 28 | + } \ | ||
| 29 | + } while (0) | ||
| 30 | + | ||
| 31 | +constexpr int32_t MIX_NB_SMALL = 16; | ||
| 32 | +constexpr int32_t MIX_NB_LARGE = 32; | ||
| 33 | + | ||
| 34 | + | ||
| 35 | +static const char* GetSocVersion() | ||
| 36 | +{ | ||
| 37 | + return aclrtGetSocName(); | ||
| 38 | +} | ||
| 39 | + | ||
| 40 | + | ||
| 41 | +static void GenerateCubeTiling(int32_t maxMN, uint8_t* tilingBuf, uint32_t* tilingSize) | ||
| 42 | +{ | ||
| 43 | + auto ascendcPlatform = platform_ascendc::PlatformAscendCManager::GetInstance(GetSocVersion()); | ||
| 44 | + matmul_tiling::MultiCoreMatmulTiling tilingApi(*ascendcPlatform); | ||
| 45 | + tilingApi.SetDim(1); | ||
| 46 | + tilingApi.SetAType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, | ||
| 47 | + matmul_tiling::DataType::DT_FLOAT, false); | ||
| 48 | + tilingApi.SetBType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, | ||
| 49 | + matmul_tiling::DataType::DT_FLOAT, false); | ||
| 50 | + tilingApi.SetCType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, | ||
| 51 | + matmul_tiling::DataType::DT_FLOAT); | ||
| 52 | + tilingApi.SetOrgShape(maxMN, maxMN, maxMN); | ||
| 53 | + tilingApi.SetShape(maxMN, maxMN, maxMN); | ||
| 54 | + tilingApi.SetBias(false); | ||
| 55 | + tilingApi.SetBufferSpace(-1, -1, -1); | ||
| 56 | + optiling::TCubeTiling cubeTiling; | ||
| 57 | + if (tilingApi.GetTiling(cubeTiling) == -1) { | ||
| 58 | + *tilingSize = 0; | ||
| 59 | + return; | ||
| 60 | + } | ||
| 61 | + *tilingSize = cubeTiling.GetDataSize(); | ||
| 62 | + cubeTiling.SaveToBuffer(tilingBuf, *tilingSize); | ||
| 63 | +} | ||
| 64 | + | ||
| 65 | +static bool IsValidSide(aclblasSideMode_t s) { return s == ACLBLAS_SIDE_LEFT || s == ACLBLAS_SIDE_RIGHT; } | ||
| 66 | +static bool IsValidUplo(aclblasFillMode_t u) { return u == ACLBLAS_UPPER || u == ACLBLAS_LOWER; } | ||
| 67 | +static bool IsValidTrans(aclblasOperation_t t) { return t == ACLBLAS_OP_N || t == ACLBLAS_OP_T || t == ACLBLAS_OP_C; } | ||
| 68 | +static bool IsValidDiag(aclblasDiagType_t d) { return d == ACLBLAS_NON_UNIT || d == ACLBLAS_UNIT; } | ||
| 69 | + | ||
| 70 | +// 计算基本 tiling 参数(side/uplo/transa/diag 映射、useOrigA、nb 等) | ||
| 71 | +static void FillCtrsmTilingBasicParams(aclblasSideMode_t side, aclblasFillMode_t uplo, | ||
| 72 | + aclblasOperation_t transa, aclblasDiagType_t diag, | ||
| 73 | + int64_t m, int64_t n, int64_t lda, int64_t ldb, int64_t batchCount, | ||
| 74 | + float alphaReal, float alphaImag, | ||
| 75 | + CtrsmBatchedTilingData& td, | ||
| 76 | + int32_t& kDim, int32_t& nCols, int32_t& kDimAligned, int32_t& nColsAligned, | ||
| 77 | + bool& sideRight, bool& useDualAiv) | ||
| 78 | +{ | ||
| 79 | + kDim = (side == ACLBLAS_SIDE_LEFT) ? (int32_t)m : (int32_t)n; | ||
| 80 | + nCols = (side == ACLBLAS_SIDE_LEFT) ? (int32_t)n : (int32_t)m; | ||
| 81 | + kDimAligned = CEIL_ALIGN(kDim, FLOAT_ALIGN); | ||
| 82 | + nColsAligned = CEIL_ALIGN(nCols, FLOAT_ALIGN); | ||
| 83 | + | ||
| 84 | + sideRight = (side == ACLBLAS_SIDE_RIGHT); | ||
| 85 | + bool isTransN = (transa == ACLBLAS_OP_N); | ||
| 86 | + bool isTransT = (transa == ACLBLAS_OP_T); | ||
| 87 | + bool isTransC = (transa == ACLBLAS_OP_C); | ||
| 88 | + bool needTA = ((isTransT || isTransC) && !sideRight) || (isTransN && sideRight); | ||
| 89 | + bool padOn = (kDim != kDimAligned) || (nCols != nColsAligned); | ||
| 90 | + bool conjA = isTransC; | ||
| 91 | + bool useOrigA = (!needTA && !padOn && !conjA); | ||
| 92 | + | ||
| 93 | + td.m = (int32_t)m; | ||
| 94 | + td.n = (int32_t)n; | ||
| 95 | + td.lda = (int32_t)lda; | ||
| 96 | + td.ldb = (int32_t)ldb; | ||
| 97 | + td.batchCount = (int32_t)batchCount; | ||
| 98 | + td.side = sideRight ? SIDE_RIGHT : SIDE_LEFT; | ||
| 99 | + td.uplo = (uplo == ACLBLAS_UPPER) ? UPLO_UPPER : UPLO_LOWER; | ||
| 100 | + td.transa = isTransN ? TRANS_N : (isTransT ? TRANS_T : TRANS_C); | ||
| 101 | + td.diag = (diag == ACLBLAS_NON_UNIT) ? DIAG_NONUNIT : DIAG_UNIT; | ||
| 102 | + td.alphaReal = alphaReal; | ||
| 103 | + td.alphaImag = alphaImag; | ||
| 104 | + td.useOrigA = useOrigA ? 1 : 0; | ||
| 105 | + td.aEffStride = useOrigA ? ((int32_t)lda * 2) : (kDimAligned * 2); | ||
| 106 | + useDualAiv = (kDim >= 128 && nColsAligned >= 128); | ||
| 107 | + td.dualAivMode = useDualAiv ? 1 : 0; | ||
| 108 | + td.nb = (kDim > 1024) ? MIX_NB_LARGE : MIX_NB_SMALL; | ||
| 109 | +} | ||
| 110 | + | ||
| 111 | +// 计算 workspace 大小和 numBlocks | ||
| 112 | +static void ComputeWorkspaceAndBlocks( | ||
| 113 | + CtrsmBatchedTilingData& td, int32_t kDimAligned, int32_t nColsAligned, | ||
| 114 | + int32_t numSplits, int32_t splitNColsAligned, int32_t lastNColsAligned, | ||
| 115 | + bool sideRight, bool useDualAiv, int64_t batchCount, | ||
| 116 | + int32_t& maxMN, uint32_t& numBlocks, int32_t& effectiveBatch) | ||
| 117 | +{ | ||
| 118 | + int32_t wsNCols = (numSplits > 1) ? | ||
| 119 | + ((splitNColsAligned > lastNColsAligned) ? splitNColsAligned : lastNColsAligned) | ||
| 120 | + : nColsAligned; | ||
| 121 | + int64_t aSize = (int64_t)kDimAligned * kDimAligned * 2; | ||
| 122 | + int64_t bSize = (int64_t)kDimAligned * wsNCols * 2; | ||
| 123 | + int64_t xnegSize = (int64_t)2 * 16 * 2 * td.nb * wsNCols * 2; | ||
| 124 | + int64_t rightTempSize = sideRight ? ((int64_t)wsNCols * kDimAligned * 2) : 0; | ||
| 125 | + int64_t gemmAreaSize = xnegSize; | ||
| 126 | + if (rightTempSize > gemmAreaSize) gemmAreaSize = rightTempSize; | ||
| 127 | + int64_t splitBGemmSize = (bSize + gemmAreaSize); | ||
| 128 | + td.splitBGemmSize = splitBGemmSize * sizeof(float); | ||
| 129 | + if (numSplits > 1) { | ||
| 130 | + td.workspaceOffset = (aSize + splitBGemmSize * numSplits) * sizeof(float); | ||
| 131 | + } else { | ||
| 132 | + td.workspaceOffset = (aSize + splitBGemmSize) * sizeof(float); | ||
| 133 | + } | ||
| 134 | + maxMN = (kDimAligned > wsNCols) ? kDimAligned : wsNCols; | ||
| 135 | + int32_t maxK = 2 * kDimAligned; | ||
| 136 | + if (maxK > maxMN) maxMN = maxK; | ||
| 137 | + if (numSplits > 1) { | ||
| 138 | + numBlocks = (uint32_t)((int32_t)batchCount * numSplits); | ||
| 139 | + effectiveBatch = (int32_t)batchCount; | ||
| 140 | + } else if (useDualAiv) { | ||
| 141 | + numBlocks = (uint32_t)batchCount; | ||
| 142 | + effectiveBatch = (int32_t)batchCount; | ||
| 143 | + } else { | ||
| 144 | + effectiveBatch = (int32_t)batchCount; | ||
| 145 | + if (effectiveBatch % 2 != 0) effectiveBatch++; | ||
| 146 | + numBlocks = (uint32_t)(effectiveBatch / 2); | ||
| 147 | + } | ||
| 148 | +} | ||
| 149 | + | ||
| 150 | +// 计算 split/numBlocks/workspace 参数 | ||
| 151 | +static void FillCtrsmTilingSplitAndBlocks( | ||
| 152 | + CtrsmBatchedTilingData& td, int32_t kDim, int32_t nCols, | ||
| 153 | + int32_t kDimAligned, int32_t nColsAligned, bool sideRight, bool useDualAiv, | ||
| 154 | + int64_t batchCount, int32_t& maxMN, uint32_t& numBlocks, int32_t& effectiveBatch) | ||
| 155 | +{ | ||
| 156 | + constexpr int32_t SPLIT_ALIGN = 16; | ||
| 157 | + constexpr int32_t TOTAL_AICORES = 20; | ||
| 158 | + int32_t numSplits = 1; | ||
| 159 | + if (useDualAiv && (int32_t)batchCount <= TOTAL_AICORES / 2) { | ||
| 160 | + int32_t maxSplits = TOTAL_AICORES / (int32_t)batchCount; | ||
| 161 | + int32_t minSplitNCols = (td.nb > 64) ? td.nb : 64; | ||
| 162 | + int32_t maxBySize = nCols / minSplitNCols; | ||
| 163 | + if (maxSplits > maxBySize) maxSplits = maxBySize; | ||
| 164 | + if ((int32_t)batchCount * maxSplits > TOTAL_AICORES) | ||
| 165 | + maxSplits = TOTAL_AICORES / (int32_t)batchCount; | ||
| 166 | + if (maxSplits > 1) numSplits = maxSplits; | ||
| 167 | + } | ||
| 168 | + int32_t splitNCols = nCols; | ||
| 169 | + int32_t splitNColsAligned = nColsAligned; | ||
| 170 | + int32_t lastNCols = nCols; | ||
| 171 | + int32_t lastNColsAligned = nColsAligned; | ||
| 172 | + if (numSplits > 1) { | ||
| 173 | + splitNCols = (nCols / numSplits) & ~(SPLIT_ALIGN - 1); | ||
| 174 | + splitNColsAligned = CEIL_ALIGN(splitNCols, FLOAT_ALIGN); | ||
| 175 | + lastNCols = nCols - splitNCols * (numSplits - 1); | ||
| 176 | + lastNColsAligned = CEIL_ALIGN(lastNCols, FLOAT_ALIGN); | ||
| 177 | + } | ||
| 178 | + td.numSplits = numSplits; | ||
| 179 | + td.splitNCols = splitNCols; | ||
| 180 | + td.splitNColsAligned = splitNColsAligned; | ||
| 181 | + td.lastNCols = lastNCols; | ||
| 182 | + td.lastNColsAligned = lastNColsAligned; | ||
| 183 | + ComputeWorkspaceAndBlocks(td, kDimAligned, nColsAligned, numSplits, | ||
| 184 | + splitNColsAligned, lastNColsAligned, sideRight, useDualAiv, | ||
| 185 | + batchCount, maxMN, numBlocks, effectiveBatch); | ||
| 186 | +} | ||
| 187 | + | ||
| 188 | +// 由 side/uplo/transa/diag 及尺寸推导 tiling 参数,并计算 kernel 启动参数(maxMN/numBlocks/effectiveBatch) | ||
| 189 | +static void FillCtrsmTiling(aclblasSideMode_t side, aclblasFillMode_t uplo, | ||
| 190 | + aclblasOperation_t transa, aclblasDiagType_t diag, | ||
| 191 | + int64_t m, int64_t n, int64_t lda, int64_t ldb, int64_t batchCount, | ||
| 192 | + float alphaReal, float alphaImag, | ||
| 193 | + CtrsmBatchedTilingData& td, int32_t& maxMN, | ||
| 194 | + uint32_t& numBlocks, int32_t& effectiveBatch) | ||
| 195 | +{ | ||
| 196 | + int32_t kDim, nCols, kDimAligned, nColsAligned; | ||
| 197 | + bool sideRight, useDualAiv; | ||
| 198 | + FillCtrsmTilingBasicParams(side, uplo, transa, diag, m, n, lda, ldb, batchCount, | ||
| 199 | + alphaReal, alphaImag, td, kDim, nCols, kDimAligned, nColsAligned, | ||
| 200 | + sideRight, useDualAiv); | ||
| 201 | + FillCtrsmTilingSplitAndBlocks(td, kDim, nCols, kDimAligned, nColsAligned, | ||
| 202 | + sideRight, useDualAiv, batchCount, maxMN, numBlocks, effectiveBatch); | ||
| 203 | +} | ||
| 204 | + | ||
| 205 | +// 分配 device 内存、拷贝入参与 cube tiling、启动 kernel 并同步、释放资源 | ||
| 206 | +static aclblasStatus_t LaunchCtrsmKernel(const CtrsmBatchedTilingData& td, | ||
| 207 | + int32_t maxMN, uint32_t numBlocks, int32_t effectiveBatch, | ||
| 208 | + const std::complex<float>* const aArray[], int64_t lda, | ||
| 209 | + std::complex<float>* const bArray[], int64_t batchCount, aclrtStream stream) | ||
| 210 | +{ | ||
| 211 | + size_t ptrArraySize = (size_t)batchCount * sizeof(void*); | ||
| 212 | + uint8_t *tilingDevice = nullptr, *aArrayDevice = nullptr, *bArrayDevice = nullptr; | ||
| 213 | + uint8_t *cubeTilingDevice = nullptr, *gemmWsDevice = nullptr, *sysWsDevice = nullptr; | ||
| 214 | + | ||
| 215 | + CHECK_RET(aclrtMalloc((void**)&tilingDevice, sizeof(td), ACL_MEM_MALLOC_HUGE_FIRST) == ACL_SUCCESS, | ||
| 216 | + return ACLBLAS_STATUS_INTERNAL_ERROR); | ||
| 217 | + CHECK_RET(aclrtMalloc((void**)&aArrayDevice, ptrArraySize, ACL_MEM_MALLOC_HUGE_FIRST) == ACL_SUCCESS, | ||
| 218 | + return ACLBLAS_STATUS_INTERNAL_ERROR); | ||
| 219 | + CHECK_RET(aclrtMalloc((void**)&bArrayDevice, ptrArraySize, ACL_MEM_MALLOC_HUGE_FIRST) == ACL_SUCCESS, | ||
| 220 | + return ACLBLAS_STATUS_INTERNAL_ERROR); | ||
| 221 | + aclrtMemcpy(tilingDevice, sizeof(td), &td, sizeof(td), ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 222 | + aclrtMemcpy(aArrayDevice, ptrArraySize, aArray, ptrArraySize, ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 223 | + aclrtMemcpy(bArrayDevice, ptrArraySize, bArray, ptrArraySize, ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 224 | + | ||
| 225 | + uint8_t cubeTilingBuf[2048]; | ||
| 226 | + uint32_t cubeTilingSize = 0; | ||
| 227 | + GenerateCubeTiling(maxMN, cubeTilingBuf, &cubeTilingSize); | ||
| 228 | + CHECK_RET(aclrtMalloc((void**)&cubeTilingDevice, sizeof(cubeTilingBuf), ACL_MEM_MALLOC_HUGE_FIRST) == ACL_SUCCESS, | ||
| 229 | + return ACLBLAS_STATUS_INTERNAL_ERROR); | ||
| 230 | + aclrtMemcpy(cubeTilingDevice, sizeof(cubeTilingBuf), cubeTilingBuf, sizeof(cubeTilingBuf), ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 231 | + | ||
| 232 | + size_t gemmWsSize = (size_t)effectiveBatch * td.workspaceOffset; | ||
| 233 | + CHECK_RET(aclrtMalloc((void**)&gemmWsDevice, gemmWsSize, ACL_MEM_MALLOC_HUGE_FIRST) == ACL_SUCCESS, | ||
| 234 | + return ACLBLAS_STATUS_INTERNAL_ERROR); | ||
| 235 | + aclrtMemset(gemmWsDevice, gemmWsSize, 0, gemmWsSize); | ||
| 236 | + | ||
| 237 | + auto platformInst = platform_ascendc::PlatformAscendCManager::GetInstance(GetSocVersion()); | ||
| 238 | + size_t sysWsSize = static_cast<size_t>(platformInst->GetLibApiWorkSpaceSize()); | ||
| 239 | + if (sysWsSize < 16 * 1024 * 1024) sysWsSize = 16 * 1024 * 1024; | ||
| 240 | + CHECK_RET(aclrtMalloc((void**)&sysWsDevice, sysWsSize, ACL_MEM_MALLOC_HUGE_FIRST) == ACL_SUCCESS, | ||
| 241 | + return ACLBLAS_STATUS_INTERNAL_ERROR); | ||
| 242 | + | ||
| 243 | + ctrsm_batched_mix12_kernel_do(aArrayDevice, bArrayDevice, tilingDevice, cubeTilingDevice, | ||
| 244 | + gemmWsDevice, sysWsDevice, numBlocks, stream); | ||
| 245 | + aclError syncRet = aclrtSynchronizeStream(stream); | ||
| 246 | + | ||
| 247 | + aclrtFree(sysWsDevice); | ||
| 248 | + aclrtFree(gemmWsDevice); | ||
| 249 | + aclrtFree(cubeTilingDevice); | ||
| 250 | + aclrtFree(bArrayDevice); | ||
| 251 | + aclrtFree(aArrayDevice); | ||
| 252 | + aclrtFree(tilingDevice); | ||
| 253 | + CHECK_RET(syncRet == ACL_SUCCESS, return ACLBLAS_STATUS_INTERNAL_ERROR); | ||
| 254 | + return ACLBLAS_STATUS_SUCCESS; | ||
| 255 | +} | ||
| 256 | + | ||
| 257 | +// 参数合法性校验:句柄、枚举、维度、lda/ldb。返回 SUCCESS 表示校验通过可继续 | ||
| 258 | +static aclblasStatus_t ValidateCtrsmArgs(aclblasHandle_t handle, | ||
| 259 | + aclblasSideMode_t side, aclblasFillMode_t uplo, aclblasOperation_t transa, aclblasDiagType_t diag, | ||
| 260 | + int64_t m, int64_t n, const std::complex<float>* alpha, | ||
| 261 | + const std::complex<float>* const aArray[], int64_t lda, | ||
| 262 | + std::complex<float>* const bArray[], int64_t ldb, int64_t batchCount) | ||
| 263 | +{ | ||
| 264 | + if (handle == nullptr) { | ||
| 265 | + return ACLBLAS_STATUS_HANDLE_IS_NULLPTR; | ||
| 266 | + } | ||
| 267 | + if (!IsValidSide(side) || !IsValidUplo(uplo) || !IsValidTrans(transa) || !IsValidDiag(diag)) { | ||
| 268 | + return ACLBLAS_STATUS_INVALID_VALUE; | ||
| 269 | + } | ||
| 270 | + if (m < 0 || n < 0 || batchCount < 0 || alpha == nullptr || aArray == nullptr || bArray == nullptr) { | ||
| 271 | + return ACLBLAS_STATUS_INVALID_VALUE; | ||
| 272 | + } | ||
| 273 | + int64_t minLda = (side == ACLBLAS_SIDE_LEFT) ? std::max((int64_t)1, m) : std::max((int64_t)1, n); | ||
| 274 | + if (lda < minLda || ldb < std::max((int64_t)1, n)) { | ||
| 275 | + return ACLBLAS_STATUS_INVALID_VALUE; | ||
| 276 | + } | ||
| 277 | + return ACLBLAS_STATUS_SUCCESS; | ||
| 278 | +} | ||
| 279 | + | ||
| 280 | +aclblasStatus_t aclblasCtrsmBatched( | ||
| 281 | + aclblasHandle_t handle, | ||
| 282 | + aclblasSideMode_t side, | ||
| 283 | + aclblasFillMode_t uplo, | ||
| 284 | + aclblasOperation_t transa, | ||
| 285 | + aclblasDiagType_t diag, | ||
| 286 | + int64_t m, int64_t n, | ||
| 287 | + const std::complex<float>* alpha, | ||
| 288 | + const std::complex<float>* const aArray[], int64_t lda, | ||
| 289 | + std::complex<float>* const bArray[], int64_t ldb, | ||
| 290 | + int64_t batchCount) | ||
| 291 | +{ | ||
| 292 | + aclblasStatus_t vst = ValidateCtrsmArgs(handle, side, uplo, transa, diag, | ||
| 293 | + m, n, alpha, aArray, lda, bArray, ldb, batchCount); | ||
| 294 | + if (vst != ACLBLAS_STATUS_SUCCESS) { | ||
| 295 | + return vst; | ||
| 296 | + } | ||
| 297 | + if (m == 0 || n == 0 || batchCount == 0) { | ||
| 298 | + return ACLBLAS_STATUS_SUCCESS; | ||
| 299 | + } | ||
| 300 | + | ||
| 301 | + float alphaReal = alpha->real(); | ||
| 302 | + float alphaImag = alpha->imag(); | ||
| 303 | + if (alphaReal == 0.0f && alphaImag == 0.0f) { | ||
| 304 | + for (int64_t i = 0; i < batchCount; i++) { | ||
| 305 | + size_t bytes = (size_t)m * ldb * 2 * sizeof(float); | ||
| 306 | + CHECK_RET(aclrtMemset(bArray[i], bytes, 0, bytes) == ACL_SUCCESS, | ||
| 307 | + return ACLBLAS_STATUS_INTERNAL_ERROR); | ||
| 308 | + } | ||
| 309 | + return ACLBLAS_STATUS_SUCCESS; | ||
| 310 | + } | ||
| 311 | + | ||
| 312 | + auto* h = reinterpret_cast<_aclblas_handle*>(handle); | ||
| 313 | + aclrtStream stream = h->stream; | ||
| 314 | + | ||
| 315 | + CtrsmBatchedTilingData td; | ||
| 316 | + int32_t maxMN; | ||
| 317 | + uint32_t numBlocks; | ||
| 318 | + int32_t effectiveBatch; | ||
| 319 | + FillCtrsmTiling(side, uplo, transa, diag, m, n, lda, ldb, batchCount, | ||
| 320 | + alphaReal, alphaImag, td, maxMN, numBlocks, effectiveBatch); | ||
| 321 | + | ||
| 322 | + return LaunchCtrsmKernel(td, maxMN, numBlocks, effectiveBatch, | ||
| 323 | + aArray, lda, bArray, batchCount, stream); | ||
| 324 | +} | ||
| @@ -0,0 +1,18 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | +void ctrsm_batched_mix12_kernel_do( | ||
| 16 | + uint8_t* aArrayGm, uint8_t* bArrayGm, uint8_t* trsmTilingGm, | ||
| 17 | + uint8_t* cubeTilingGm, uint8_t* gemmWsGm, uint8_t* sysWorkspace, | ||
| 18 | + uint32_t numBlocks, void* stream); | ||
| @@ -0,0 +1,69 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | +extern "C" __global__ __aicore__ void ctrsm_batched_mix12_kernel( | ||
| 19 | + GM_ADDR aArrayGm, GM_ADDR bArrayGm, GM_ADDR trsmTilingGm, | ||
| 20 | + GM_ADDR cubeTilingGm, GM_ADDR gemmWsGm, GM_ADDR sysWorkspace) | ||
| 21 | +{ | ||
| 22 | + KERNEL_TASK_TYPE_DEFAULT(KERNEL_TYPE_MIX_AIC_1_2); | ||
| 23 | + AscendC::TPipe pipe; | ||
| 24 | + auto trsmTiling = (__gm__ CtrsmBatchedTilingData*)trsmTilingGm; | ||
| 25 | + TCubeTiling cubeTiling; | ||
| 26 | + CopyCubeTiling(&cubeTiling, cubeTilingGm); | ||
| 27 | + if ASCEND_IS_AIC { | ||
| 28 | + CtrsmMixAic aic; | ||
| 29 | + aic.Init(aArrayGm, bArrayGm, gemmWsGm, trsmTiling, cubeTiling); | ||
| 30 | + REGIST_MATMUL_OBJ(&pipe, GetSysWorkSpacePtr(), aic.mm, &aic.cubeTiling); | ||
| 31 | + aic.Process12(); | ||
| 32 | + aic.mm.End(); | ||
| 33 | + } | ||
| 34 | + if ASCEND_IS_AIV { | ||
| 35 | + // 按 side/uplo/transa 计算计算路径,分派到对应的模板路径类型 | ||
| 36 | + bool right = (trsmTiling->side == SIDE_RIGHT); | ||
| 37 | + bool needTA = NeedTransA(trsmTiling); | ||
| 38 | + int32_t effUplo = needTA ? (trsmTiling->uplo == UPLO_UPPER ? UPLO_LOWER : UPLO_UPPER) | ||
| 39 | + : trsmTiling->uplo; | ||
| 40 | + bool forward = (effUplo == UPLO_LOWER); | ||
| 41 | + if (forward && !right) { | ||
| 42 | + CtrsmLowerLeft aiv; | ||
| 43 | + aiv.Init(aArrayGm, bArrayGm, gemmWsGm, trsmTiling, &pipe); | ||
| 44 | + aiv.Process12(); | ||
| 45 | + } else if (forward && right) { | ||
| 46 | + CtrsmLowerRight aiv; | ||
| 47 | + aiv.Init(aArrayGm, bArrayGm, gemmWsGm, trsmTiling, &pipe); | ||
| 48 | + aiv.Process12(); | ||
| 49 | + } else if (!forward && !right) { | ||
| 50 | + CtrsmUpperLeft aiv; | ||
| 51 | + aiv.Init(aArrayGm, bArrayGm, gemmWsGm, trsmTiling, &pipe); | ||
| 52 | + aiv.Process12(); | ||
| 53 | + } else { | ||
| 54 | + CtrsmUpperRight aiv; | ||
| 55 | + aiv.Init(aArrayGm, bArrayGm, gemmWsGm, trsmTiling, &pipe); | ||
| 56 | + aiv.Process12(); | ||
| 57 | + } | ||
| 58 | + } | ||
| 59 | +} | ||
| 60 | + | ||
| 61 | +void ctrsm_batched_mix12_kernel_do(GM_ADDR aArrayGm, GM_ADDR bArrayGm, GM_ADDR trsmTilingGm, | ||
| 62 | + GM_ADDR cubeTilingGm, GM_ADDR gemmWsGm, GM_ADDR sysWorkspace, | ||
| 63 | + uint32_t numBlocks, void* stream) | ||
| 64 | +{ | ||
| 65 | + ctrsm_batched_mix12_kernel<<<numBlocks, nullptr, stream>>>( | ||
| 66 | + aArrayGm, bArrayGm, trsmTilingGm, cubeTilingGm, gemmWsGm, sysWorkspace); | ||
| 67 | +} | ||
| 68 | + | ||
| 69 | + | ||
| @@ -0,0 +1,418 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | +typedef MatmulType<AscendC::TPosition::GM, CubeFormat::ND, float> MmA; | ||
| 16 | +typedef MatmulType<AscendC::TPosition::GM, CubeFormat::ND, float> MmB; | ||
| 17 | +typedef MatmulType<AscendC::TPosition::GM, CubeFormat::ND, float> MmC; | ||
| 18 | + | ||
| 19 | +class CtrsmMixAic { | ||
| 20 | +public: | ||
| 21 | + Matmul<MmA, MmB, MmC> mm; | ||
| 22 | + TCubeTiling cubeTiling; | ||
| 23 | + | ||
| 24 | + __aicore__ inline CtrsmMixAic() {} | ||
| 25 | + | ||
| 26 | + __aicore__ inline void Init(GM_ADDR aArrayGm, GM_ADDR bArrayGm, GM_ADDR gemmWsGm, | ||
| 27 | + const __gm__ CtrsmBatchedTilingData* t, const TCubeTiling& ct) | ||
| 28 | + { | ||
| 29 | + td = t; | ||
| 30 | + cubeTiling = ct; | ||
| 31 | + blockIdx = AscendC::GetBlockIdx(); | ||
| 32 | + right = (td->side == SIDE_RIGHT); | ||
| 33 | + kDim = right ? td->n : td->m; | ||
| 34 | + nCols = right ? td->m : td->n; | ||
| 35 | + nb = td->nb; | ||
| 36 | + int32_t kDimPad = CEIL_ALIGN(kDim, FLOAT_ALIGN); | ||
| 37 | + int32_t nColsPad = CEIL_ALIGN(nCols, FLOAT_ALIGN); | ||
| 38 | + if (kDim != kDimPad || nCols != nColsPad) { kDim = kDimPad; nCols = nColsPad; } | ||
| 39 | + nColsAligned = CEIL_ALIGN(nCols, FLOAT_ALIGN); | ||
| 40 | + numSplits = td->numSplits; | ||
| 41 | + if (numSplits > 1) { | ||
| 42 | + int32_t splitIdx = (int32_t)blockIdx % numSplits; | ||
| 43 | + bool isLast = (splitIdx == numSplits - 1); | ||
| 44 | + int32_t localNColsAligned = isLast ? td->lastNColsAligned : td->splitNColsAligned; | ||
| 45 | + nCols = localNColsAligned; | ||
| 46 | + nColsAligned = localNColsAligned; | ||
| 47 | + } | ||
| 48 | + bool needTA = NeedTransA(td); | ||
| 49 | + int32_t effUplo = needTA ? (td->uplo == UPLO_UPPER ? UPLO_LOWER : UPLO_UPPER) | ||
| 50 | + : td->uplo; | ||
| 51 | + forward = (effUplo == UPLO_LOWER); | ||
| 52 | + gmAArray.SetGlobalBuffer((__gm__ uint64_t*)aArrayGm, td->batchCount); | ||
| 53 | + gmBArray.SetGlobalBuffer((__gm__ uint64_t*)bArrayGm, td->batchCount); | ||
| 54 | + gemmWsBase = gemmWsGm; | ||
| 55 | + useOrigA = (td->useOrigA == 1); | ||
| 56 | + aEffStride = td->aEffStride; | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + __aicore__ inline void Process12() | ||
| 60 | + { | ||
| 61 | + int32_t numPanels = (kDim + nb - 1) / nb; | ||
| 62 | + if (numSplits > 1) { | ||
| 63 | + int32_t slot = (int32_t)blockIdx; | ||
| 64 | + if (numPanels <= 2) { | ||
| 65 | + Process12Simple(slot, -1, numPanels); | ||
| 66 | + } else { | ||
| 67 | + Process12Grouped(slot, -1, numPanels); | ||
| 68 | + } | ||
| 69 | + } else if (td->dualAivMode) { | ||
| 70 | + int32_t batch = (int32_t)blockIdx; | ||
| 71 | + if (numPanels <= 2) { | ||
| 72 | + Process12Simple(batch, -1, numPanels); | ||
| 73 | + } else { | ||
| 74 | + Process12Grouped(batch, -1, numPanels); | ||
| 75 | + } | ||
| 76 | + } else { | ||
| 77 | + int32_t g = (int32_t)blockIdx; | ||
| 78 | + int32_t b0 = 2 * g, b1 = 2 * g + 1; | ||
| 79 | + if (numPanels <= 2) { | ||
| 80 | + Process12Simple(b0, b1, numPanels); | ||
| 81 | + } else { | ||
| 82 | + Process12Grouped(b0, b1, numPanels); | ||
| 83 | + } | ||
| 84 | + } | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | +private: | ||
| 88 | + __aicore__ inline void Ptrs(int32_t slot, __gm__ float*& eA, int32_t& eAStride, | ||
| 89 | + __gm__ float*& eBR, __gm__ float*& eBI, | ||
| 90 | + int32_t& eLdb, __gm__ float*& gmGemm) | ||
| 91 | + { | ||
| 92 | + int32_t batch = (numSplits > 1) ? (slot / numSplits) : slot; | ||
| 93 | + int32_t splitIdx = (numSplits > 1) ? (slot % numSplits) : 0; | ||
| 94 | + __gm__ float* batchWs = (__gm__ float*)gemmWsBase | ||
| 95 | + + (int64_t)batch * (td->workspaceOffset / sizeof(float)); | ||
| 96 | + int64_t aPlane = (int64_t)kDim * kDim; | ||
| 97 | + if (useOrigA) { | ||
| 98 | + eA = (__gm__ float*)gmAArray.GetValue(batch); | ||
| 99 | + eAStride = aEffStride; | ||
| 100 | + } else { | ||
| 101 | + eA = batchWs; | ||
| 102 | + eAStride = 2 * kDim; | ||
| 103 | + } | ||
| 104 | + int32_t wsNCols = (numSplits > 1) ? | ||
| 105 | + ((td->splitNColsAligned > td->lastNColsAligned) ? td->splitNColsAligned : td->lastNColsAligned) | ||
| 106 | + : nColsAligned; | ||
| 107 | + int64_t bPlane = (int64_t)kDim * wsNCols; | ||
| 108 | + int64_t splitBGemmFloats = td->splitBGemmSize / sizeof(float); | ||
| 109 | + __gm__ float* splitWs = batchWs + 2 * aPlane + (int64_t)splitIdx * splitBGemmFloats; | ||
| 110 | + eBR = splitWs; | ||
| 111 | + eBI = eBR + bPlane; | ||
| 112 | + eLdb = nColsAligned; | ||
| 113 | + gmGemm = eBI + bPlane; | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + __aicore__ inline void SetupXnegPtrs(int32_t slot, int32_t idx, int32_t numPanels, | ||
| 117 | + __gm__ float*& xR, __gm__ float*& xI, | ||
| 118 | + __gm__ float* gmGemm) | ||
| 119 | + { | ||
| 120 | + int32_t xSlot = XnegSlot(idx, numPanels, forward); | ||
| 121 | + int64_t xnegPlane = (int64_t)2 * LIM_GROUP * 2 * nb * nColsAligned; | ||
| 122 | + xR = gmGemm + (int64_t)xSlot * 2 * nb * nColsAligned; | ||
| 123 | + xI = gmGemm + xnegPlane + (int64_t)xSlot * 2 * nb * nColsAligned; | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + __aicore__ inline void DoComplexGemm( | ||
| 127 | + AscendC::GlobalTensor<float>& gA, | ||
| 128 | + AscendC::GlobalTensor<float>& gBR, AscendC::GlobalTensor<float>& gBI, | ||
| 129 | + AscendC::GlobalTensor<float>& gXReal, AscendC::GlobalTensor<float>& gXImag, | ||
| 130 | + int32_t eAStride, int32_t eLdb, | ||
| 131 | + int32_t rowStart, int32_t rowCount, int32_t colStart, int32_t actualK) | ||
| 132 | + { | ||
| 133 | + int32_t aOff = rowStart * eAStride + colStart * 2; | ||
| 134 | + mm.SetOrgShape(rowCount, nCols, eAStride, nColsAligned, eLdb); | ||
| 135 | + mm.SetSingleShape(rowCount, nCols, 2 * actualK); | ||
| 136 | + mm.SetTensorA(gA[aOff], false); | ||
| 137 | + mm.SetTensorB(gXReal[0], false); | ||
| 138 | + mm.IterateAll(gBR[rowStart * eLdb], 1); | ||
| 139 | + mm.SetOrgShape(rowCount, nCols, eAStride, nColsAligned, eLdb); | ||
| 140 | + mm.SetSingleShape(rowCount, nCols, 2 * actualK); | ||
| 141 | + mm.SetTensorA(gA[aOff], false); | ||
| 142 | + mm.SetTensorB(gXImag[0], false); | ||
| 143 | + mm.IterateAll(gBI[rowStart * eLdb], 1); | ||
| 144 | + } | ||
| 145 | + | ||
| 146 | + // 组装本 slot 的 A/B/Xneg 全局张量并执行一次复数 GEMM 更新。 | ||
| 147 | + // DirectRankK / PreUpdateRankKWithinGroup / FullTrailUpdateWithinGroup 共用此流程, | ||
| 148 | + // 仅更新的行区间 [rowStart, rowStart+rowCount) 不同。 | ||
| 149 | + __aicore__ inline void SetupAndGemm(int32_t slot, int32_t idx, int32_t numPanels, | ||
| 150 | + int32_t rowStart, int32_t rowCount, | ||
| 151 | + int32_t panelStart, int32_t actualNb) | ||
| 152 | + { | ||
| 153 | + __gm__ float *eA, *eBR, *eBI, *gmGemm, *xR, *xI; | ||
| 154 | + int32_t eAStride, eLdb; | ||
| 155 | + Ptrs(slot, eA, eAStride, eBR, eBI, eLdb, gmGemm); | ||
| 156 | + SetupXnegPtrs(slot, idx, numPanels, xR, xI, gmGemm); | ||
| 157 | + AscendC::GlobalTensor<float> gA, gBR, gBI, gXReal, gXImag; | ||
| 158 | + gA.SetGlobalBuffer(eA, (uint32_t)((int64_t)kDim * eAStride)); | ||
| 159 | + gBR.SetGlobalBuffer(eBR, (uint32_t)((int64_t)kDim * eLdb)); | ||
| 160 | + gBI.SetGlobalBuffer(eBI, (uint32_t)((int64_t)kDim * eLdb)); | ||
| 161 | + gXReal.SetGlobalBuffer(xR, (uint32_t)((int64_t)2 * nb * nColsAligned)); | ||
| 162 | + gXImag.SetGlobalBuffer(xI, (uint32_t)((int64_t)2 * nb * nColsAligned)); | ||
| 163 | + DoComplexGemm(gA, gBR, gBI, gXReal, gXImag, | ||
| 164 | + eAStride, eLdb, rowStart, rowCount, panelStart, actualNb); | ||
| 165 | + } | ||
| 166 | + | ||
| 167 | + __aicore__ inline void ComputeTrail(int32_t idx, int32_t numPanels, | ||
| 168 | + int32_t& panelStart, int32_t& actualNb, | ||
| 169 | + int32_t& trailStart, int32_t& trailRows) | ||
| 170 | + { | ||
| 171 | + int32_t p = forward ? idx : (numPanels - 1 - idx); | ||
| 172 | + panelStart = p * nb; | ||
| 173 | + actualNb = (nb < kDim - panelStart) ? nb : (kDim - panelStart); | ||
| 174 | + if (forward) { trailStart = panelStart + actualNb; trailRows = kDim - trailStart; } | ||
| 175 | + else { trailStart = 0; trailRows = panelStart; } | ||
| 176 | + } | ||
| 177 | + | ||
| 178 | + __aicore__ inline bool DirectRankK(int32_t slot, int32_t idx, int32_t numPanels) | ||
| 179 | + { | ||
| 180 | + int32_t panelStart, actualNb, trailStart, trailRows; | ||
| 181 | + ComputeTrail(idx, numPanels, panelStart, actualNb, trailStart, trailRows); | ||
| 182 | + if (trailRows <= 0) return false; | ||
| 183 | + int32_t directRows = (nb < trailRows) ? nb : trailRows; | ||
| 184 | + int32_t directStart = forward ? trailStart : (trailStart + trailRows - directRows); | ||
| 185 | + SetupAndGemm(slot, idx, numPanels, directStart, directRows, panelStart, actualNb); | ||
| 186 | + return (trailRows > directRows); | ||
| 187 | + } | ||
| 188 | + | ||
| 189 | + __aicore__ inline void PreUpdateRankKWithinGroup(int32_t slot, int32_t idx, int32_t numPanels, | ||
| 190 | + int32_t groupEndRow, int32_t groupBoundaryRow) | ||
| 191 | + { | ||
| 192 | + int32_t panelStart, actualNb, trailStart, trailRows; | ||
| 193 | + ComputeTrail(idx, numPanels, panelStart, actualNb, trailStart, trailRows); | ||
| 194 | + int32_t directRows = (nb < trailRows) ? nb : trailRows; | ||
| 195 | + int32_t preStart, preRows; | ||
| 196 | + if (forward) { preStart = trailStart + directRows; preRows = groupEndRow - preStart; } | ||
| 197 | + else { | ||
| 198 | + int32_t directStart = trailStart + trailRows - directRows; | ||
| 199 | + preStart = groupBoundaryRow; | ||
| 200 | + preRows = directStart - groupBoundaryRow; | ||
| 201 | + } | ||
| 202 | + if (preRows <= 0) return; | ||
| 203 | + SetupAndGemm(slot, idx, numPanels, preStart, preRows, panelStart, actualNb); | ||
| 204 | + } | ||
| 205 | + | ||
| 206 | + __aicore__ inline void BigGroupGemm(int32_t slot, int32_t idxStart, int32_t groupSize, | ||
| 207 | + int32_t numPanels) | ||
| 208 | + { | ||
| 209 | + int32_t bigM, bigStart, colStart; | ||
| 210 | + ComputeBigGemmBounds(idxStart, groupSize, numPanels, bigM, bigStart, colStart); | ||
| 211 | + if (bigM <= 0) return; | ||
| 212 | + __gm__ float *eA, *eBR, *eBI, *gmGemm; | ||
| 213 | + int32_t eAStride, eLdb; | ||
| 214 | + Ptrs(slot, eA, eAStride, eBR, eBI, eLdb, gmGemm); | ||
| 215 | + int32_t g = idxStart / LIM_GROUP; | ||
| 216 | + int32_t groupBase = (g % 2) * LIM_GROUP; | ||
| 217 | + int64_t xnegPlane = (int64_t)2 * LIM_GROUP * 2 * nb * nColsAligned; | ||
| 218 | + __gm__ float* xR = gmGemm + (int64_t)groupBase * 2 * nb * nColsAligned; | ||
| 219 | + __gm__ float* xI = gmGemm + xnegPlane + (int64_t)groupBase * 2 * nb * nColsAligned; | ||
| 220 | + int32_t totalK = groupSize * nb; | ||
| 221 | + int32_t maxK = kDim - colStart; | ||
| 222 | + if (totalK > maxK) totalK = maxK; | ||
| 223 | + AscendC::GlobalTensor<float> gA, gBR, gBI, gXReal, gXImag; | ||
| 224 | + gA.SetGlobalBuffer(eA, (uint32_t)((int64_t)kDim * eAStride)); | ||
| 225 | + gBR.SetGlobalBuffer(eBR, (uint32_t)((int64_t)kDim * eLdb)); | ||
| 226 | + gBI.SetGlobalBuffer(eBI, (uint32_t)((int64_t)kDim * eLdb)); | ||
| 227 | + gXReal.SetGlobalBuffer(xR, (uint32_t)((int64_t)2 * totalK * nColsAligned)); | ||
| 228 | + gXImag.SetGlobalBuffer(xI, (uint32_t)((int64_t)2 * totalK * nColsAligned)); | ||
| 229 | + DoComplexGemm(gA, gBR, gBI, gXReal, gXImag, | ||
| 230 | + eAStride, eLdb, bigStart, bigM, colStart, totalK); | ||
| 231 | + } | ||
| 232 | + | ||
| 233 | + // 用组内 panel 子区间 [panelOffset, panelOffset+accPanels) 的 Xneg 更新远端行块 | ||
| 234 | + // [bigStart, bigStart+bigM)。K=accPanels*nb。用于把 BigGroupGemm 按 K 拆分、提前与 AIV 并行 | ||
| 235 | + __aicore__ inline void FarGemm(int32_t slot, int32_t idxStart, int32_t panelOffset, | ||
| 236 | + int32_t accPanels, int32_t bigStart, int32_t bigM) | ||
| 237 | + { | ||
| 238 | + if (bigM <= 0 || accPanels <= 0) return; | ||
| 239 | + __gm__ float *eA, *eBR, *eBI, *gmGemm; | ||
| 240 | + int32_t eAStride, eLdb; | ||
| 241 | + Ptrs(slot, eA, eAStride, eBR, eBI, eLdb, gmGemm); | ||
| 242 | + int32_t g = idxStart / LIM_GROUP; | ||
| 243 | + int32_t groupBase = (g % 2) * LIM_GROUP; | ||
| 244 | + int64_t xnegPlane = (int64_t)2 * LIM_GROUP * 2 * nb * nColsAligned; | ||
| 245 | + int32_t baseSlot = groupBase + panelOffset; | ||
| 246 | + __gm__ float* xR = gmGemm + (int64_t)baseSlot * 2 * nb * nColsAligned; | ||
| 247 | + __gm__ float* xI = gmGemm + xnegPlane + (int64_t)baseSlot * 2 * nb * nColsAligned; | ||
| 248 | + int32_t totalK = accPanels * nb; | ||
| 249 | + int32_t colStart = (idxStart + panelOffset) * nb; | ||
| 250 | + AscendC::GlobalTensor<float> gA, gBR, gBI, gXReal, gXImag; | ||
| 251 | + gA.SetGlobalBuffer(eA, (uint32_t)((int64_t)kDim * eAStride)); | ||
| 252 | + gBR.SetGlobalBuffer(eBR, (uint32_t)((int64_t)kDim * eLdb)); | ||
| 253 | + gBI.SetGlobalBuffer(eBI, (uint32_t)((int64_t)kDim * eLdb)); | ||
| 254 | + gXReal.SetGlobalBuffer(xR, (uint32_t)((int64_t)2 * totalK * nColsAligned)); | ||
| 255 | + gXImag.SetGlobalBuffer(xI, (uint32_t)((int64_t)2 * totalK * nColsAligned)); | ||
| 256 | + DoComplexGemm(gA, gBR, gBI, gXReal, gXImag, | ||
| 257 | + eAStride, eLdb, bigStart, bigM, colStart, totalK); | ||
| 258 | + } | ||
| 259 | + | ||
| 260 | + __aicore__ inline void ComputeBigGemmBounds(int32_t idxStart, int32_t groupSize, | ||
| 261 | + int32_t numPanels, | ||
| 262 | + int32_t& bigM, int32_t& bigStart, int32_t& colStart) | ||
| 263 | + { | ||
| 264 | + if (forward) { | ||
| 265 | + int32_t pLast = idxStart + groupSize - 1; | ||
| 266 | + int32_t groupEndRow = (((pLast + 2) * nb < kDim) ? (pLast + 2) * nb : kDim); | ||
| 267 | + bigM = kDim - groupEndRow; | ||
| 268 | + bigStart = groupEndRow; | ||
| 269 | + colStart = idxStart * nb; | ||
| 270 | + } else { | ||
| 271 | + int32_t pLast = numPanels - 1 - (idxStart + groupSize - 1); | ||
| 272 | + int32_t groupBoundaryRow = (((pLast - 1) * nb > 0) ? (pLast - 1) * nb : 0); | ||
| 273 | + bigM = groupBoundaryRow; | ||
| 274 | + bigStart = 0; | ||
| 275 | + colStart = pLast * nb; | ||
| 276 | + } | ||
| 277 | + } | ||
| 278 | + | ||
| 279 | + __aicore__ inline bool PanelHasTrail(int32_t idx, int32_t numPanels) | ||
| 280 | + { | ||
| 281 | + int32_t panelStart, actualNb, trailStart, trailRows; | ||
| 282 | + ComputeTrail(idx, numPanels, panelStart, actualNb, trailStart, trailRows); | ||
| 283 | + return trailRows > 0; | ||
| 284 | + } | ||
| 285 | + | ||
| 286 | + __aicore__ inline void Process12Simple(int32_t b0, int32_t b1, int32_t numPanels) | ||
| 287 | + { | ||
| 288 | + bool useMerged = (td->dualAivMode == 0); | ||
| 289 | + for (int32_t idx = 0; idx < numPanels; idx++) { | ||
| 290 | + if (!PanelHasTrail(idx, numPanels)) continue; | ||
| 291 | + AscendC::CrossCoreWaitFlag<2, PIPE_FIX>(FLAG_TRSV); | ||
| 292 | + if (useMerged) { | ||
| 293 | + FullTrailUpdateWithinGroup(b0, idx, numPanels, kDim, 0); | ||
| 294 | + if (b1 >= 0 && b1 < td->batchCount) | ||
| 295 | + FullTrailUpdateWithinGroup(b1, idx, numPanels, kDim, 0); | ||
| 296 | + AscendC::PipeBarrier<PIPE_FIX>(); | ||
| 297 | + AscendC::CrossCoreSetFlag<2, PIPE_FIX>(FLAG_GEMM); | ||
| 298 | + } else { | ||
| 299 | + bool hasMore0 = DirectRankK(b0, idx, numPanels); | ||
| 300 | + bool hasMore1 = (b1 >= 0 && b1 < td->batchCount) ? DirectRankK(b1, idx, numPanels) : false; | ||
| 301 | + AscendC::PipeBarrier<PIPE_FIX>(); | ||
| 302 | + AscendC::CrossCoreSetFlag<2, PIPE_FIX>(FLAG_GEMM); | ||
| 303 | + if (hasMore0) PreUpdateRankKWithinGroup(b0, idx, numPanels, kDim, 0); | ||
| 304 | + if (hasMore1) PreUpdateRankKWithinGroup(b1, idx, numPanels, kDim, 0); | ||
| 305 | + } | ||
| 306 | + } | ||
| 307 | + } | ||
| 308 | + | ||
| 309 | + __aicore__ inline void GroupBounds(int32_t grp, int32_t numPanels, | ||
| 310 | + int32_t& idxStart, int32_t& idxEnd, int32_t& groupSize, | ||
| 311 | + int32_t& groupEndRow, int32_t& groupBoundaryRow) | ||
| 312 | + { | ||
| 313 | + ::GroupBounds(grp, numPanels, nb, kDim, forward, | ||
| 314 | + idxStart, idxEnd, groupSize, groupEndRow, groupBoundaryRow); | ||
| 315 | + } | ||
| 316 | + | ||
| 317 | + __aicore__ inline void Process12Grouped(int32_t b0, int32_t b1, int32_t numPanels) | ||
| 318 | + { | ||
| 319 | + int32_t numGroups = (numPanels + LIM_GROUP - 1) / LIM_GROUP; | ||
| 320 | + for (int32_t grp = 0; grp < numGroups; grp++) { | ||
| 321 | + int32_t idxStart, idxEnd, groupSize, groupEndRow, groupBoundaryRow; | ||
| 322 | + GroupBounds(grp, numPanels, idxStart, idxEnd, groupSize, groupEndRow, groupBoundaryRow); | ||
| 323 | + ProcessOneGroup(b0, b1, numPanels, idxStart, idxEnd, groupSize, | ||
| 324 | + groupEndRow, groupBoundaryRow); | ||
| 325 | + } | ||
| 326 | + } | ||
| 327 | + | ||
| 328 | + // 单个 panel 的 trailing 更新(merged 全量 / direct+preupdate 两条路径) | ||
| 329 | + __aicore__ inline void UpdateOnePanel(int32_t b0, int32_t b1, int32_t idx, int32_t numPanels, | ||
| 330 | + int32_t groupEndRow, int32_t groupBoundaryRow, bool useMerged) | ||
| 331 | + { | ||
| 332 | + bool hasB1 = (b1 >= 0 && b1 < td->batchCount); | ||
| 333 | + if (useMerged) { | ||
| 334 | + FullTrailUpdateWithinGroup(b0, idx, numPanels, groupEndRow, groupBoundaryRow); | ||
| 335 | + if (hasB1) FullTrailUpdateWithinGroup(b1, idx, numPanels, groupEndRow, groupBoundaryRow); | ||
| 336 | + AscendC::PipeBarrier<PIPE_FIX>(); | ||
| 337 | + AscendC::CrossCoreSetFlag<2, PIPE_FIX>(FLAG_GEMM); | ||
| 338 | + return; | ||
| 339 | + } | ||
| 340 | + bool hasMore0 = DirectRankK(b0, idx, numPanels); | ||
| 341 | + bool hasMore1 = hasB1 ? DirectRankK(b1, idx, numPanels) : false; | ||
| 342 | + AscendC::PipeBarrier<PIPE_FIX>(); | ||
| 343 | + AscendC::CrossCoreSetFlag<2, PIPE_FIX>(FLAG_GEMM); | ||
| 344 | + if (hasMore0) PreUpdateRankKWithinGroup(b0, idx, numPanels, groupEndRow, groupBoundaryRow); | ||
| 345 | + if (hasMore1) PreUpdateRankKWithinGroup(b1, idx, numPanels, groupEndRow, groupBoundaryRow); | ||
| 346 | + } | ||
| 347 | + | ||
| 348 | + // 组末远端更新收尾:doSplit 补齐剩余段,否则做整块 BigGroupGemm | ||
| 349 | + __aicore__ inline void FinishGroupFar(int32_t b0, int32_t b1, int32_t idxStart, int32_t groupSize, | ||
| 350 | + int32_t numPanels, int32_t groupEndRow, int32_t groupBoundaryRow, | ||
| 351 | + bool doSplit, int32_t doneP, int32_t bigStartF, int32_t bigMF) | ||
| 352 | + { | ||
| 353 | + if (doSplit) { | ||
| 354 | + int32_t rem = groupSize - doneP; | ||
| 355 | + if (rem > 0) FarGemm(b0, idxStart, doneP, rem, bigStartF, bigMF); | ||
| 356 | + return; | ||
| 357 | + } | ||
| 358 | + int32_t bigM = forward ? (kDim - groupEndRow) : groupBoundaryRow; | ||
| 359 | + if (bigM <= 0) return; | ||
| 360 | + BigGroupGemm(b0, idxStart, groupSize, numPanels); | ||
| 361 | + if (b1 >= 0 && b1 < td->batchCount) BigGroupGemm(b1, idxStart, groupSize, numPanels); | ||
| 362 | + } | ||
| 363 | + | ||
| 364 | + __aicore__ inline void ProcessOneGroup(int32_t b0, int32_t b1, int32_t numPanels, | ||
| 365 | + int32_t idxStart, int32_t idxEnd, int32_t groupSize, | ||
| 366 | + int32_t groupEndRow, int32_t groupBoundaryRow) | ||
| 367 | + { | ||
| 368 | + bool useMerged = (td->dualAivMode == 0); | ||
| 369 | + constexpr int32_t FAR_STEP = 2; | ||
| 370 | + // forward: 把远端 BigGroupGemm 按 K 分成多段(每 FAR_STEP 个 panel 一段), | ||
| 371 | + // 每段解完后立即用该段 X(K=FAR_STEP*nb)更新远端大块,与 AIV 解后续 panel 并行。 | ||
| 372 | + // 各段 K 区间不相交 → 累加不重复;远端行 AIV 不碰 → 无 race。 | ||
| 373 | + int32_t bigStartF = forward ? groupEndRow : 0; | ||
| 374 | + int32_t bigMF = forward ? (kDim - groupEndRow) : 0; | ||
| 375 | + bool doSplit = false; | ||
| 376 | + int32_t doneP = 0; // 已用 FarGemm 处理的 panel 数 | ||
| 377 | + | ||
| 378 | + for (int32_t idx = idxStart; idx <= idxEnd; idx++) { | ||
| 379 | + if (!PanelHasTrail(idx, numPanels)) continue; | ||
| 380 | + AscendC::CrossCoreWaitFlag<2, PIPE_FIX>(FLAG_TRSV); | ||
| 381 | + UpdateOnePanel(b0, b1, idx, numPanels, groupEndRow, groupBoundaryRow, useMerged); | ||
| 382 | + // 每积累满 FAR_STEP 个 panel,立即对远端大块做一段更新(与 AIV 并行) | ||
| 383 | + if (doSplit && (idx - idxStart + 1 - doneP) >= FAR_STEP) { | ||
| 384 | + FarGemm(b0, idxStart, doneP, FAR_STEP, bigStartF, bigMF); | ||
| 385 | + doneP += FAR_STEP; | ||
| 386 | + } | ||
| 387 | + } | ||
| 388 | + FinishGroupFar(b0, b1, idxStart, groupSize, numPanels, groupEndRow, groupBoundaryRow, | ||
| 389 | + doSplit, doneP, bigStartF, bigMF); | ||
| 390 | + } | ||
| 391 | + | ||
| 392 | + __aicore__ inline void FullTrailUpdateWithinGroup(int32_t slot, int32_t idx, int32_t numPanels, | ||
| 393 | + int32_t groupEndRow, int32_t groupBoundaryRow) | ||
| 394 | + { | ||
| 395 | + int32_t panelStart, actualNb, trailStart, trailRows; | ||
| 396 | + ComputeTrail(idx, numPanels, panelStart, actualNb, trailStart, trailRows); | ||
| 397 | + if (trailRows <= 0) return; | ||
| 398 | + int32_t updateStart, updateRows; | ||
| 399 | + if (forward) { | ||
| 400 | + updateStart = trailStart; | ||
| 401 | + updateRows = groupEndRow - trailStart; | ||
| 402 | + } else { | ||
| 403 | + updateStart = groupBoundaryRow; | ||
| 404 | + updateRows = trailStart + trailRows - groupBoundaryRow; | ||
| 405 | + } | ||
| 406 | + if (updateRows <= 0) return; | ||
| 407 | + SetupAndGemm(slot, idx, numPanels, updateStart, updateRows, panelStart, actualNb); | ||
| 408 | + } | ||
| 409 | + | ||
| 410 | + const __gm__ CtrsmBatchedTilingData* td; | ||
| 411 | + AscendC::GlobalTensor<uint64_t> gmAArray, gmBArray; | ||
| 412 | + __gm__ uint8_t* gemmWsBase; | ||
| 413 | + uint32_t blockIdx; | ||
| 414 | + int32_t kDim, nCols, nb, nColsAligned; | ||
| 415 | + int32_t aEffStride; | ||
| 416 | + int32_t numSplits; | ||
| 417 | + bool forward, right, useOrigA; | ||
| 418 | +}; | ||
| @@ -0,0 +1,532 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +/*! | ||
| 12 | + * \file ctrsm_batched_kernel_aiv.h | ||
| 13 | + * \brief 复数三角求解 AIV 编排类,按计算路径模板化。原单一大类已按职责拆成协作的多个类: | ||
| 14 | + * - CtrsmAivCfg 共享派生配置 + UB buffer 指针 | ||
| 15 | + * - CtrsmConvert 复数 AoS<->SoA 转换/分块转置工具(路径无关) | ||
| 16 | + * - CtrsmCanonA A 规范化(补零/转置/共轭) | ||
| 17 | + * - CtrsmCanonB<RIGHT> B 规范化与回写(左/右乘) | ||
| 18 | + * - CtrsmPanelSolver<FORWARD> Panel 三角求解(前代/回代) | ||
| 19 | + * - CtrsmMixAivImpl<FORWARD,RIGHT> 编排类:持有 pipe/UB buffer/cfg,装配并驱动子类 | ||
| 20 | + * UB buffer 由编排类统一分配(保留原有别名布局以满足 192KB 预算),子类仅持指针引用。 | ||
| 21 | + * | ||
| 22 | + * 四条计算路径由模板参数在编译期固定(消除运行时分支),对应文件末尾四个类型别名; | ||
| 23 | + * 内核入口按 side/uplo/transa 分派到对应路径类型。 | ||
| 24 | + */ | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + | ||
| 32 | + | ||
| 33 | + | ||
| 34 | + | ||
| 35 | +template <bool FORWARD, bool RIGHT> | ||
| 36 | +class CtrsmMixAivImpl { | ||
| 37 | +public: | ||
| 38 | + __aicore__ inline CtrsmMixAivImpl() {} | ||
| 39 | + | ||
| 40 | + // 初始化:解析 tiling、设置全局内存指针、分配 UB 缓冲区、装配子对象 | ||
| 41 | + __aicore__ inline void Init(GM_ADDR aArrayGm, GM_ADDR bArrayGm, GM_ADDR gemmWsGm, | ||
| 42 | + const __gm__ CtrsmBatchedTilingData* t, AscendC::TPipe* pipeIn) | ||
| 43 | + { | ||
| 44 | + cfg.td = t; | ||
| 45 | + pipe = pipeIn; | ||
| 46 | + blockIdx = AscendC::GetBlockIdx(); | ||
| 47 | + cfg.kDim = RIGHT ? t->n : t->m; | ||
| 48 | + cfg.nCols = RIGHT ? t->m : t->n; | ||
| 49 | + cfg.nb = t->nb; | ||
| 50 | + cfg.kDimOrig = cfg.kDim; | ||
| 51 | + cfg.nColsOrig = cfg.nCols; | ||
| 52 | + int32_t kDimPad = CEIL_ALIGN(cfg.kDim, FLOAT_ALIGN); | ||
| 53 | + int32_t nColsPad = CEIL_ALIGN(cfg.nCols, FLOAT_ALIGN); | ||
| 54 | + cfg.padOn = (cfg.kDim != kDimPad) || (cfg.nCols != nColsPad); | ||
| 55 | + if (cfg.padOn) { cfg.kDim = kDimPad; cfg.nCols = nColsPad; } | ||
| 56 | + cfg.nColsAligned = CEIL_ALIGN(cfg.nCols, FLOAT_ALIGN); | ||
| 57 | + cfg.nbAligned = CEIL_ALIGN(cfg.nb, FLOAT_ALIGN); | ||
| 58 | + cfg.needTA = NeedTransA(t); | ||
| 59 | + cfg.conjA = IsConjTransA(t); | ||
| 60 | + gmAArray.SetGlobalBuffer((__gm__ uint64_t*)aArrayGm, t->batchCount); | ||
| 61 | + gmBArray.SetGlobalBuffer((__gm__ uint64_t*)bArrayGm, t->batchCount); | ||
| 62 | + gemmWsBase = gemmWsGm; | ||
| 63 | + cfg.useOrigA = (t->useOrigA == 1); | ||
| 64 | + cfg.aEffStride = t->aEffStride; | ||
| 65 | + cfg.localNCols = cfg.nColsOrig; | ||
| 66 | + cfg.localNColsAligned = cfg.nColsAligned; | ||
| 67 | + cfg.nColsOffset = 0; | ||
| 68 | + cfg.colStart = 0; | ||
| 69 | + cfg.colEnd = cfg.nColsAligned; | ||
| 70 | + InitBuffers(); | ||
| 71 | + WireSubObjects(); | ||
| 72 | + convert.BuildDeinterleaveOffsets(); // gather 偏移表构建一次,后续 LoadPanelA 复用 | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + // 初始化UB缓冲区分配:根据矩阵维度计算各缓冲区大小并分配 | ||
| 76 | + __aicore__ inline void InitBuffers() | ||
| 77 | + { | ||
| 78 | + int32_t kDimAligned = CEIL_ALIGN(cfg.kDim, FLOAT_ALIGN); | ||
| 79 | + int32_t rowMax = kDimAligned; | ||
| 80 | + if (cfg.nColsAligned > rowMax) rowMax = cfg.nColsAligned; | ||
| 81 | + if (rowMax < FLOAT_ALIGN) rowMax = FLOAT_ALIGN; | ||
| 82 | + rowMax = CEIL_ALIGN(rowMax, 32); | ||
| 83 | + pipe->InitBuffer(bufRow, rowMax * sizeof(float)); | ||
| 84 | + pipe->InitBuffer(bufPanelA_real, cfg.nbAligned * cfg.nbAligned * sizeof(float)); | ||
| 85 | + pipe->InitBuffer(bufPanelA_imag, cfg.nbAligned * cfg.nbAligned * sizeof(float)); | ||
| 86 | + | ||
| 87 | + int32_t fixedFloats = 2 * cfg.nbAligned * cfg.nbAligned + cfg.nbAligned + rowMax; | ||
| 88 | + int32_t perColFloats = 5 * cfg.nb + 1; | ||
| 89 | + constexpr int32_t UB_FLOATS = 192 * 1024 / (int32_t)sizeof(float); | ||
| 90 | + int32_t colTileMax = (UB_FLOATS - fixedFloats) / perColFloats; | ||
| 91 | + colTileMax = (colTileMax / FLOAT_ALIGN) * FLOAT_ALIGN; | ||
| 92 | + cfg.colTile = (cfg.nColsAligned <= colTileMax) ? cfg.nColsAligned : colTileMax; | ||
| 93 | + if (cfg.colTile < FLOAT_ALIGN) cfg.colTile = FLOAT_ALIGN; | ||
| 94 | + int32_t baseBuf = cfg.nb * cfg.colTile; | ||
| 95 | + int32_t interBuf = 2 * baseBuf; // 交错 B 存储 [实|虚] 需 nb*2*colTile | ||
| 96 | + int32_t panelBRealSize = (CtrsmAivCfg::TS * CtrsmAivCfg::TS > interBuf) ? CtrsmAivCfg::TS * CtrsmAivCfg::TS : interBuf; | ||
| 97 | + int32_t negINSize = (CtrsmAivCfg::TS * 16 > baseBuf) ? CtrsmAivCfg::TS * 16 : baseBuf; | ||
| 98 | + int32_t totalUsed = fixedFloats + panelBRealSize + 4 * baseBuf + negINSize + cfg.colTile; | ||
| 99 | + while (totalUsed > UB_FLOATS && cfg.colTile > FLOAT_ALIGN) { | ||
| 100 | + cfg.colTile -= FLOAT_ALIGN; | ||
| 101 | + baseBuf = cfg.nb * cfg.colTile; | ||
| 102 | + interBuf = 2 * baseBuf; | ||
| 103 | + panelBRealSize = (CtrsmAivCfg::TS * CtrsmAivCfg::TS > interBuf) ? CtrsmAivCfg::TS * CtrsmAivCfg::TS : interBuf; | ||
| 104 | + negINSize = (CtrsmAivCfg::TS * 16 > baseBuf) ? CtrsmAivCfg::TS * 16 : baseBuf; | ||
| 105 | + totalUsed = fixedFloats + panelBRealSize + 4 * baseBuf + negINSize + cfg.colTile; | ||
| 106 | + } | ||
| 107 | + baseBuf = cfg.nb * cfg.colTile; | ||
| 108 | + interBuf = 2 * baseBuf; | ||
| 109 | + panelBRealSize = (CtrsmAivCfg::TS * CtrsmAivCfg::TS > interBuf) ? CtrsmAivCfg::TS * CtrsmAivCfg::TS : interBuf; | ||
| 110 | + negINSize = (CtrsmAivCfg::TS * 16 > baseBuf) ? CtrsmAivCfg::TS * 16 : baseBuf; | ||
| 111 | + pipe->InitBuffer(bufPanelB_real, panelBRealSize * sizeof(float)); | ||
| 112 | + cfg.srcBufFloats = panelBRealSize; | ||
| 113 | + pipe->InitBuffer(bufPanelB_imag, baseBuf * sizeof(float)); | ||
| 114 | + pipe->InitBuffer(bufRankK, cfg.colTile * sizeof(float)); | ||
| 115 | + pipe->InitBuffer(bufNeg_real, baseBuf * sizeof(float)); | ||
| 116 | + pipe->InitBuffer(bufNeg_imag, baseBuf * sizeof(float)); | ||
| 117 | + pipe->InitBuffer(bufNeg_imag_neg, negINSize * sizeof(float)); | ||
| 118 | + int32_t gc = cfg.nb * cfg.colTile; | ||
| 119 | + cfg.gatherChunk = (gc < 256) ? gc : 256; | ||
| 120 | + cfg.gatherChunk = (cfg.gatherChunk / FLOAT_ALIGN) * FLOAT_ALIGN; | ||
| 121 | + if (cfg.gatherChunk < FLOAT_ALIGN) cfg.gatherChunk = FLOAT_ALIGN; | ||
| 122 | + // 专用 gather 偏移表 buffer(gatherChunk 个 int,固定内容) | ||
| 123 | + pipe->InitBuffer(bufGatherEven, cfg.gatherChunk * sizeof(int32_t)); | ||
| 124 | + pipe->InitBuffer(bufGatherOdd, cfg.gatherChunk * sizeof(int32_t)); | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + // 向量核主入口:根据 numSplits/dualAivMode 选择多核拆分/分列/原始独立模式 | ||
| 128 | + __aicore__ inline void Process12() | ||
| 129 | + { | ||
| 130 | + if (cfg.td->numSplits > 1) { | ||
| 131 | + int32_t aivBlock = (int32_t)blockIdx / 2; | ||
| 132 | + int32_t half = (int32_t)blockIdx % 2; | ||
| 133 | + int32_t batch = aivBlock / cfg.td->numSplits; | ||
| 134 | + int32_t splitIdx = aivBlock % cfg.td->numSplits; | ||
| 135 | + bool isLast = (splitIdx == cfg.td->numSplits - 1); | ||
| 136 | + cfg.localNCols = isLast ? cfg.td->lastNCols : cfg.td->splitNCols; | ||
| 137 | + cfg.localNColsAligned = isLast ? cfg.td->lastNColsAligned : cfg.td->splitNColsAligned; | ||
| 138 | + cfg.nColsOffset = splitIdx * cfg.td->splitNCols; | ||
| 139 | + int32_t localNColsAligned = cfg.localNColsAligned; | ||
| 140 | + cfg.nColsAligned = localNColsAligned; | ||
| 141 | + cfg.nCols = localNColsAligned; | ||
| 142 | + int32_t colMid = CEIL_ALIGN(localNColsAligned / 2, FLOAT_ALIGN); | ||
| 143 | + if (colMid > localNColsAligned) colMid = localNColsAligned; | ||
| 144 | + if (half == 0) { cfg.colStart = 0; cfg.colEnd = colMid; } | ||
| 145 | + else { cfg.colStart = colMid; cfg.colEnd = localNColsAligned; } | ||
| 146 | + ProcessOneBatchSplit(batch, half); | ||
| 147 | + } else if (cfg.td->dualAivMode) { | ||
| 148 | + int32_t batch = (int32_t)blockIdx / 2; | ||
| 149 | + int32_t half = (int32_t)blockIdx % 2; | ||
| 150 | + int32_t colMid = CEIL_ALIGN(cfg.nColsAligned / 2, FLOAT_ALIGN); | ||
| 151 | + if (colMid > cfg.nColsAligned) colMid = cfg.nColsAligned; | ||
| 152 | + if (half == 0) { cfg.colStart = 0; cfg.colEnd = colMid; } | ||
| 153 | + else { cfg.colStart = colMid; cfg.colEnd = cfg.nColsAligned; } | ||
| 154 | + ProcessOneBatchPadded(batch); | ||
| 155 | + } else { | ||
| 156 | + int32_t batch = (int32_t)blockIdx; | ||
| 157 | + cfg.colStart = 0; | ||
| 158 | + cfg.colEnd = cfg.nColsAligned; | ||
| 159 | + if (batch < cfg.td->batchCount) { | ||
| 160 | + cfg.buildRowStart = 0; | ||
| 161 | + cfg.buildRowEnd = cfg.kDim; | ||
| 162 | + ProcessOneBatchOriginal(batch); | ||
| 163 | + } else { | ||
| 164 | + DummyPanelSync(); | ||
| 165 | + } | ||
| 166 | + } | ||
| 167 | + } | ||
| 168 | + | ||
| 169 | +private: | ||
| 170 | + __aicore__ inline void WireSubObjects() | ||
| 171 | + { | ||
| 172 | + cfg.bufPanelA_real = &bufPanelA_real; cfg.bufPanelA_imag = &bufPanelA_imag; | ||
| 173 | + cfg.bufPanelB_real = &bufPanelB_real; cfg.bufPanelB_imag = &bufPanelB_imag; | ||
| 174 | + cfg.bufNeg_real = &bufNeg_real; cfg.bufNeg_imag = &bufNeg_imag; cfg.bufNeg_imag_neg = &bufNeg_imag_neg; | ||
| 175 | + cfg.bufRankK = &bufRankK; cfg.bufRow = &bufRow; | ||
| 176 | + cfg.bufGatherEven = &bufGatherEven; cfg.bufGatherOdd = &bufGatherOdd; | ||
| 177 | + convert.Bind(&cfg); | ||
| 178 | + canonA.Bind(&cfg, &convert); | ||
| 179 | + canonB.Bind(&cfg, &convert); | ||
| 180 | + solver.Bind(&cfg, &convert); | ||
| 181 | + } | ||
| 182 | + | ||
| 183 | + // 判断当前Panel是否有Trail区域需要GEMM更新 | ||
| 184 | + __aicore__ inline bool PanelHasTrailAiv(int32_t idx, int32_t numPanels) | ||
| 185 | + { | ||
| 186 | + int32_t p = FORWARD ? idx : (numPanels - 1 - idx); | ||
| 187 | + int32_t panelStart = p * cfg.nb; | ||
| 188 | + int32_t actualNb = (cfg.nb < cfg.kDim - panelStart) ? cfg.nb : (cfg.kDim - panelStart); | ||
| 189 | + int32_t trailRows = FORWARD ? (cfg.kDim - (panelStart + actualNb)) : panelStart; | ||
| 190 | + return trailRows > 0; | ||
| 191 | + } | ||
| 192 | + | ||
| 193 | + // 空batch时执行虚拟同步,配合Cube核保持跨核flag对齐 | ||
| 194 | + __aicore__ inline void DummyPanelSync() | ||
| 195 | + { | ||
| 196 | + int32_t numPanels = (cfg.kDim + cfg.nb - 1) / cfg.nb; | ||
| 197 | + for (int32_t idx = 0; idx < numPanels; idx++) { | ||
| 198 | + if (!PanelHasTrailAiv(idx, numPanels)) continue; | ||
| 199 | + AscendC::PipeBarrier<PIPE_MTE3>(); | ||
| 200 | + AscendC::CrossCoreSetFlag<2, PIPE_MTE3>(FLAG_TRSV); | ||
| 201 | + AscendC::CrossCoreWaitFlag<2, PIPE_MTE2>(FLAG_GEMM); | ||
| 202 | + } | ||
| 203 | + } | ||
| 204 | + | ||
| 205 | + // 准备A矩阵工作区(转置/padding),返回有效A指针和stride | ||
| 206 | + __aicore__ inline void PrepareAMatrix(int32_t batch, __gm__ float* coreWs, | ||
| 207 | + __gm__ float* gmBc_real, __gm__ float* gmBc_imag, __gm__ float* gmGemm, | ||
| 208 | + __gm__ float*& effA, int32_t& effAStride) | ||
| 209 | + { | ||
| 210 | + __gm__ float* gmA = (__gm__ float*)gmAArray.GetValue(batch); | ||
| 211 | + __gm__ float* gmAc = coreWs; | ||
| 212 | + if (cfg.useOrigA) { | ||
| 213 | + effA = gmA; | ||
| 214 | + effAStride = cfg.aEffStride; | ||
| 215 | + } else if (cfg.needTA) { | ||
| 216 | + int32_t wsStride = 2 * cfg.kDim; | ||
| 217 | + float signIm = cfg.conjA ? -1.0f : 1.0f; | ||
| 218 | + convert.TransposeADirectToAoS(gmA, cfg.kDimOrig, cfg.td->lda, | ||
| 219 | + gmAc, wsStride, signIm, 0, cfg.kDim, cfg.padOn, cfg.kDim); | ||
| 220 | + effA = gmAc; | ||
| 221 | + effAStride = wsStride; | ||
| 222 | + } else { | ||
| 223 | + canonA.BuildPaddedA(gmA, gmAc, gmBc_real, gmBc_imag, gmGemm); | ||
| 224 | + effA = gmAc; | ||
| 225 | + effAStride = 2 * cfg.kDim; | ||
| 226 | + } | ||
| 227 | + } | ||
| 228 | + | ||
| 229 | + // 准备B矩阵、执行求解循环、回写结果 | ||
| 230 | + __aicore__ inline void PrepareBAndSolve(int32_t batch, __gm__ float* effA, int32_t effAStride, | ||
| 231 | + __gm__ float* gmBc_real, __gm__ float* gmBc_imag, __gm__ float* gmGemm) | ||
| 232 | + { | ||
| 233 | + __gm__ float* gmB = (__gm__ float*)gmBArray.GetValue(batch); | ||
| 234 | + if (RIGHT) { | ||
| 235 | + int32_t rTotal = (cfg.td->m < cfg.nColsOrig) ? cfg.td->m : cfg.nColsOrig; | ||
| 236 | + int32_t deintCols = (cfg.td->n < cfg.kDimOrig) ? cfg.td->n : cfg.kDimOrig; | ||
| 237 | + if (cfg.padOn) { | ||
| 238 | + convert.ZeroGmRows(gmBc_real, cfg.kDim, cfg.nColsAligned, cfg.nColsAligned); | ||
| 239 | + convert.ZeroGmRows(gmBc_imag, cfg.kDim, cfg.nColsAligned, cfg.nColsAligned); | ||
| 240 | + } | ||
| 241 | + convert.TransposeAoSDirectToSoA(gmB, rTotal, deintCols, cfg.td->ldb, | ||
| 242 | + gmBc_real, gmBc_imag, cfg.nColsAligned, 0, cfg.kDimOrig); | ||
| 243 | + float aRe = cfg.td->alphaReal; | ||
| 244 | + float aIm = cfg.td->alphaImag; | ||
| 245 | + if (aRe != 1.0f || aIm != 0.0f) { | ||
| 246 | + cfg.buildRowStart = 0; | ||
| 247 | + cfg.buildRowEnd = cfg.kDim; | ||
| 248 | + canonB.BuildBRightPhase2Alpha(gmBc_real, gmBc_imag, cfg.nColsAligned, aRe, aIm); | ||
| 249 | + } | ||
| 250 | + } else { | ||
| 251 | + cfg.buildRowStart = 0; | ||
| 252 | + cfg.buildRowEnd = cfg.kDim; | ||
| 253 | + canonB.BuildPaddedB(gmB, gmBc_real, gmBc_imag, gmGemm); | ||
| 254 | + } | ||
| 255 | + RunPanelLoop(effA, effAStride, gmBc_real, gmBc_imag, gmGemm, gmB); | ||
| 256 | + AscendC::PipeBarrier<PIPE_ALL>(); | ||
| 257 | + if (RIGHT) { | ||
| 258 | + canonB.WriteBackPaddedB(gmBc_real, gmBc_imag, gmB, gmGemm, 0, cfg.td->m); | ||
| 259 | + } | ||
| 260 | + } | ||
| 261 | + | ||
| 262 | + // 原始单AIV处理路径(无分列,workspace按blockIdx索引) | ||
| 263 | + __aicore__ inline void ProcessOneBatchOriginal(int32_t batch) | ||
| 264 | + { | ||
| 265 | + __gm__ float* coreWs = (__gm__ float*)gemmWsBase | ||
| 266 | + + (int64_t)blockIdx * (cfg.td->workspaceOffset / sizeof(float)); | ||
| 267 | + int64_t aPlaneSize = (int64_t)cfg.kDim * cfg.kDim; | ||
| 268 | + __gm__ float* gmAc = coreWs; | ||
| 269 | + int64_t bPlaneSize = (int64_t)cfg.kDim * cfg.nColsAligned; | ||
| 270 | + __gm__ float* gmBc_real = coreWs + 2 * aPlaneSize; | ||
| 271 | + __gm__ float* gmBc_imag = gmBc_real + bPlaneSize; | ||
| 272 | + __gm__ float* gmGemm = gmBc_imag + bPlaneSize; | ||
| 273 | + __gm__ float* effA; | ||
| 274 | + int32_t effAStride; | ||
| 275 | + PrepareAMatrix(batch, coreWs, gmBc_real, gmBc_imag, gmGemm, effA, effAStride); | ||
| 276 | + PrepareBAndSolve(batch, effA, effAStride, gmBc_real, gmBc_imag, gmGemm); | ||
| 277 | + } | ||
| 278 | + // 处理单个batch(dual分列路径):构建A/B工作区、执行Panel循环、回写结果 | ||
| 279 | + __aicore__ inline void ProcessOneBatchPadded(int32_t batch) | ||
| 280 | + { | ||
| 281 | + __gm__ float* gmA = (__gm__ float*)gmAArray.GetValue(batch); | ||
| 282 | + __gm__ float* gmB = (__gm__ float*)gmBArray.GetValue(batch); | ||
| 283 | + __gm__ float* coreWs = (__gm__ float*)gemmWsBase | ||
| 284 | + + (int64_t)batch * (cfg.td->workspaceOffset / sizeof(float)); | ||
| 285 | + int64_t aPlaneSize = (int64_t)cfg.kDim * cfg.kDim; | ||
| 286 | + __gm__ float* gmAc = coreWs; | ||
| 287 | + int64_t bPlaneSize = (int64_t)cfg.kDim * cfg.nColsAligned; | ||
| 288 | + __gm__ float* gmBc_real = coreWs + 2 * aPlaneSize; | ||
| 289 | + __gm__ float* gmBc_imag = gmBc_real + bPlaneSize; | ||
| 290 | + __gm__ float* gmGemm = gmBc_imag + bPlaneSize; | ||
| 291 | + int32_t half = (int32_t)blockIdx % 2; | ||
| 292 | + __gm__ float* effA; | ||
| 293 | + int32_t effAStride; | ||
| 294 | + | ||
| 295 | + PrepareAWithSync(gmA, gmAc, gmBc_real, gmBc_imag, gmGemm, half, effA, effAStride); | ||
| 296 | + PrepareBWithSync(gmB, gmBc_real, gmBc_imag, gmGemm, half); | ||
| 297 | + | ||
| 298 | + RunPanelLoop(effA, effAStride, gmBc_real, gmBc_imag, gmGemm, gmB); | ||
| 299 | + AscendC::PipeBarrier<PIPE_ALL>(); | ||
| 300 | + if (RIGHT) { | ||
| 301 | + DualAivBarrier(); | ||
| 302 | + // dual-AIV 写回按输出行切分:两核各写一半,消除整矩阵重复转置/回写 | ||
| 303 | + int32_t mOrig = cfg.td->m; | ||
| 304 | + int32_t rowMid = ((mOrig / 2 + CtrsmAivCfg::TS - 1) / CtrsmAivCfg::TS) * CtrsmAivCfg::TS; | ||
| 305 | + if (rowMid > mOrig) rowMid = mOrig; | ||
| 306 | + int32_t wbBeg = (half == 0) ? 0 : rowMid; | ||
| 307 | + int32_t wbEnd = (half == 0) ? rowMid : mOrig; | ||
| 308 | + canonB.WriteBackPaddedB(gmBc_real, gmBc_imag, gmB, gmGemm, wbBeg, wbEnd); | ||
| 309 | + } | ||
| 310 | + } | ||
| 311 | + | ||
| 312 | + // 多核拆分路径:每个 block 的 2 AIV 协同处理一个 split(复用 dual-AIV 同步协议) | ||
| 313 | + __aicore__ inline void ProcessOneBatchSplit(int32_t batch, int32_t half) | ||
| 314 | + { | ||
| 315 | + __gm__ float* gmA = (__gm__ float*)gmAArray.GetValue(batch); | ||
| 316 | + __gm__ float* gmBOrig = (__gm__ float*)gmBArray.GetValue(batch); | ||
| 317 | + __gm__ float* gmB; | ||
| 318 | + if (RIGHT) { | ||
| 319 | + gmB = gmBOrig + (int64_t)cfg.nColsOffset * cfg.td->ldb * 2; | ||
| 320 | + } else { | ||
| 321 | + gmB = gmBOrig; | ||
| 322 | + } | ||
| 323 | + int32_t savedNColsOrig = cfg.nColsOrig; | ||
| 324 | + cfg.nColsOrig = cfg.localNCols; | ||
| 325 | + int32_t aivBlock = (int32_t)blockIdx / 2; | ||
| 326 | + int32_t splitIdx = aivBlock % cfg.td->numSplits; | ||
| 327 | + __gm__ float* batchWs = (__gm__ float*)gemmWsBase | ||
| 328 | + + (int64_t)batch * (cfg.td->workspaceOffset / sizeof(float)); | ||
| 329 | + int64_t aPlaneSize = (int64_t)cfg.kDim * cfg.kDim; | ||
| 330 | + __gm__ float* gmAc = batchWs; | ||
| 331 | + int32_t wsNCols = (cfg.td->splitNColsAligned > cfg.td->lastNColsAligned) | ||
| 332 | + ? cfg.td->splitNColsAligned : cfg.td->lastNColsAligned; | ||
| 333 | + int64_t bPlaneSize = (int64_t)cfg.kDim * wsNCols; | ||
| 334 | + int64_t splitBGemmFloats = cfg.td->splitBGemmSize / sizeof(float); | ||
| 335 | + __gm__ float* splitWs = batchWs + 2 * aPlaneSize + (int64_t)splitIdx * splitBGemmFloats; | ||
| 336 | + __gm__ float* gmBc_real = splitWs; | ||
| 337 | + __gm__ float* gmBc_imag = gmBc_real + bPlaneSize; | ||
| 338 | + __gm__ float* gmGemm = gmBc_imag + bPlaneSize; | ||
| 339 | + __gm__ float* effA; | ||
| 340 | + int32_t effAStride; | ||
| 341 | + | ||
| 342 | + PrepareAWithSync(gmA, gmAc, gmBc_real, gmBc_imag, gmGemm, half, effA, effAStride); | ||
| 343 | + PrepareBSplit(gmB, gmBc_real, gmBc_imag, gmGemm, half); | ||
| 344 | + | ||
| 345 | + RunPanelLoop(effA, effAStride, gmBc_real, gmBc_imag, gmGemm, gmB); | ||
| 346 | + AscendC::PipeBarrier<PIPE_ALL>(); | ||
| 347 | + if (RIGHT) { | ||
| 348 | + DualAivBarrier(); | ||
| 349 | + int32_t localM = cfg.localNCols; | ||
| 350 | + int32_t rowMid = ((localM / 2 + CtrsmAivCfg::TS - 1) / CtrsmAivCfg::TS) * CtrsmAivCfg::TS; | ||
| 351 | + if (rowMid > localM) rowMid = localM; | ||
| 352 | + int32_t wbBeg = (half == 0) ? 0 : rowMid; | ||
| 353 | + int32_t wbEnd = (half == 0) ? rowMid : localM; | ||
| 354 | + canonB.WriteBackPaddedB(gmBc_real, gmBc_imag, gmB, gmGemm, wbBeg, wbEnd); | ||
| 355 | + } | ||
| 356 | + cfg.nColsOrig = savedNColsOrig; | ||
| 357 | + } | ||
| 358 | + | ||
| 359 | + // 共用:Left 模式下按 half 分行构建 B 工作区 | ||
| 360 | + __aicore__ inline void PrepareBLeftHalf(__gm__ float* gmB, | ||
| 361 | + __gm__ float* gmBc_real, __gm__ float* gmBc_imag, __gm__ float* gmGemm, | ||
| 362 | + int32_t half) | ||
| 363 | + { | ||
| 364 | + int32_t totalRows = cfg.kDim; | ||
| 365 | + int32_t rowMid = CEIL_ALIGN(totalRows / 2, FLOAT_ALIGN); | ||
| 366 | + if (rowMid > totalRows) rowMid = totalRows; | ||
| 367 | + cfg.buildRowStart = (half == 0) ? 0 : rowMid; | ||
| 368 | + cfg.buildRowEnd = (half == 0) ? rowMid : totalRows; | ||
| 369 | + canonB.BuildPaddedB(gmB, gmBc_real, gmBc_imag, gmGemm); | ||
| 370 | + DualAivBarrier(); | ||
| 371 | + } | ||
| 372 | + | ||
| 373 | + // 共用:Right 模式下按 half 分列解交织 B 并可选 alpha 缩放 | ||
| 374 | + __aicore__ inline void PrepareBRightHalf(__gm__ float* gmB, | ||
| 375 | + __gm__ float* gmBc_real, __gm__ float* gmBc_imag, | ||
| 376 | + int32_t half, int32_t rTotal) | ||
| 377 | + { | ||
| 378 | + int32_t nColsAligned = cfg.nColsAligned; | ||
| 379 | + int32_t kDimOrig = cfg.kDimOrig; | ||
| 380 | + int32_t kDim = cfg.kDim; | ||
| 381 | + int32_t cbMid = CEIL_ALIGN(kDim / 2, FLOAT_ALIGN); | ||
| 382 | + if (cbMid > kDim) cbMid = kDim; | ||
| 383 | + int32_t cbBeg = (half == 0) ? 0 : cbMid; | ||
| 384 | + int32_t cbEnd = (half == 0) ? cbMid : kDim; | ||
| 385 | + cfg.buildRowStart = cbBeg; | ||
| 386 | + cfg.buildRowEnd = (cbEnd < kDimOrig) ? cbEnd : kDimOrig; | ||
| 387 | + int32_t nOrig = cfg.td->n; | ||
| 388 | + int32_t deintCols = (nOrig < kDimOrig) ? nOrig : kDimOrig; | ||
| 389 | + convert.TransposeAoSDirectToSoA(gmB, rTotal, deintCols, cfg.td->ldb, | ||
| 390 | + gmBc_real, gmBc_imag, nColsAligned, cbBeg, cbEnd); | ||
| 391 | + float aRe = cfg.td->alphaReal; | ||
| 392 | + float aIm = cfg.td->alphaImag; | ||
| 393 | + if (aRe != 1.0f || aIm != 0.0f) { | ||
| 394 | + canonB.BuildBRightPhase2Alpha(gmBc_real, gmBc_imag, nColsAligned, aRe, aIm); | ||
| 395 | + } | ||
| 396 | + DualAivBarrier(); | ||
| 397 | + } | ||
| 398 | + | ||
| 399 | + // B 工作区准备(split 模式):按 half 分行清零/解交织,复用 dual-AIV 协议 | ||
| 400 | + __aicore__ inline void PrepareBSplit(__gm__ float* gmB, | ||
| 401 | + __gm__ float* gmBc_real, __gm__ float* gmBc_imag, __gm__ float* gmGemm, | ||
| 402 | + int32_t half) | ||
| 403 | + { | ||
| 404 | + if (!RIGHT) { | ||
| 405 | + PrepareBLeftHalf(gmB, gmBc_real, gmBc_imag, gmGemm, half); | ||
| 406 | + return; | ||
| 407 | + } | ||
| 408 | + int32_t nColsOrig = cfg.nColsOrig; | ||
| 409 | + int32_t kDimOrig = cfg.kDimOrig; | ||
| 410 | + int32_t rTotal = (nColsOrig < kDimOrig) ? nColsOrig : kDimOrig; | ||
| 411 | + PrepareBRightHalf(gmB, gmBc_real, gmBc_imag, half, rTotal); | ||
| 412 | + } | ||
| 413 | + | ||
| 414 | + // A工作区准备:needTA 时单 pass 转置(两核并行各做一半输出列),否则单核直接复制 | ||
| 415 | + __aicore__ inline void PrepareAWithSync(__gm__ float* gmA, __gm__ float* gmAc, | ||
| 416 | + __gm__ float* gmBc_real, __gm__ float* gmBc_imag, __gm__ float* gmGemm, | ||
| 417 | + int32_t half, __gm__ float*& effA, int32_t& effAStride) | ||
| 418 | + { | ||
| 419 | + if (!cfg.useOrigA) { | ||
| 420 | + if (cfg.needTA) { | ||
| 421 | + int32_t kDimOrig = cfg.kDimOrig; | ||
| 422 | + int32_t kDim = cfg.kDim; | ||
| 423 | + int32_t wsStride = 2 * kDim; | ||
| 424 | + float signIm = cfg.conjA ? -1.0f : 1.0f; | ||
| 425 | + int32_t colMid = CEIL_ALIGN(kDim / 2, FLOAT_ALIGN); | ||
| 426 | + if (colMid > kDim) colMid = kDim; | ||
| 427 | + int32_t cBeg = (half == 0) ? 0 : colMid; | ||
| 428 | + int32_t cEnd = (half == 0) ? colMid : kDim; | ||
| 429 | + convert.TransposeADirectToAoS(gmA, kDimOrig, cfg.td->lda, | ||
| 430 | + gmAc, wsStride, signIm, cBeg, cEnd, cfg.padOn, kDim); | ||
| 431 | + DualAivBarrier(); | ||
| 432 | + } else { | ||
| 433 | + if (half == 0) { | ||
| 434 | + canonA.BuildPaddedA(gmA, gmAc, gmBc_real, gmBc_imag, gmGemm); | ||
| 435 | + } | ||
| 436 | + DualAivBarrier(); | ||
| 437 | + } | ||
| 438 | + effA = gmAc; | ||
| 439 | + effAStride = 2 * cfg.kDim; | ||
| 440 | + } else { | ||
| 441 | + effA = gmA; | ||
| 442 | + effAStride = cfg.aEffStride; | ||
| 443 | + } | ||
| 444 | + } | ||
| 445 | + | ||
| 446 | + // 双 AIV 屏障:AI Core 内两 AIV 各完成本核 workspace 构建后经 mode1 核间同步互等 | ||
| 447 | + // (替代原 GM flag 忙等轮询,消除轮询循环与 PIPE_ALL;PIPE_MTE3 保证 GM 写对对方可见) | ||
| 448 | + __aicore__ inline void DualAivBarrier() | ||
| 449 | + { | ||
| 450 | + AscendC::CrossCoreSetFlag<1, PIPE_MTE3>(FLAG_DUAL_AIV); | ||
| 451 | + AscendC::CrossCoreWaitFlag<1, PIPE_MTE3>(FLAG_DUAL_AIV); | ||
| 452 | + } | ||
| 453 | + | ||
| 454 | + // B工作区准备:设置分行范围、构建补零B,并按 left/right 与 half 完成跨AIV同步 | ||
| 455 | + __aicore__ inline void PrepareBWithSync(__gm__ float* gmB, | ||
| 456 | + __gm__ float* gmBc_real, __gm__ float* gmBc_imag, __gm__ float* gmGemm, | ||
| 457 | + int32_t half) | ||
| 458 | + { | ||
| 459 | + if (!RIGHT) { | ||
| 460 | + PrepareBLeftHalf(gmB, gmBc_real, gmBc_imag, gmGemm, half); | ||
| 461 | + return; | ||
| 462 | + } | ||
| 463 | + // Right dual:单 pass 构建(两核各做一半输出行,含 pad) | ||
| 464 | + int32_t mOrig = cfg.td->m; | ||
| 465 | + int32_t nColsOrig = cfg.nColsOrig; | ||
| 466 | + int32_t rTotal = (mOrig < nColsOrig) ? mOrig : nColsOrig; | ||
| 467 | + PrepareBRightHalf(gmB, gmBc_real, gmBc_imag, half, rTotal); | ||
| 468 | + } | ||
| 469 | + | ||
| 470 | + // 逐Panel执行三角求解,并与AIC核同步完成Trail区域GEMM更新 | ||
| 471 | + // 优化:在等待AIC GEMM期间预加载下一Panel的A对角块(与GEMM并行) | ||
| 472 | + __aicore__ inline void RunPanelLoop(__gm__ float* effA, int32_t effAStride, | ||
| 473 | + __gm__ float* gmBcR, __gm__ float* gmBcI, | ||
| 474 | + __gm__ float* gmGemm, __gm__ float* gmB) | ||
| 475 | + { | ||
| 476 | + int32_t nb = cfg.nb, kDim = cfg.kDim, nColsAligned = cfg.nColsAligned; | ||
| 477 | + int32_t numPanels = (kDim + nb - 1) / nb; | ||
| 478 | + AscendC::LocalTensor<float> ubAR = bufPanelA_real.Get<float>(); | ||
| 479 | + AscendC::LocalTensor<float> ubAI = bufPanelA_imag.Get<float>(); | ||
| 480 | + for (int32_t idx = 0; idx < numPanels; idx++) { | ||
| 481 | + int32_t p = FORWARD ? idx : (numPanels - 1 - idx); | ||
| 482 | + int32_t panelStart = p * nb; | ||
| 483 | + int32_t actualNb = (nb < kDim - panelStart) ? nb : (kDim - panelStart); | ||
| 484 | + int32_t slot = XnegSlot(idx, numPanels, FORWARD); | ||
| 485 | + int64_t xnegPlaneSize = (int64_t)2 * LIM_GROUP * 2 * nb * nColsAligned; | ||
| 486 | + __gm__ float* xR = gmGemm + (int64_t)slot * 2 * nb * nColsAligned; | ||
| 487 | + __gm__ float* xI = gmGemm + xnegPlaneSize + (int64_t)slot * 2 * nb * nColsAligned; | ||
| 488 | + if (idx == 0) { | ||
| 489 | + solver.LoadPanelA(effA, effAStride, ubAR, ubAI, panelStart, actualNb); | ||
| 490 | + } | ||
| 491 | + solver.PanelTrsv(effA, effAStride, gmBcR, gmBcI, nColsAligned, | ||
| 492 | + xR, xI, panelStart, actualNb, PanelHasTrailAiv(idx, numPanels)); | ||
| 493 | + if (PanelHasTrailAiv(idx, numPanels)) { | ||
| 494 | + AscendC::PipeBarrier<PIPE_MTE3>(); | ||
| 495 | + AscendC::CrossCoreSetFlag<2, PIPE_MTE3>(FLAG_TRSV); | ||
| 496 | + if (!RIGHT) { | ||
| 497 | + canonB.WriteBackPanelRows(gmBcR, gmBcI, gmB, panelStart, actualNb); | ||
| 498 | + } | ||
| 499 | + int32_t nextIdx = idx + 1; | ||
| 500 | + if (nextIdx < numPanels) { | ||
| 501 | + int32_t np = FORWARD ? nextIdx : (numPanels - 1 - nextIdx); | ||
| 502 | + int32_t nextStart = np * nb; | ||
| 503 | + int32_t nextNb = (nb < kDim - nextStart) ? nb : (kDim - nextStart); | ||
| 504 | + solver.LoadPanelA(effA, effAStride, ubAR, ubAI, nextStart, nextNb); | ||
| 505 | + } | ||
| 506 | + AscendC::CrossCoreWaitFlag<2, PIPE_MTE2>(FLAG_GEMM); | ||
| 507 | + } else if (!RIGHT) { | ||
| 508 | + canonB.WriteBackPanelRows(gmBcR, gmBcI, gmB, panelStart, actualNb); | ||
| 509 | + } | ||
| 510 | + } | ||
| 511 | + } | ||
| 512 | + | ||
| 513 | + // ---- owned resources ---- | ||
| 514 | + AscendC::TPipe* pipe; | ||
| 515 | + CtrsmAivCfg cfg; | ||
| 516 | + CtrsmConvert convert; | ||
| 517 | + CtrsmCanonA canonA; | ||
| 518 | + CtrsmCanonB<RIGHT> canonB; | ||
| 519 | + CtrsmPanelSolver<FORWARD> solver; | ||
| 520 | + AscendC::GlobalTensor<uint64_t> gmAArray, gmBArray; | ||
| 521 | + __gm__ uint8_t* gemmWsBase; | ||
| 522 | + uint32_t blockIdx; | ||
| 523 | + BufVecCalc bufPanelA_real, bufPanelA_imag, bufPanelB_real, bufPanelB_imag; | ||
| 524 | + BufVecCalc bufNeg_real, bufNeg_imag, bufNeg_imag_neg, bufRankK, bufRow; | ||
| 525 | + BufVecCalc bufGatherEven, bufGatherOdd; | ||
| 526 | +}; | ||
| 527 | + | ||
| 528 | +// 四条计算路径的具体类型别名 | ||
| 529 | +using CtrsmLowerLeft = CtrsmMixAivImpl<true, false>; // 下三角前代 + 左乘 | ||
| 530 | +using CtrsmLowerRight = CtrsmMixAivImpl<true, true>; // 下三角前代 + 右乘 | ||
| 531 | +using CtrsmUpperLeft = CtrsmMixAivImpl<false, false>; // 上三角回代 + 左乘 | ||
| 532 | +using CtrsmUpperRight = CtrsmMixAivImpl<false, true>; // 上三角回代 + 右乘 | ||
| @@ -0,0 +1,149 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +/*! | ||
| 12 | + * \file ctrsm_batched_kernel_aiv_canon_a.h | ||
| 13 | + * \brief A 矩阵规范化器:把用户 A 转成补零对齐的 AoS 工作区(清零→直拷/转置(+共轭)→补单位对角)。 | ||
| 14 | + * 转置分快速路径与分块路径,均委托 CtrsmConvert 做解交织/交织/分块转置。 | ||
| 15 | + * 与计算路径(forward/right)无关,依赖 needTA/conjA 运行时标志。 | ||
| 16 | + */ | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | +class CtrsmCanonA { | ||
| 24 | +public: | ||
| 25 | + __aicore__ inline CtrsmCanonA() {} | ||
| 26 | + | ||
| 27 | + __aicore__ inline void Bind(CtrsmAivCfg* cfg, CtrsmConvert* cvt) { cfg_ = cfg; cvt_ = cvt; } | ||
| 28 | + | ||
| 29 | + // 构建补零后的A矩阵AoS工作区:清零→直接复制(仅 NoTrans 调用) | ||
| 30 | + __aicore__ inline void BuildPaddedA(__gm__ float* gmA, __gm__ float* gmAc, | ||
| 31 | + __gm__ float* gmTmp1, __gm__ float* gmTmp2, | ||
| 32 | + __gm__ float* gmExtra) | ||
| 33 | + { | ||
| 34 | + int32_t wsStride = 2 * cfg_->kDim; | ||
| 35 | + if (cfg_->padOn) { | ||
| 36 | + cvt_->ZeroGmRows(gmAc, cfg_->kDim, wsStride, wsStride); | ||
| 37 | + } | ||
| 38 | + float signIm = cfg_->conjA ? -1.0f : 1.0f; | ||
| 39 | + CopyADirectAoS(gmA, gmAc, wsStride, signIm); | ||
| 40 | + if (cfg_->padOn) { | ||
| 41 | + PadIdentityRowsAoS(gmAc, wsStride); | ||
| 42 | + } | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + // 将AoS工作空间逐行清零已提取到 CtrsmConvert::ZeroGmRows | ||
| 46 | + | ||
| 47 | + // 直接复制A矩阵AoS到workspace(不转置),可选共轭翻转虚部 | ||
| 48 | + __aicore__ inline void CopyADirectAoS(__gm__ float* gmA, __gm__ float* gmAc, | ||
| 49 | + int32_t wsStride, float signIm) | ||
| 50 | + { | ||
| 51 | + int32_t kDimOrig = cfg_->kDimOrig, kDim = cfg_->kDim; | ||
| 52 | + AscendC::GlobalTensor<float> gA, gAc; | ||
| 53 | + gA.SetGlobalBuffer(gmA, (uint32_t)((int64_t)kDimOrig * cfg_->td->lda * 2)); | ||
| 54 | + gAc.SetGlobalBuffer(gmAc, (uint32_t)((int64_t)kDim * wsStride)); | ||
| 55 | + int32_t srcRowFloats = kDimOrig * 2; | ||
| 56 | + int32_t srcRowAligned = CEIL_ALIGN(srcRowFloats, FLOAT_ALIGN); // = slice UB 步长 | ||
| 57 | + int32_t batchRows = cfg_->srcBufFloats / srcRowAligned; | ||
| 58 | + if (batchRows > kDimOrig) batchRows = kDimOrig; | ||
| 59 | + if (batchRows < 1) batchRows = 1; | ||
| 60 | + uint32_t srcStrideBytes = (uint32_t)((cfg_->td->lda * 2 - srcRowFloats) * (int32_t)sizeof(float)); | ||
| 61 | + if (signIm == 1.0f) { | ||
| 62 | + CopyDirectPlain(gA, gAc, wsStride, srcRowFloats, srcRowAligned, batchRows, srcStrideBytes); | ||
| 63 | + } else { | ||
| 64 | + CopyDirectConj(gA, gAc, wsStride, srcRowFloats, srcRowAligned, batchRows, srcStrideBytes); | ||
| 65 | + } | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + // 纯拷贝路径:批量载入 → 批量写回 | ||
| 69 | + __aicore__ inline void CopyDirectPlain(AscendC::GlobalTensor<float>& gA, | ||
| 70 | + AscendC::GlobalTensor<float>& gAc, int32_t wsStride, int32_t srcRowFloats, | ||
| 71 | + int32_t srcRowAligned, int32_t batchRows, uint32_t srcStrideBytes) | ||
| 72 | + { | ||
| 73 | + int32_t kDimOrig = cfg_->kDimOrig; | ||
| 74 | + AscendC::LocalTensor<float> ubTmp = cfg_->bufPanelB_real->Get<float>(); | ||
| 75 | + uint32_t ubGap = (uint32_t)(((srcRowAligned - srcRowFloats) * (int32_t)sizeof(float)) / 32); | ||
| 76 | + uint32_t gmGap = (uint32_t)((wsStride - srcRowFloats) * (int32_t)sizeof(float)); | ||
| 77 | + for (int32_t bStart = 0; bStart < kDimOrig; bStart += batchRows) { | ||
| 78 | + int32_t bCount = (batchRows < kDimOrig - bStart) ? batchRows : (kDimOrig - bStart); | ||
| 79 | + BatchLoadRows(gA, ubTmp, bStart, bCount, srcRowFloats, srcStrideBytes); | ||
| 80 | + AscendC::PipeBarrier<PIPE_ALL>(); | ||
| 81 | + AscendC::DataCopyExtParams wbP((uint16_t)bCount, | ||
| 82 | + (uint32_t)(srcRowFloats * sizeof(float)), ubGap, gmGap, 0); | ||
| 83 | + AscendC::DataCopyPad(gAc[(int64_t)bStart * wsStride], ubTmp, wbP); | ||
| 84 | + AscendC::PipeBarrier<PIPE_ALL>(); | ||
| 85 | + } | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + // 共轭路径:构建 conjMask → 批量载入 → 各行独立 Mul → 各行独立写回 | ||
| 89 | + __aicore__ inline void CopyDirectConj(AscendC::GlobalTensor<float>& gA, | ||
| 90 | + AscendC::GlobalTensor<float>& gAc, int32_t wsStride, int32_t srcRowFloats, | ||
| 91 | + int32_t srcRowAligned, int32_t batchRows, uint32_t srcStrideBytes) | ||
| 92 | + { | ||
| 93 | + int32_t kDimOrig = cfg_->kDimOrig; | ||
| 94 | + AscendC::LocalTensor<float> ubSrc = cfg_->bufPanelB_real->Get<float>(); | ||
| 95 | + AscendC::LocalTensor<float> conjMask = cfg_->bufNeg_imag_neg->Get<float>(); | ||
| 96 | + for (int32_t j = 0; j < FLOAT_ALIGN / 2; j++) { | ||
| 97 | + conjMask.SetValue(2 * j, 1.0f); | ||
| 98 | + conjMask.SetValue(2 * j + 1, -1.0f); | ||
| 99 | + } | ||
| 100 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 101 | + for (int32_t c = FLOAT_ALIGN; c < srcRowAligned; c += FLOAT_ALIGN) { | ||
| 102 | + AscendC::DataCopy(conjMask[c], conjMask, FLOAT_ALIGN); | ||
| 103 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 104 | + } | ||
| 105 | + for (int32_t bStart = 0; bStart < kDimOrig; bStart += batchRows) { | ||
| 106 | + int32_t bCount = (batchRows < kDimOrig - bStart) ? batchRows : (kDimOrig - bStart); | ||
| 107 | + BatchLoadRows(gA, ubSrc, bStart, bCount, srcRowFloats, srcStrideBytes); | ||
| 108 | + AscendC::PipeBarrier<PIPE_ALL>(); | ||
| 109 | + for (int32_t j = 0; j < bCount; j++) { | ||
| 110 | + AscendC::Mul(ubSrc[j * srcRowAligned], ubSrc[j * srcRowAligned], conjMask, srcRowAligned); | ||
| 111 | + } | ||
| 112 | + AscendC::PipeBarrier<PIPE_ALL>(); | ||
| 113 | + uint32_t ubGap = (uint32_t)(((srcRowAligned - srcRowFloats) * (int32_t)sizeof(float)) / 32); | ||
| 114 | + uint32_t gmGap = (uint32_t)((wsStride - srcRowFloats) * (int32_t)sizeof(float)); | ||
| 115 | + AscendC::DataCopyExtParams wbP((uint16_t)bCount, | ||
| 116 | + (uint32_t)(srcRowFloats * sizeof(float)), ubGap, gmGap, 0); | ||
| 117 | + AscendC::DataCopyPad(gAc[(int64_t)bStart * wsStride], ubSrc, wbP); | ||
| 118 | + AscendC::PipeBarrier<PIPE_ALL>(); | ||
| 119 | + } | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + // 多行批量载入 A 的 AoS 行到 UB(dstStride=0 自动 32B 对齐打包,slice 步长 = srcRowAligned) | ||
| 123 | + __aicore__ inline void BatchLoadRows(AscendC::GlobalTensor<float>& gA, | ||
| 124 | + AscendC::LocalTensor<float>& ubDst, int32_t bStart, int32_t bCount, | ||
| 125 | + int32_t srcRowFloats, uint32_t srcStrideBytes) | ||
| 126 | + { | ||
| 127 | + if (bCount > 1) { | ||
| 128 | + AscendC::DataCopyExtParams rBatch((uint16_t)bCount, | ||
| 129 | + (uint32_t)(srcRowFloats * sizeof(float)), srcStrideBytes, 0, 0); | ||
| 130 | + AscendC::DataCopyPad(ubDst, gA[(int64_t)bStart * cfg_->td->lda * 2], rBatch, {false, 0, 0, 0}); | ||
| 131 | + } else { | ||
| 132 | + AscendC::DataCopyExtParams rRow(1, (uint32_t)(srcRowFloats * sizeof(float)), 0, 0, 0); | ||
| 133 | + AscendC::DataCopyPad(ubDst, gA[(int64_t)bStart * cfg_->td->lda * 2], rRow, {false, 0, 0, 0}); | ||
| 134 | + } | ||
| 135 | + } | ||
| 136 | + | ||
| 137 | + // 对补零行填充单位对角线(real=1.0, imag=0.0) | ||
| 138 | + __aicore__ inline void PadIdentityRowsAoS(__gm__ float* gmAc, int32_t wsStride) | ||
| 139 | + { | ||
| 140 | + AscendC::LocalTensor<float> ub = cfg_->bufRow->Get<float>(); | ||
| 141 | + AscendC::GlobalTensor<float> gAc; | ||
| 142 | + gAc.SetGlobalBuffer(gmAc, (uint32_t)((int64_t)cfg_->kDim * wsStride)); | ||
| 143 | + cvt_->PadDiagonalIdentity(gAc, ub, cfg_->kDimOrig, cfg_->kDim, wsStride); | ||
| 144 | + } | ||
| 145 | + | ||
| 146 | +private: | ||
| 147 | + CtrsmAivCfg* cfg_; | ||
| 148 | + CtrsmConvert* cvt_; | ||
| 149 | +}; | ||
| @@ -0,0 +1,318 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +/*! | ||
| 12 | + * \file ctrsm_batched_kernel_aiv_canon_b.h | ||
| 13 | + * \brief B 矩阵规范化与回写器(按左右乘模板化):AoS->SoA 构建、alpha 缩放, | ||
| 14 | + * 以及求解结果回写(Left 逐面板行回写 / Right 转置后整体交织回写)。 | ||
| 15 | + */ | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | +template <bool RIGHT> | ||
| 23 | +class CtrsmCanonB { | ||
| 24 | +public: | ||
| 25 | + __aicore__ inline CtrsmCanonB() {} | ||
| 26 | + | ||
| 27 | + __aicore__ inline void Bind(CtrsmAivCfg* cfg, CtrsmConvert* cvt) { cfg_ = cfg; cvt_ = cvt; } | ||
| 28 | + | ||
| 29 | + // 构建补零后的B矩阵SoA工作区:清零→解交织→alpha缩放(按buildRowStart/End分行) | ||
| 30 | + __aicore__ inline void BuildPaddedB(__gm__ float* gmB, | ||
| 31 | + __gm__ float* gmBc_real, __gm__ float* gmBc_imag, | ||
| 32 | + __gm__ float* gmTemp) | ||
| 33 | + { | ||
| 34 | + int32_t nColsAligned = cfg_->nColsAligned; | ||
| 35 | + if (cfg_->padOn) { | ||
| 36 | + cvt_->ZeroGmRows(gmBc_real + (int64_t)cfg_->buildRowStart * nColsAligned, | ||
| 37 | + cfg_->buildRowEnd - cfg_->buildRowStart, nColsAligned, nColsAligned); | ||
| 38 | + cvt_->ZeroGmRows(gmBc_imag + (int64_t)cfg_->buildRowStart * nColsAligned, | ||
| 39 | + cfg_->buildRowEnd - cfg_->buildRowStart, nColsAligned, nColsAligned); | ||
| 40 | + } | ||
| 41 | + if (!RIGHT) { | ||
| 42 | + DeinterleaveBLeft(gmB, gmBc_real, gmBc_imag); | ||
| 43 | + } else { | ||
| 44 | + DeinterleaveBRight(gmB, gmBc_real, gmBc_imag, gmTemp); | ||
| 45 | + } | ||
| 46 | + float aRe = cfg_->td->alphaReal; | ||
| 47 | + float aIm = cfg_->td->alphaImag; | ||
| 48 | + if (aRe != 1.0f || aIm != 0.0f) { | ||
| 49 | + AscendC::PipeBarrier<PIPE_ALL>(); | ||
| 50 | + AlphaScale(gmBc_real, gmBc_imag, nColsAligned, aRe, aIm); | ||
| 51 | + } | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + // 将SoA结果写回原始AoS格式的B矩阵(仅Right模式调用) | ||
| 55 | + // rowBeg/rowEnd 限定输出行范围(dual-AIV 两核各写一半) | ||
| 56 | + __aicore__ inline void WriteBackPaddedB(__gm__ float* gmBcR, __gm__ float* gmBcI, | ||
| 57 | + __gm__ float* gmB, __gm__ float* gmTemp, | ||
| 58 | + int32_t rowBeg, int32_t rowEnd) | ||
| 59 | + { | ||
| 60 | + InterleaveBRight(gmBcR, gmBcI, gmB, gmTemp, rowBeg, rowEnd); | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + // Right dual 前端阶段1:清零本核 gmBc 行段(buildRow) + 解交织 [tBeg,tEnd) 行到 temp | ||
| 64 | + __aicore__ inline void BuildBRightPhase1(__gm__ float* gmB, | ||
| 65 | + __gm__ float* gmBc_real, __gm__ float* gmBc_imag, __gm__ float* gmTemp, | ||
| 66 | + int32_t tBeg, int32_t tEnd) | ||
| 67 | + { | ||
| 68 | + int32_t nColsAligned = cfg_->nColsAligned; | ||
| 69 | + if (cfg_->padOn) { | ||
| 70 | + cvt_->ZeroGmRows(gmBc_real + (int64_t)cfg_->buildRowStart * nColsAligned, | ||
| 71 | + cfg_->buildRowEnd - cfg_->buildRowStart, nColsAligned, nColsAligned); | ||
| 72 | + cvt_->ZeroGmRows(gmBc_imag + (int64_t)cfg_->buildRowStart * nColsAligned, | ||
| 73 | + cfg_->buildRowEnd - cfg_->buildRowStart, nColsAligned, nColsAligned); | ||
| 74 | + } | ||
| 75 | + DeinterleaveBRightToTemp(gmB, gmTemp, tBeg, tEnd); | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + // Right dual 前端阶段2:转置 temp→gmBc 本核输出行段 [cbBeg,cbEnd) + alpha 缩放本核行段 | ||
| 79 | + __aicore__ inline void BuildBRightPhase2(__gm__ float* gmBc_real, __gm__ float* gmBc_imag, | ||
| 80 | + __gm__ float* gmTemp, int32_t cbBeg, int32_t cbEnd) | ||
| 81 | + { | ||
| 82 | + TransposeBTempToBc(gmBc_real, gmBc_imag, gmTemp, cbBeg, cbEnd); | ||
| 83 | + float aRe = cfg_->td->alphaReal; | ||
| 84 | + float aIm = cfg_->td->alphaImag; | ||
| 85 | + if (aRe != 1.0f || aIm != 0.0f) { | ||
| 86 | + AlphaScale(gmBc_real, gmBc_imag, cfg_->nColsAligned, aRe, aIm); | ||
| 87 | + } | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + // 仅 alpha 缩放(buildRowStart/End 已在外部设置) | ||
| 91 | + __aicore__ inline void BuildBRightPhase2Alpha(__gm__ float* gmBc_real, __gm__ float* gmBc_imag, | ||
| 92 | + int32_t effLdb, float aRe, float aIm) | ||
| 93 | + { | ||
| 94 | + AlphaScale(gmBc_real, gmBc_imag, effLdb, aRe, aIm); | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | + // 将已求解的nb行从SoA数据交织回写到用户B矩阵(Left模式逐面板回写) | ||
| 98 | + // 单列分块时直接从 UB 读取(省 MTE2),多列分块退回 GM 搬入 | ||
| 99 | + __aicore__ inline void WriteBackPanelRows(__gm__ float* gmBcR, __gm__ float* gmBcI, | ||
| 100 | + __gm__ float* gmB, | ||
| 101 | + int32_t panelStart, int32_t actualNb) | ||
| 102 | + { | ||
| 103 | + int32_t nColsAligned = cfg_->nColsAligned; | ||
| 104 | + int32_t mOrig = cfg_->td->m, nOrig = cfg_->td->n; | ||
| 105 | + int32_t endRow = panelStart + actualNb; | ||
| 106 | + if (endRow > mOrig) endRow = mOrig; | ||
| 107 | + int32_t localNCols = cfg_->localNCols; | ||
| 108 | + int32_t clipEnd = (localNCols < nOrig) ? localNCols : nOrig; | ||
| 109 | + int32_t wbColStart = (cfg_->colStart < clipEnd) ? cfg_->colStart : clipEnd; | ||
| 110 | + int32_t wbColEnd = (cfg_->colEnd < clipEnd) ? cfg_->colEnd : clipEnd; | ||
| 111 | + int32_t wbCount = wbColEnd - wbColStart; | ||
| 112 | + if (wbCount <= 0) return; | ||
| 113 | + int32_t gmBColStart = wbColStart + cfg_->nColsOffset; | ||
| 114 | + if (cfg_->colTile >= nColsAligned) { | ||
| 115 | + WriteBackPanelRowsFromUB(gmB, panelStart, endRow, gmBColStart, wbCount); | ||
| 116 | + } else { | ||
| 117 | + WriteBackPanelRowsFromGM(gmBcR, gmBcI, gmB, panelStart, endRow, wbColStart, wbCount, gmBColStart); | ||
| 118 | + } | ||
| 119 | + } | ||
| 120 | + | ||
| 121 | + // 单列分块:直接从 UB 已有的 ubBR/ubBI 读取,批量交织后 1 条 strided DMA 写出 | ||
| 122 | + __aicore__ inline void WriteBackPanelRowsFromUB(__gm__ float* gmB, | ||
| 123 | + int32_t panelStart, int32_t endRow, int32_t wbColStart, int32_t wbCount) | ||
| 124 | + { | ||
| 125 | + int32_t mOrig = cfg_->td->m; | ||
| 126 | + int32_t wbCountA = CEIL_ALIGN(wbCount, FLOAT_ALIGN); | ||
| 127 | + AscendC::LocalTensor<float> ubBR = cfg_->bufPanelB_imag->Get<float>(); | ||
| 128 | + AscendC::LocalTensor<float> ubBI = cfg_->bufNeg_imag->Get<float>(); | ||
| 129 | + AscendC::LocalTensor<float> ubR = cfg_->bufPanelB_real->Get<float>(); | ||
| 130 | + AscendC::LocalTensor<float> ub = cfg_->bufRow->Get<float>(); | ||
| 131 | + int32_t rowCount = endRow - panelStart; | ||
| 132 | + AscendC::DataCopy(ubR, ubBI, rowCount * wbCountA); | ||
| 133 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 134 | + cvt_->BuildInterleaveOffsets(wbCount); | ||
| 135 | + AscendC::LocalTensor<int32_t> offInter = cfg_->bufNeg_imag->Get<int32_t>(); | ||
| 136 | + // 批量交织:16 行全部 InterleaveRow 到 bufNeg_real(作为连续大 buffer 使用) | ||
| 137 | + // bufNeg_real 大小 = nb*colTile = 1024f,需要 rowCount*wbCount*2 = 16*128 = 2048f | ||
| 138 | + // 不够!改用 bufPanelB_real 的后半段(4096f 总量,前 rowCount*wbCountA 已被 ubR 占) | ||
| 139 | + // ubR 占 rowCount*wbCountA = 16*64 = 1024f,bufPanelB_real 剩余 4096-1024 = 3072f >= 2048f ✓ | ||
| 140 | + int32_t outRowFloats = wbCount * 2; | ||
| 141 | + int32_t outRowAligned = CEIL_ALIGN(outRowFloats, FLOAT_ALIGN); | ||
| 142 | + AscendC::LocalTensor<float> ubOutAll = cfg_->bufPanelB_real->Get<float>(); | ||
| 143 | + int32_t outBase = rowCount * wbCountA; // ubR 占用的尾部之后 | ||
| 144 | + AscendC::LocalTensor<float> rowReal = cfg_->bufNeg_imag_neg->Get<float>(); | ||
| 145 | + for (int32_t i = 0; i < rowCount; i++) { | ||
| 146 | + int32_t rowUbOff = i * wbCountA; | ||
| 147 | + AscendC::DataCopy(rowReal, ubBR[rowUbOff], wbCountA); | ||
| 148 | + AscendC::DataCopy(ub, ubR[rowUbOff], wbCountA); | ||
| 149 | + AscendC::LocalTensor<float> ubOutRow = ubOutAll[outBase + i * outRowAligned]; | ||
| 150 | + cvt_->InterleaveRow(rowReal, ub, ubOutRow, offInter, wbCount); | ||
| 151 | + } | ||
| 152 | + // 统一 strided DMA 写出 | ||
| 153 | + AscendC::GlobalTensor<float> gB; | ||
| 154 | + gB.SetGlobalBuffer(gmB, (uint32_t)((int64_t)mOrig * cfg_->td->ldb * 2)); | ||
| 155 | + int64_t gbOff = (int64_t)panelStart * cfg_->td->ldb * 2 + wbColStart * 2; | ||
| 156 | + uint32_t ubOutGap32B = (uint32_t)(((outRowAligned - outRowFloats) * sizeof(float)) / 32); | ||
| 157 | + uint32_t gmGapBytes = (uint32_t)((cfg_->td->ldb * 2 - outRowFloats) * sizeof(float)); | ||
| 158 | + AscendC::SetFlag<AscendC::HardEvent::V_MTE3>(0); | ||
| 159 | + AscendC::WaitFlag<AscendC::HardEvent::V_MTE3>(0); | ||
| 160 | + if (((outRowAligned - outRowFloats) * (int32_t)sizeof(float)) % 32 == 0) { | ||
| 161 | + AscendC::DataCopyExtParams wbOut((uint16_t)rowCount, | ||
| 162 | + (uint32_t)(outRowFloats * sizeof(float)), ubOutGap32B, gmGapBytes, 0); | ||
| 163 | + AscendC::DataCopyPad(gB[gbOff], ubOutAll[outBase], wbOut); | ||
| 164 | + } else { | ||
| 165 | + AscendC::DataCopyExtParams wbOut(1, (uint32_t)(outRowFloats * sizeof(float)), 0, 0, 0); | ||
| 166 | + for (int32_t i = 0; i < rowCount; i++) { | ||
| 167 | + AscendC::DataCopyPad(gB[gbOff], ubOutAll[outBase + i * outRowAligned], wbOut); | ||
| 168 | + gbOff += cfg_->td->ldb * 2; | ||
| 169 | + } | ||
| 170 | + } | ||
| 171 | + AscendC::PipeBarrier<PIPE_ALL>(); | ||
| 172 | + } | ||
| 173 | + | ||
| 174 | + // 多列分块:从 GM (gmBc) 搬入 SoA 数据再交织写出 | ||
| 175 | + // 当 wbCount 超出 UB 容量时按列分 chunk 处理 | ||
| 176 | + __aicore__ inline void WriteBackPanelRowsFromGM(__gm__ float* gmBcR, __gm__ float* gmBcI, | ||
| 177 | + __gm__ float* gmB, int32_t panelStart, int32_t endRow, | ||
| 178 | + int32_t wbColStart, int32_t wbCount, int32_t gmBColStart) | ||
| 179 | + { | ||
| 180 | + int32_t kDim = cfg_->kDim, nColsAligned = cfg_->nColsAligned; | ||
| 181 | + int32_t mOrig = cfg_->td->m; | ||
| 182 | + AscendC::LocalTensor<float> ub = cfg_->bufRow->Get<float>(); | ||
| 183 | + AscendC::LocalTensor<float> ubR = cfg_->bufPanelB_real->Get<float>(); | ||
| 184 | + AscendC::LocalTensor<float> ubOut = cfg_->bufNeg_real->Get<float>(); | ||
| 185 | + AscendC::GlobalTensor<float> gBcR, gBcI, gB; | ||
| 186 | + gBcR.SetGlobalBuffer(gmBcR, (uint32_t)((int64_t)kDim * nColsAligned)); | ||
| 187 | + gBcI.SetGlobalBuffer(gmBcI, (uint32_t)((int64_t)kDim * nColsAligned)); | ||
| 188 | + gB.SetGlobalBuffer(gmB, (uint32_t)((int64_t)mOrig * cfg_->td->ldb * 2)); | ||
| 189 | + constexpr int32_t EVT_ID = 0; | ||
| 190 | + int32_t ldbStride = cfg_->td->ldb * 2; | ||
| 191 | + | ||
| 192 | + // InterleaveRow 需要: ubR 容量 >= 2*countA, ubOut 容量 >= 2*countA | ||
| 193 | + // countA = CEIL_ALIGN(chunkCols, FLOAT_ALIGN) | ||
| 194 | + // ubR = bufPanelB_real (srcBufFloats), ubOut = bufNeg_real (nb*colTile) | ||
| 195 | + int32_t maxColsR = cfg_->srcBufFloats / 2; | ||
| 196 | + int32_t maxColsOut = cfg_->nb * cfg_->colTile / 2; | ||
| 197 | + int32_t maxChunkCols = (maxColsR < maxColsOut) ? maxColsR : maxColsOut; | ||
| 198 | + maxChunkCols = (maxChunkCols / FLOAT_ALIGN) * FLOAT_ALIGN; | ||
| 199 | + if (maxChunkCols < FLOAT_ALIGN) maxChunkCols = FLOAT_ALIGN; | ||
| 200 | + | ||
| 201 | + for (int32_t cs = 0; cs < wbCount; cs += maxChunkCols) { | ||
| 202 | + int32_t chunkCols = (maxChunkCols < wbCount - cs) ? maxChunkCols : (wbCount - cs); | ||
| 203 | + cvt_->BuildInterleaveOffsets(chunkCols); | ||
| 204 | + AscendC::LocalTensor<int32_t> offInter = cfg_->bufNeg_imag->Get<int32_t>(); | ||
| 205 | + int64_t gbOff = (int64_t)panelStart * ldbStride + (gmBColStart + cs) * 2; | ||
| 206 | + int64_t bcOff = (int64_t)panelStart * nColsAligned + wbColStart + cs; | ||
| 207 | + for (int32_t i = panelStart; i < endRow; i++) { | ||
| 208 | + AscendC::DataCopyPad(ubR, gBcR[bcOff], | ||
| 209 | + {1, (uint32_t)(chunkCols * sizeof(float)), 0, 0, 0}, {false, 0, 0, 0}); | ||
| 210 | + AscendC::DataCopyPad(ub, gBcI[bcOff], | ||
| 211 | + {1, (uint32_t)(chunkCols * sizeof(float)), 0, 0, 0}, {false, 0, 0, 0}); | ||
| 212 | + AscendC::SetFlag<AscendC::HardEvent::MTE2_V>(EVT_ID); | ||
| 213 | + AscendC::WaitFlag<AscendC::HardEvent::MTE2_V>(EVT_ID); | ||
| 214 | + if (i > panelStart) { | ||
| 215 | + AscendC::WaitFlag<AscendC::HardEvent::MTE3_V>(EVT_ID); | ||
| 216 | + } | ||
| 217 | + cvt_->InterleaveRow(ubR, ub, ubOut, offInter, chunkCols); | ||
| 218 | + AscendC::SetFlag<AscendC::HardEvent::V_MTE3>(EVT_ID); | ||
| 219 | + AscendC::WaitFlag<AscendC::HardEvent::V_MTE3>(EVT_ID); | ||
| 220 | + AscendC::DataCopyPad(gB[gbOff], ubOut, | ||
| 221 | + {1, (uint32_t)(chunkCols * 2 * sizeof(float)), 0, 0, 0}); | ||
| 222 | + AscendC::SetFlag<AscendC::HardEvent::MTE3_V>(EVT_ID); | ||
| 223 | + gbOff += ldbStride; | ||
| 224 | + bcOff += nColsAligned; | ||
| 225 | + } | ||
| 226 | + AscendC::WaitFlag<AscendC::HardEvent::MTE3_V>(EVT_ID); | ||
| 227 | + } | ||
| 228 | + } | ||
| 229 | + | ||
| 230 | +private: | ||
| 231 | + // 将SoA工作空间逐行清零已提取到 CtrsmConvert::ZeroGmRows | ||
| 232 | + | ||
| 233 | + // Deinterleave helper methods split to separate file | ||
| 234 | + | ||
| 235 | + | ||
| 236 | + // 阶段2:将temp转置到gmBc工作区,仅产出[cbBeg,cbEnd)输出行(=temp列,dual两核各转一段) | ||
| 237 | + __aicore__ inline void TransposeBTempToBc(__gm__ float* gmBcR, __gm__ float* gmBcI, | ||
| 238 | + __gm__ float* gmTemp, int32_t cbBeg, int32_t cbEnd) | ||
| 239 | + { | ||
| 240 | + int32_t kDim = cfg_->kDim, kDimOrig = cfg_->kDimOrig; | ||
| 241 | + int32_t nColsAligned = cfg_->nColsAligned, nColsOrig = cfg_->nColsOrig; | ||
| 242 | + if (cbEnd > kDimOrig) cbEnd = kDimOrig; | ||
| 243 | + if (cbBeg < 0) cbBeg = 0; | ||
| 244 | + if (cbBeg >= cbEnd) return; | ||
| 245 | + __gm__ float* tempR = gmTemp; | ||
| 246 | + __gm__ float* tempI = gmTemp + (int64_t)nColsOrig * kDim; | ||
| 247 | + cvt_->TiledTransposePair(tempR, tempI, nColsOrig, kDimOrig, kDim, gmBcR, gmBcI, nColsAligned, | ||
| 248 | + cbBeg, cbEnd); | ||
| 249 | + } | ||
| 250 | + | ||
| 251 | + // 对B矩阵乘以复数alpha系数(按buildRow范围分行处理) | ||
| 252 | + __aicore__ inline void AlphaScale(__gm__ float* gmBcR, __gm__ float* gmBcI, | ||
| 253 | + int32_t effLdb, float aRe, float aIm) | ||
| 254 | + { | ||
| 255 | + int32_t kDim = cfg_->kDim, nColsAligned = cfg_->nColsAligned, colTile = cfg_->colTile; | ||
| 256 | + AscendC::LocalTensor<float> ubR = cfg_->bufPanelB_real->Get<float>(); | ||
| 257 | + AscendC::LocalTensor<float> ubI = cfg_->bufPanelB_imag->Get<float>(); | ||
| 258 | + AscendC::LocalTensor<float> ubTmp = cfg_->bufRankK->Get<float>(); | ||
| 259 | + AscendC::GlobalTensor<float> gR, gI; | ||
| 260 | + gR.SetGlobalBuffer(gmBcR, (uint32_t)((int64_t)kDim * effLdb)); | ||
| 261 | + gI.SetGlobalBuffer(gmBcI, (uint32_t)((int64_t)kDim * effLdb)); | ||
| 262 | + int32_t ct = (colTile < nColsAligned) ? colTile : nColsAligned; | ||
| 263 | + for (int32_t i = cfg_->buildRowStart; i < cfg_->buildRowEnd; i++) { | ||
| 264 | + for (int32_t cs = 0; cs < nColsAligned; cs += ct) { | ||
| 265 | + AlphaScaleChunk(gR, gI, ubR, ubI, ubTmp, effLdb, i, cs, ct, aRe, aIm); | ||
| 266 | + } | ||
| 267 | + } | ||
| 268 | + } | ||
| 269 | + | ||
| 270 | + // 对一个分块执行复数alpha缩放:newR = aRe*R - aIm*I, newI = aRe*I + aIm*R | ||
| 271 | + __aicore__ inline void AlphaScaleChunk( | ||
| 272 | + AscendC::GlobalTensor<float>& gR, AscendC::GlobalTensor<float>& gI, | ||
| 273 | + AscendC::LocalTensor<float>& ubR, AscendC::LocalTensor<float>& ubI, | ||
| 274 | + AscendC::LocalTensor<float>& ubTmp, | ||
| 275 | + int32_t effLdb, int32_t row, int32_t cs, int32_t ct, float aRe, float aIm) | ||
| 276 | + { | ||
| 277 | + int32_t nColsAligned = cfg_->nColsAligned; | ||
| 278 | + int32_t cw = (cs + ct <= nColsAligned) ? ct : (nColsAligned - cs); | ||
| 279 | + int32_t cwA = CEIL_ALIGN(cw, FLOAT_ALIGN); | ||
| 280 | + AscendC::DataCopyExtParams rp(1, (uint32_t)(cw * sizeof(float)), 0, 0, 0); | ||
| 281 | + AscendC::DataCopyPadExtParams<float> pad{false, 0, 0, 0}; | ||
| 282 | + AscendC::DataCopyPad(ubR, gR[(int64_t)row * effLdb + cs], rp, pad); | ||
| 283 | + AscendC::DataCopyPad(ubI, gI[(int64_t)row * effLdb + cs], rp, pad); | ||
| 284 | + AscendC::PipeBarrier<PIPE_ALL>(); | ||
| 285 | + AscendC::Muls(ubTmp, ubR, aRe, cwA); | ||
| 286 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 287 | + AscendC::Axpy(ubTmp, ubI, -aIm, cwA); | ||
| 288 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 289 | + AscendC::Muls(ubI, ubI, aRe, cwA); | ||
| 290 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 291 | + AscendC::Axpy(ubI, ubR, aIm, cwA); | ||
| 292 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 293 | + AscendC::DataCopy(ubR, ubTmp, cwA); | ||
| 294 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 295 | + AscendC::DataCopyPad(gR[(int64_t)row * effLdb + cs], ubR, rp); | ||
| 296 | + AscendC::DataCopyPad(gI[(int64_t)row * effLdb + cs], ubI, rp); | ||
| 297 | + AscendC::PipeBarrier<PIPE_ALL>(); | ||
| 298 | + } | ||
| 299 | + | ||
| 300 | + // 右侧模式回写:单 pass SoA→AoS 转置直接写回 B(替代 TiledTransposePair + 逐行 Interleave) | ||
| 301 | + __aicore__ inline void InterleaveBRight(__gm__ float* gmBcR, __gm__ float* gmBcI, | ||
| 302 | + __gm__ float* gmB, __gm__ float* gmTemp, | ||
| 303 | + int32_t rowBeg, int32_t rowEnd) | ||
| 304 | + { | ||
| 305 | + int32_t kDimOrig = cfg_->kDimOrig; | ||
| 306 | + int32_t nColsAligned = cfg_->nColsAligned, nColsOrig = cfg_->nColsOrig; | ||
| 307 | + int32_t mOrig = cfg_->td->m; | ||
| 308 | + if (rowBeg < 0) rowBeg = 0; | ||
| 309 | + if (rowEnd > mOrig) rowEnd = mOrig; | ||
| 310 | + if (rowBeg >= rowEnd) return; | ||
| 311 | + int32_t ldb2 = cfg_->td->ldb * 2; | ||
| 312 | + cvt_->TransposeSoADirectToAoS(gmBcR, gmBcI, kDimOrig, nColsOrig, nColsAligned, | ||
| 313 | + gmB, ldb2, rowBeg, rowEnd); | ||
| 314 | + } | ||
| 315 | + | ||
| 316 | + CtrsmAivCfg* cfg_; | ||
| 317 | + CtrsmConvert* cvt_; | ||
| 318 | +}; | ||
【openlibing.ci】检测到当前PR中存在代码检查告警抑制 2 处,详情见下表,请Committer检视合理性。 / Detected 2 code check alert suppression(s) in this PR, see table below. Committers please review.
run_full_test.py
from run_full_test_common import Harness, write_config # noqa: E402run_full_test.py
from run_full_test_common import Harness, write_config # noqa: E402