# 昇腾算子之张量与向量乘法 **Repository Path**: cluo29/ColonywiseScale ## Basic Information - **Project Name**: 昇腾算子之张量与向量乘法 - **Description**: 昇腾算子之张量与向量乘法 - **Primary Language**: Unknown - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-19 - **Last Updated**: 2026-08-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 昇腾算子之张量与向量乘法 ## 开发者 https://gitee.com/Nicet 大湾区大学信息科学技术学院,胡人 大湾区大学信息科学技术学院,罗除,https://gitee.com/cluo29 ## 课题承担方 大湾区大学信息科学技术学院,罗除,https://gitee.com/cluo29 ## 课题委托方 人工智能与数字经济广东省实验室(深圳) ## 项目支撑 由人工智能与数字经济广东省实验室(深圳) 开放课题资助(编号:GML-KF-24-01) This research was financially supported by the Open Research Fund from Guangdong Laboratory of Artificial Intelligence and Digital Economy (SZ), under Grant No.GML-KF-24-01. ## 论文文献 Hu, R., & Luo, C. (2026). Modeling and Applying Tree-Like Path Planning of Multiple Ant Colonies. Proceedings of the Annual Meeting of the Cognitive Science Society, 48. Retrieved from https://escholarship.org/uc/item/5843n9h5 ## ColonywiseScale AscendC 算子 实现了 `ColonywiseScale` 算子,对应蚁群算法(ACO)中的信息素保有率乘法操作。 一组相同大小的矩阵(colony维度)分别乘以各自对应的保有率系数 rho(retention rate), 其中 evaporation_rate + retention_rate = 1。 ## 算子定义 ``` Y[i1,...,im,...,iN] = coeff[im] * X[i1,...,im,...,iN] ``` | 项目 | 说明 | |------|------| | 输入 X | 任意维度浮点张量 (float32) | | 输入 coeff | 1D 系数向量,长度 = X.shape[colony_dim] | | 属性 colony_dim | 指定 colony(蚁群)维度 | | 输出 Y | 与 X 同形状 | ## 目标芯片与验证环境 | 项目 | 值 | |------|------| | 目标芯片 | Ascend 310B(1 vector核 + 1 cube核) | | 验证环境 | Ascend 910_93 | | 开发策略 | 按 310B 单核逻辑实现,在 910_93 上编译验证 | | 工具链 | msopgen + CANN 9.0.0 | ## 当前最优实现(v2 向量化 Muls) ### 核心思路 1. 将 coeff 一次性 DataCopy 到 UB(对齐到 8 个 float),仅一次 GM→UB 搬运 2. 按 (outer, k) 双层循环遍历每个 slice 3. 每 slice 从 UB 中标量读 `coeffLocal.GetValue(k)` 获取对应系数 4. slice 内部用 `Muls`(向量乘标量)分块处理,TILE_ELEMS=1024 ### 性能特征 | 指标 | 值 | |------|------| | 标量操作数 | O(K × outerSize) — 每 slice 仅 1 次 GetValue | | 向量操作数 | O(totalLen) — Muls 全向量化 | | 流水级 | MTE2 → Vector → MTE3 三级并行 | | Buffer 策略 | 双 buffer (BUFFER_NUM=2) 实现 DMA/计算重叠 | | Tile 大小 | 1024 floats = 4KB/tile | ### 关键代码路径 ``` LoadCoeff() → DataCopy coeff GM→UB (一次性) ↓ for outer, k: scalar = coeffLocal.GetValue(k) ← 唯一标量操作 ProcessSlice(offset, sliceSize, scalar): DataCopy xGm→xLocal ← MTE2 Muls(yLocal, xLocal, scalar) ← Vector DataCopy yLocal→yGm ← MTE3 ``` ### 文件列表 | 文件 | 说明 | |------|------| | `op_kernel/colonywise_scale.cpp` | 当前最优 kernel (v2) | | `op_kernel/colonywise_scale_v1_scalar.cpp` | 备份: v1 逐元素标量版 | | `op_kernel/colonywise_scale_v2_vectorized.cpp` | 备份: v2 向量化版(与当前一致) | | `op_kernel/colonywise_scale_tiling.h` | Tiling 结构定义 | | `op_host/colonywise_scale.cpp` | Host 端 tiling 计算 + 算子注册 | | `test_aclnn.cpp` | aclnn C++ 验证程序(3 个测试用例) | ## 方案演进历程 ### v1: 全局线性扫描 + 标量读 coeff(可行但慢) - 按 TILE_ELEMS=256 分块线性处理整个 tensor - 每个元素算 `(globalIdx / sliceSize) % K` 确定 coeff 索引 - 用 `coeffGm.GetValue(kIdx)` 逐元素从 GM 标量读取 - 构建 scalar tensor 后用 `Mul` 向量化 - **问题**: O(totalLen) 次 GM 标量读 + UB 标量写,开销大 ### v2: 向量化 Muls + coeff 预加载(当前采用) - coeff 预加载到 UB,避免重复 GM 读 - 按 slice 粒度处理,直接用 `Muls` 向量乘标量 - 标量操作降至 O(K × outerSize) - **提升**: 消除全部 GM 标量访问,向量化率接近 100% ### 失败方案: DataCopy coeff + 按 slice Muls(首次尝试) - DataCopy 要求 count 对齐到 8 float,小 K 时读越界 - 小 sliceSize 的 alignedLen 导致相邻 slice 写重叠 - **教训**: DataCopy 对齐是硬约束,不能简单 pad ## Cube 核 CV 融合分析 ### 结论:不适用于本算子 ### 原因分析 **数学层面** - 本算子是逐元素乘标量 (Hadamard 积特例) - Cube 做矩阵乘法: `C[i,j] = Σ_k A[i,k] * B[k,j]`,含求和降维 - 二者数学结构不同,无法高效映射 **尝试过的 matmul 映射** - `X @ diag(s*I_N)`: 计算量 O(N³) vs 向量 O(N²),增加 N 倍 - `scalar_expand @ X_reshape`: 变成列求和,语义错误 - `A=scalar(expand [1,K]), B=X_reshape[K,N]`: 做了 K 维求和,非逐元素乘 **硬件约束** - 910_93 (arch 3003) 及 310B (arch 3113): fp32 cube matmul 不支持 - 仅支持 fp16 → fp32 cube,需额外 Cast 操作 + 精度损失 - Cube 最小维度 K_mm ≥ 16 (fp16),无法做 K=1 标量乘 - `REGIST_MATMUL_OBJ` 编译时需 constexpr 有效 TCubeTiling 指针 - 实际编译报 `type 'half' cannot be used prior to '::'` 等模板实例化错误 **适合 CV 融合的真实场景** - 将 evaporation (Vector Muls) 与后续路径概率 matmul (Cube) 融合为单 kernel - Vector 核做信息素衰减,Cube 核做路径选择矩阵乘,二者流水并行 - 这是算法层面的算子融合,超出单个 ColonywiseScale 的范畴 ## 关键开发经验 | # | 经验 | 详情 | |---|------|------| | 1 | DataCopy 对齐 | count 必须 8 的倍数(float32) / 16 的倍数(fp16) | | 2 | Tiling 结构 | 用 `__attribute__((packed))` 普通 struct,无需 `BEGIN_TILING_DATA_DEF` 宏 | | 3 | REGISTER_TILING_DEFAULT | 必须在 kernel entry 内声明,否则 OPC 报 "do not registe tiling struct" | | 4 | Host 读取属性 | `context->GetAttrs()->GetAttrPointer(0)`,非 `GetAttr(0)->GetInt()` | | 5 | Host 写 tiling | `GetTilingData()` 获取指针直接写字段,无 `SetTilingData` 方法 | | 6 | AddConfig 芯片名 | 需与 CMakePresets 的 `ASCEND_COMPUTE_UNIT` 一致: `"ascend910_93"` | | 7 | 安装路径 | `--install-path` 绝对路径 + `ASCEND_CUSTOM_OPP_PATH` 环境变量 | | 8 | Cube 不适合逐元素乘 | Cube 做 GEMM 有求和降维,element-wise 只能用 Vector | ## 编译与验证 ```bash cd ColonywiseScale source /home/developer/Ascend/cann-9.0.0/set_env.sh # 编译 bash build.sh # 安装 bash build_out/custom_opp_ubuntu_aarch64.run --quiet \ --install-path=/mnt/workspace/gitCode/devops/myop/ColonywiseScale/opp_install # 编译测试 CANN=/home/developer/Ascend/cann-9.0.0 OPP=/mnt/workspace/gitCode/devops/myop/ColonywiseScale/opp_install g++ -std=c++17 -o test_aclnn test_aclnn.cpp \ -I${CANN}/include -I${OPP}/vendors/customize/op_api/include -I./build_out/autogen \ -L${CANN}/lib64 -L${OPP}/vendors/customize/op_api/lib \ -lascendcl -lnnopbase -lcust_opapi \ -Wl,-rpath,${CANN}/lib64:${OPP}/vendors/customize/op_api/lib # 运行 export ASCEND_CUSTOM_OPP_PATH=${OPP} source ${OPP}/vendors/customize/bin/set_env.bash ./test_aclnn ``` ## 验证结果 ``` [PASS] ColonywiseScale basic test (K=3, N=2, colony_dim=0) [PASS] ColonywiseScale colony_dim=1 [2,3,2,2] [PASS] Pheromone retention (ACO: rho=[0.9,0.8,0.7]) ```