已合并
add hostlaunch #60
bluesky901创建于 7月31日
add hostlaunch #60
已合并
bluesky901创建于 7月31日
共 21 个文件变更+4866-1
@@ -0,0 +1,51 @@
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+cmake_minimum_required(VERSION 3.16)
12+ 
13+project(asc_comm LANGUAGES C CXX)
14+ 
15+set(CMAKE_C_STANDARD 11)
16+set(CMAKE_C_STANDARD_REQUIRED ON)
17+set(CMAKE_CXX_STANDARD 17)
18+set(CMAKE_CXX_STANDARD_REQUIRED ON)
19+ 
20+option(ASCCOMM_BUILD_CCU "Build asc-comm CCU launch wrapper library" ON)
21+ 
22+if(CUSTOM_ASCEND_CANN_PACKAGE_PATH)
23+ set(_ASCCOMM_CANN_PACKAGE_PATH "${CUSTOM_ASCEND_CANN_PACKAGE_PATH}")
24+elseif(ASCEND_CANN_PACKAGE_PATH)
25+ set(_ASCCOMM_CANN_PACKAGE_PATH "${ASCEND_CANN_PACKAGE_PATH}")
26+elseif(DEFINED ENV{ASCEND_HOME_PATH})
27+ set(_ASCCOMM_CANN_PACKAGE_PATH "$ENV{ASCEND_HOME_PATH}")
28+elseif(DEFINED ENV{ASCEND_CANN_PACKAGE_PATH})
29+ set(_ASCCOMM_CANN_PACKAGE_PATH "$ENV{ASCEND_CANN_PACKAGE_PATH}")
30+elseif(DEFINED ENV{ASCEND_OPP_PATH})
31+ get_filename_component(_ASCCOMM_CANN_PACKAGE_PATH "$ENV{ASCEND_OPP_PATH}/.." ABSOLUTE)
32+else()
33+ set(_ASCCOMM_CANN_PACKAGE_PATH "/usr/local/Ascend/cann")
34+endif()
35+set(ASCEND_CANN_PACKAGE_PATH "${_ASCCOMM_CANN_PACKAGE_PATH}" CACHE PATH "CANN package path")
36+ 
37+if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64|arm")
38+ set(_ASCCOMM_CANN_ARCH "aarch64-linux")
39+else()
40+ set(_ASCCOMM_CANN_ARCH "x86_64-linux")
41+endif()
42+set(ASCCOMM_CANN_ARCH_DIR "${ASCEND_CANN_PACKAGE_PATH}/${_ASCCOMM_CANN_ARCH}" CACHE PATH
43+ "Architecture-specific CANN package path")
44+if(ASCEND_CANN_PACKAGE_PATH AND NOT EXISTS "${ASCCOMM_CANN_ARCH_DIR}")
45+ set(ASCCOMM_CANN_ARCH_DIR "${ASCEND_CANN_PACKAGE_PATH}/aarch64-linux" CACHE PATH
46+ "Architecture-specific CANN package path" FORCE)
47+endif()
48+ 
49+if(ASCCOMM_BUILD_CCU)
50+ add_subdirectory(src/ccu)
51+endif()
MOAT.xml+2-0
@@ -14,7 +14,9 @@
14 <policylist>14 <policylist>
15 <policy name="projectPolicy" desc="Project allowed licenses">15 <policy name="projectPolicy" desc="Project allowed licenses">
16 <policyitem type="license" name="CANN-2.0" path=".*" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter" desc="Approved CANN license"/>16 <policyitem type="license" name="CANN-2.0" path=".*" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter" desc="Approved CANN license"/>
17+ <policyitem type="license" name="BSD-style" path="src/ccu/xxhash_impl\.inc" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter" desc="Approved xxHash BSD 2-Clause license"/>
G
Ggao_dafa8月20日

这里是跟ci同事对过的吗?这个相当于是白名单了。确认下是屏蔽还是改这里?

likedislike
bluesky901
8月24日 评论:
17 <policyitem type="copyright" name="Huawei Technologies Co., Ltd." path=".*" rule="may" group="defaultGroup" filefilter="copyrightPolicyFilter" desc="Approved copyright owner"/>18 <policyitem type="copyright" name="Huawei Technologies Co., Ltd." path=".*" rule="may" group="defaultGroup" filefilter="copyrightPolicyFilter" desc="Approved copyright owner"/>
19+ <policyitem type="copyright" name="Yann Collet" path="src/ccu/xxhash_impl\.inc" rule="may" group="defaultGroup" filefilter="copyrightPolicyFilter" desc="Approved xxHash copyright owner"/>
18 <policyitem type="filetype" name="!binary" path=".*" rule="must" group="defaultGroup" filefilter="binaryFileTypePolicyFilter" desc="Reject binary files unless explicitly filtered"/>20 <policyitem type="filetype" name="!binary" path=".*" rule="must" group="defaultGroup" filefilter="binaryFileTypePolicyFilter" desc="Reject binary files unless explicitly filtered"/>
19 </policy>21 </policy>
20 </policylist>22 </policylist>
@@ -22,3 +22,22 @@ Redistribution and use in source and binary forms, with or without modification,
223. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.223. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
23 23 
24THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.24THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25+ 
26+Software: xxHash
27+Copyright notice:
28+Copyright (C) 2012-2023 Yann Collet
29+All rights reserved.
30+ 
31+License: BSD 2-Clause License
32+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
33+ 
34+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
35+ 
36+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
37+ 
38+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
39+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
40+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
41+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
42+AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
43+OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,73 @@
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+cmake_minimum_required(VERSION 3.16.0)
12+find_package(ASC REQUIRED)
13+project(hccl_examples_custom_ops_allgather_ccu_direct LANGUAGES CXX ASC)
14+ 
15+if(NOT DEFINED ASCEND_CANN_PACKAGE_PATH)
16+ if(DEFINED ENV{ASCEND_HOME_PATH})
17+ set(ASCEND_CANN_PACKAGE_PATH $ENV{ASCEND_HOME_PATH})
18+ elseif(DEFINED ENV{ASCEND_OPP_PATH})
19+ get_filename_component(ASCEND_CANN_PACKAGE_PATH "$ENV{ASCEND_OPP_PATH}/.." ABSOLUTE)
20+ else()
21+ message(FATAL_ERROR "ASCEND_CANN_PACKAGE_PATH or ASCEND_HOME_PATH must be set")
22+ endif()
23+endif()
24+ 
25+add_executable(demo
26+ main.asc
27+)
28+ 
29+target_include_directories(demo PRIVATE
30+ # CANN Toolkit头文件
31+ ${ASCEND_CANN_PACKAGE_PATH}/include
32+ ${ASCEND_CANN_PACKAGE_PATH}/include/hccl
33+ ${ASCEND_CANN_PACKAGE_PATH}/include/hcomm
B
Bbluesky9018月17日

缺少asc/include/头文件路径包含

likedislike
34+ ${ASCEND_CANN_PACKAGE_PATH}/include/hcomm/ccu
35+ ${ASCEND_CANN_PACKAGE_PATH}/asc/include/comm_api/ccu
36+ ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc
37+ ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/hcomm
38+ ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/hcomm/ccu
39+)
40+ 
41+target_compile_features(demo PRIVATE cxx_std_14)
42+target_compile_options(demo PRIVATE
43+ -Werror
44+ -fstack-protector-strong
45+ -fPIE
46+ -O2
47+ # -s
48+)
49+set(CMAKE_ASC_ARCHITECTURES "dav-3510" CACHE STRING "CMAKE_ASC_ARCHITECTURES, e.g. dav-3510")
50+target_compile_options(demo PRIVATE
51+ $<$<COMPILE_LANGUAGE:ASC>:--npu-arch=${CMAKE_ASC_ARCHITECTURES}>
52+)
53+ 
54+target_compile_definitions(demo PRIVATE
55+ _GLIBCXX_USE_CXX11_ABI=0
56+)
57+target_link_options(demo PRIVATE
58+ -pie
59+ -Wl,-z,relro
60+ -Wl,-z,now
61+ -Wl,-z,noexecstack
62+)
63+target_link_directories(demo PRIVATE
64+ ${ASCEND_CANN_PACKAGE_PATH}/lib64
65+)
66+target_link_libraries(demo PRIVATE
67+ hcomm
68+ asccomm_ccu
69+ c_sec
70+ ascendcl
71+ acl_rt
72+ ascendc_runtime
73+)
@@ -0,0 +1,112 @@
1+# CCU Direct AllGather样例
2+ 
3+## 概述
4+ 
5+本样例展示如何基于HCCL通信域和CCU数据面接口,以直调`<<<>>>`方式实现AllGather集合通信操作。
6+ 
7+样例会根据当前环境中的NPU数量创建通信域,每个Device对应一个rank。每个rank输入一段FP32数据,CCU
8+Kernel完成AllGather后,每个rank的输出Buffer中按rank顺序保存所有rank的输入数据。
9+ 
10+## 本样例支持的产品及CANN软件版本
11+ 
12+| 产品 | CANN软件版本 |
13+| --- | --- |
14+| Ascend 950PR/Ascend 950DT | >= CANN 9.1.0 |
15+ 
16+## 目录结构介绍
17+ 
18+```text
19+01_allgather
20+├── CMakeLists.txt // 编译工程文件
21+├── README.md // 中文样例说明
22+├── README_en.md // 英文样例说明
23+└── main.asc // Host侧流程和CCU AllGather Kernel实现
24+```
25+ 
26+## 样例描述
27+ 
28+### 功能说明
29+ 
30+每个rank的输入为`sendCount`个FP32元素。AllGather完成后,每个rank的`recvBuf`按rank顺序保存所有rank
31+的输入:
32+ 
33+```text
34+rank r sendBuf = segment_r
35+rank p recvBuf = [segment_0 | segment_1 | ... | segment_N-1]
36+```
37+ 
D

应加上支持的cann版本

likedislike
38+### 样例规格
39+ 
40+| 项目 | 说明 |
41+| --- | --- |
42+| 通信模式 | HCCL通信域内CCU AllGather |
43+| 调用方式 | CCU Kernel直调`<<<>>>` |
44+| 数据类型 | FP32 |
45+| 单rank输入规模 | 256个FP32元素 |
46+| 输出规模 | `rankSize * 256`个FP32元素 |
47+| 支持rank数 | 不超过`CCU_MAX_RANK_SIZE`,当前样例中为16 |
48+ 
49+### 实现流程
50+ 
51+1. 初始化ACL和HCCL通信域,获取当前环境中的NPU数量。
52+2. 每个Device创建一个rank,并初始化输入Buffer。
53+3. 基于HCCL通信域申请CCU Channel和CCU实例资源。
54+4. 通过`HcommCcuGetMemToken`获取输入内存Token,并准备CCU任务参数。
55+5. 通过`CcuAllGatherMesh1DMem2MemKernel<<<schd, insHandle, stream>>>`直调CCU Kernel。
56+6. 同步Stream后将结果拷贝回Host侧并打印。
57+7. 销毁HCCL通信域、Stream和Device侧内存。
58+ 
59+## 编译运行
60+ 
61+在本样例根目录下执行如下步骤,编译并运行样例。本样例仅支持NPU运行模式。
62+ 
63+- 配置环境变量
64+ 
65+ 请根据当前环境上CANN开发套件包的安装方式配置环境变量,并开启CCU调度模式。
66+ 
67+ ```bash
68+ source ${install_path}/cann/set_env.sh
69+ export HCCL_OP_EXPANSION_MODE=CCU_SCHED
70+ ```
71+ 
72+ > **说明:** `${install_path}`为CANN包安装目录,未指定安装目录时默认安装至`/usr/local/Ascend`。
73+ 
74+- 样例执行
75+ 
76+ 在本样例目录下执行如下命令。
77+ 
78+ ```bash
79+ mkdir -p build
80+ cd build
81+ cmake -DCMAKE_ASC_ARCHITECTURES=dav-3510 ..
82+ make -j
83+ ./demo
84+ ```
85+ 
86+- 编译选项说明
87+ 
88+ | 选项 | 可选值 | 说明 |
89+ | --- | --- | --- |
90+ | `CMAKE_ASC_RUN_MODE` | `npu`(默认) | 运行模式,本样例仅支持NPU运行 |
91+ | `CMAKE_ASC_ARCHITECTURES` | `dav-3510` | NPU架构,对应Ascend 950PR/Ascend 950DT |
92+ 
93+- 执行结果
94+ 
95+ 两卡场景下,rank `d`的输入元素初始化为`d + 1`。运行成功后终端会输出类似以下信息:
96+ 
97+ ```text
98+ Found 2 NPU device(s) available
99+ rankId: 0, input: [ 1 1 1 ... ]
100+ rankId: 1, input: [ 2 2 2 ... ]
101+ rankId: 0, recvBuf: [ 1 1 1 ... 2 2 2 ... ]
102+ rankId: 1, recvBuf: [ 1 1 1 ... 2 2 2 ... ]
103+ ```
104+ 
105+ 每个rank的`recvBuf`均包含所有rank的输入数据,表示样例执行成功。
106+ 
107+## 注意事项
108+ 
109+- 运行样例需要至少2张NPU;单卡环境仅支持编译验证。
110+- 运行前必须设置`HCCL_OP_EXPANSION_MODE=CCU_SCHED`。
111+- 当前样例默认使用`dav-3510`架构,仅覆盖Ascend 950PR/Ascend 950DT场景。
112+- 当前样例会使用环境中可见的全部NPU设备,设备数量不能超过`CCU_MAX_RANK_SIZE`。
@@ -0,0 +1,114 @@
1+# CCU Direct AllGather Sample
2+ 
3+## Overview
4+ 
5+This sample demonstrates how to implement AllGather collective communication over an HCCL communication domain and
6+CCU data-plane APIs by directly launching the CCU kernel with `<<<>>>`.
7+ 
8+The sample creates one rank for each available NPU device. Each rank provides one FP32 input segment. After the
9+CCU kernel completes AllGather, the output buffer on every rank contains all rank input segments in rank order.
10+ 
11+## Supported Products and CANN Software Versions
12+ 
13+| Product | CANN Software Version |
14+| --- | --- |
15+| Ascend 950PR/Ascend 950DT | >= CANN 9.1.0 |
16+ 
17+## Directory Structure
18+ 
19+```text
20+01_allgather
21+├── CMakeLists.txt // Build configuration file
22+├── README.md // Chinese documentation
23+├── README_en.md // English documentation
24+└── main.asc // Host flow and CCU AllGather kernel implementation
25+```
26+ 
27+## Sample Description
28+ 
29+### Functionality
30+ 
31+Each rank input contains `sendCount` FP32 elements. After AllGather, `recvBuf` on every rank stores all rank input
32+segments in rank order:
33+ 
34+```text
35+rank r sendBuf = segment_r
36+rank p recvBuf = [segment_0 | segment_1 | ... | segment_N-1]
37+```
38+ 
39+### Specifications
40+ 
41+| Item | Description |
42+| --- | --- |
43+| Communication mode | CCU AllGather in an HCCL communication domain |
44+| Launch mode | Direct CCU kernel launch with `<<<>>>` |
45+| Data type | FP32 |
46+| Input size per rank | 256 FP32 elements |
47+| Output size | `rankSize * 256` FP32 elements |
48+| Supported ranks | No more than `CCU_MAX_RANK_SIZE`, which is 16 in this sample |
49+ 
50+### Implementation Flow
51+ 
52+1. Initialize ACL and the HCCL communication domain, and query the number of NPU devices.
53+2. Create one rank for each device and initialize the input buffer.
54+3. Acquire CCU channels and CCU instance resources from the HCCL communication domain.
55+4. Obtain the input memory token through `HcommCcuGetMemToken` and prepare CCU task arguments.
56+5. Directly launch the CCU kernel through `CcuAllGatherMesh1DMem2MemKernel<<<schd, insHandle, stream>>>`.
57+6. Synchronize the stream, copy the result back to the host, and print it.
58+7. Destroy the HCCL communication domain, streams, and device memory.
59+ 
60+## Build and Run
61+ 
62+Perform the following steps in the sample root directory. This sample supports NPU run mode only.
63+ 
64+- Set Environment Variables
65+ 
66+ Configure CANN environment variables according to your installation and enable CCU scheduling mode.
67+ 
68+ ```bash
69+ source ${install_path}/cann/set_env.sh
70+ export HCCL_OP_EXPANSION_MODE=CCU_SCHED
71+ ```
72+ 
73+ > **Note:** `${install_path}` is the CANN installation directory. The default installation directory is
74+ > `/usr/local/Ascend`.
75+ 
76+- Run the Sample
77+ 
78+ Run the following commands in the sample directory.
79+ 
80+ ```bash
81+ mkdir -p build
82+ cd build
83+ cmake -DCMAKE_ASC_ARCHITECTURES=dav-3510 ..
84+ make -j
85+ ./demo
86+ ```
87+ 
88+- Build Options
89+ 
90+ | Option | Values | Description |
91+ | --- | --- | --- |
92+ | `CMAKE_ASC_RUN_MODE` | `npu` (default) | Run mode. This sample supports NPU execution only |
93+ | `CMAKE_ASC_ARCHITECTURES` | `dav-3510` | NPU architecture for Ascend 950PR/Ascend 950DT |
94+ 
95+- Expected Output
96+ 
97+ In a two-device run, the input elements of rank `d` are initialized to `d + 1`. The output is similar to:
98+ 
99+ ```text
100+ Found 2 NPU device(s) available
101+ rankId: 0, input: [ 1 1 1 ... ]
102+ rankId: 1, input: [ 2 2 2 ... ]
103+ rankId: 0, recvBuf: [ 1 1 1 ... 2 2 2 ... ]
104+ rankId: 1, recvBuf: [ 1 1 1 ... 2 2 2 ... ]
105+ ```
106+ 
107+ The sample succeeds when `recvBuf` on every rank contains all rank input segments.
108+ 
109+## Notes
110+ 
111+- At least two NPU devices are required to run the sample. Single-device environments support compilation only.
112+- Set `HCCL_OP_EXPANSION_MODE=CCU_SCHED` before running the sample.
113+- The sample uses `dav-3510` by default and covers Ascend 950PR/Ascend 950DT.
114+- The sample uses all visible NPU devices, and the device count must not exceed `CCU_MAX_RANK_SIZE`.
@@ -0,0 +1,73 @@
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+cmake_minimum_required(VERSION 3.16.0)
12+find_package(ASC REQUIRED)
13+project(hccl_examples_custom_ops_allgather_ccu_direct LANGUAGES CXX ASC)
14+ 
15+if(NOT DEFINED ASCEND_CANN_PACKAGE_PATH)
16+ if(DEFINED ENV{ASCEND_HOME_PATH})
17+ set(ASCEND_CANN_PACKAGE_PATH $ENV{ASCEND_HOME_PATH})
18+ elseif(DEFINED ENV{ASCEND_OPP_PATH})
19+ get_filename_component(ASCEND_CANN_PACKAGE_PATH "$ENV{ASCEND_OPP_PATH}/.." ABSOLUTE)
20+ else()
21+ message(FATAL_ERROR "ASCEND_CANN_PACKAGE_PATH or ASCEND_HOME_PATH must be set")
22+ endif()
23+endif()
24+ 
25+add_executable(demo
26+ main.asc
27+)
28+ 
29+target_include_directories(demo PRIVATE
30+ # CANN Toolkit头文件
31+ ${ASCEND_CANN_PACKAGE_PATH}/include
32+ ${ASCEND_CANN_PACKAGE_PATH}/include/hccl
33+ ${ASCEND_CANN_PACKAGE_PATH}/include/hcomm
B
Bbluesky9018月17日

缺少asc/include/头文件路径包含

likedislike
34+ ${ASCEND_CANN_PACKAGE_PATH}/include/hcomm/ccu
35+ ${ASCEND_CANN_PACKAGE_PATH}/asc/include/comm_api/ccu
36+ ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc
37+ ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/hcomm
38+ ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/hcomm/ccu
39+)
40+ 
41+target_compile_features(demo PRIVATE cxx_std_14)
42+target_compile_options(demo PRIVATE
43+ -Werror
44+ -fstack-protector-strong
45+ -fPIE
46+ -O2
47+ # -s
48+)
49+set(CMAKE_ASC_ARCHITECTURES "dav-3510" CACHE STRING "CMAKE_ASC_ARCHITECTURES, e.g. dav-3510")
50+target_compile_options(demo PRIVATE
51+ $<$<COMPILE_LANGUAGE:ASC>:--npu-arch=${CMAKE_ASC_ARCHITECTURES}>
52+)
53+ 
54+target_compile_definitions(demo PRIVATE
55+ _GLIBCXX_USE_CXX11_ABI=0
56+)
57+target_link_options(demo PRIVATE
58+ -pie
59+ -Wl,-z,relro
60+ -Wl,-z,now
61+ -Wl,-z,noexecstack
62+)
63+target_link_directories(demo PRIVATE
64+ ${ASCEND_CANN_PACKAGE_PATH}/lib64
65+)
66+target_link_libraries(demo PRIVATE
67+ hcomm
68+ asccomm_ccu
69+ c_sec
70+ ascendcl
71+ acl_rt
72+ ascendc_runtime
73+)
@@ -0,0 +1,114 @@
1+# CCU Direct AllGather + Add样例
2+ 
3+## 概述
4+ 
5+本样例展示如何先通过CCU以直调`<<<>>>`方式完成AllGather通信,再通过AICore vector kernel对AllGather
6+结果执行Add计算。
7+ 
8+样例会根据当前环境中的NPU数量创建通信域,每个Device对应一个rank。每个rank输入一段FP32数据,先完成
9+跨rank AllGather,再将聚合后的结果作为AICore计算输入。
10+ 
11+## 本样例支持的产品及CANN软件版本
12+ 
13+| 产品 | CANN软件版本 |
14+| --- | --- |
15+| Ascend 950PR/Ascend 950DT | >= CANN 9.1.0 |
16+ 
17+## 目录结构介绍
18+ 
19+```text
20+02_allgather_add
21+├── CMakeLists.txt // 编译工程文件
22+├── README.md // 中文样例说明
23+├── README_en.md // 英文样例说明
24+└── main.asc // Host侧流程、CCU AllGather Kernel和AICore Add Kernel实现
25+```
26+ 
27+## 样例描述
28+ 
29+### 功能说明
30+ 
31+每个rank的输入为`sendCount`个FP32元素。样例先将各rank输入AllGather到每个rank的`recvBuf`,再通过
32+AICore vector kernel读取`recvBuf`并将Add结果写入`computeBuf`。
33+ 
34+```text
35+sendBuf -> CCU AllGather -> recvBuf -> AICore Add -> computeBuf
36+```
37+ 
38+### 样例规格
39+ 
40+| 项目 | 说明 |
41+| --- | --- |
42+| 通信模式 | HCCL通信域内CCU AllGather |
43+| 调用方式 | CCU Kernel直调`<<<>>>`,AICore Kernel直调`<<<>>>` |
44+| 数据类型 | FP32 |
45+| 单rank输入规模 | 256个FP32元素 |
46+| AllGather输出规模 | `rankSize * 256`个FP32元素 |
47+| Add输出规模 | `rankSize * 256`个FP32元素 |
48+| 支持rank数 | 不超过`CCU_MAX_RANK_SIZE`,当前样例中为16 |
49+ 
50+### 实现流程
51+ 
52+1. 初始化ACL和HCCL通信域,获取当前环境中的NPU数量。
53+2. 每个Device创建一个rank,并初始化输入Buffer。
54+3. 基于HCCL通信域申请CCU Channel、CCU实例、CCU变量和CCU事件资源。
55+4. 通过`HcommCcuGetMemToken`获取输入内存Token,并准备CCU任务参数。
56+5. 通过`CcuAllGatherMesh1DMem2MemKernel<<<schd, insHandle, streamCcu>>>`直调CCU Kernel完成AllGather。
57+6. 通过`vector_add<<<1, nullptr, streamAiv>>>`直调AICore vector kernel,对AllGather结果执行Add计算。
58+7. 同步AIV和CCU Stream后将`computeBuf`拷贝回Host侧并打印。
59+8. 销毁HCCL通信域、Stream和Device侧内存。
60+ 
61+## 编译运行
62+ 
63+在本样例根目录下执行如下步骤,编译并运行样例。本样例仅支持NPU运行模式。
64+ 
65+- 配置环境变量
66+ 
67+ 请根据当前环境上CANN开发套件包的安装方式配置环境变量,并开启CCU调度模式。
68+ 
69+ ```bash
70+ source ${install_path}/cann/set_env.sh
71+ export HCCL_OP_EXPANSION_MODE=CCU_SCHED
72+ ```
73+ 
74+ > **说明:** `${install_path}`为CANN包安装目录,未指定安装目录时默认安装至`/usr/local/Ascend`。
75+ 
76+- 样例执行
77+ 
78+ 在本样例目录下执行如下命令。
79+ 
80+ ```bash
81+ mkdir -p build
82+ cd build
83+ cmake -DCMAKE_ASC_ARCHITECTURES=dav-3510 ..
84+ make -j
85+ ./demo
86+ ```
87+ 
88+- 编译选项说明
89+ 
90+ | 选项 | 可选值 | 说明 |
91+ | --- | --- | --- |
92+ | `CMAKE_ASC_RUN_MODE` | `npu`(默认) | 运行模式,本样例仅支持NPU运行 |
93+ | `CMAKE_ASC_ARCHITECTURES` | `dav-3510` | NPU架构,对应Ascend 950PR/Ascend 950DT |
94+ 
95+- 执行结果
96+ 
97+ 两卡场景下,rank `d`的输入元素初始化为`d + 1`。运行成功后终端会输出类似以下信息:
98+ 
99+ ```text
100+ Found 2 NPU device(s) available
101+ rankId: 0, input: [ 1 1 1 ... ]
102+ rankId: 1, input: [ 2 2 2 ... ]
103+ rankId: 0, computeBuf: [ 9 9 9 ... 10 10 10 ... ]
104+ rankId: 1, computeBuf: [ 9 9 9 ... 10 10 10 ... ]
105+ ```
106+ 
107+ 每个rank均完成AllGather并输出AICore Add后的结果,表示样例执行成功。
108+ 
109+## 注意事项
110+ 
111+- 运行样例需要至少2张NPU;单卡环境仅支持编译验证。
112+- 运行前必须设置`HCCL_OP_EXPANSION_MODE=CCU_SCHED`。
113+- 当前样例默认使用`dav-3510`架构,仅覆盖Ascend 950PR/Ascend 950DT场景。
114+- 当前样例会使用环境中可见的全部NPU设备,设备数量不能超过`CCU_MAX_RANK_SIZE`。
@@ -0,0 +1,116 @@
1+# CCU Direct AllGather + Add Sample
2+ 
3+## Overview
4+ 
5+This sample demonstrates how to complete AllGather communication by directly launching a CCU kernel with `<<<>>>`,
6+and then run an AICore vector kernel to perform Add computation on the AllGather result.
7+ 
8+The sample creates one rank for each available NPU device. Each rank provides one FP32 input segment. The sample
9+first gathers all rank inputs to every rank and then uses the gathered data as the input of the AICore computation.
10+ 
11+## Supported Products and CANN Software Versions
12+ 
13+| Product | CANN Software Version |
14+| --- | --- |
15+| Ascend 950PR/Ascend 950DT | >= CANN 9.1.0 |
16+ 
17+## Directory Structure
18+ 
19+```text
20+02_allgather_add
21+├── CMakeLists.txt // Build configuration file
22+├── README.md // Chinese documentation
23+├── README_en.md // English documentation
24+└── main.asc // Host flow, CCU AllGather kernel, and AICore Add kernel implementation
25+```
26+ 
27+## Sample Description
28+ 
29+### Functionality
30+ 
31+Each rank input contains `sendCount` FP32 elements. The sample first gathers all rank inputs to `recvBuf` on every
32+rank, and then an AICore vector kernel reads `recvBuf` and writes the Add result to `computeBuf`.
33+ 
34+```text
35+sendBuf -> CCU AllGather -> recvBuf -> AICore Add -> computeBuf
36+```
37+ 
38+### Specifications
39+ 
40+| Item | Description |
41+| --- | --- |
42+| Communication mode | CCU AllGather in an HCCL communication domain |
43+| Launch mode | Direct CCU kernel launch with `<<<>>>` and direct AICore kernel launch with `<<<>>>` |
44+| Data type | FP32 |
45+| Input size per rank | 256 FP32 elements |
46+| AllGather output size | `rankSize * 256` FP32 elements |
47+| Add output size | `rankSize * 256` FP32 elements |
48+| Supported ranks | No more than `CCU_MAX_RANK_SIZE`, which is 16 in this sample |
49+ 
50+### Implementation Flow
51+ 
52+1. Initialize ACL and the HCCL communication domain, and query the number of NPU devices.
53+2. Create one rank for each device and initialize the input buffer.
54+3. Acquire CCU channels, a CCU instance, CCU variables, and CCU events from the HCCL communication domain.
55+4. Obtain the input memory token through `HcommCcuGetMemToken` and prepare CCU task arguments.
56+5. Directly launch the CCU kernel through `CcuAllGatherMesh1DMem2MemKernel<<<schd, insHandle, streamCcu>>>`.
57+6. Directly launch the AICore vector kernel through `vector_add<<<1, nullptr, streamAiv>>>` to compute the
58+ AllGather result.
59+7. Synchronize the AIV and CCU streams, copy `computeBuf` back to the host, and print it.
60+8. Destroy the HCCL communication domain, streams, and device memory.
61+ 
62+## Build and Run
63+ 
64+Perform the following steps in the sample root directory. This sample supports NPU run mode only.
65+ 
66+- Set Environment Variables
67+ 
68+ Configure CANN environment variables according to your installation and enable CCU scheduling mode.
69+ 
70+ ```bash
71+ source ${install_path}/cann/set_env.sh
72+ export HCCL_OP_EXPANSION_MODE=CCU_SCHED
73+ ```
74+ 
75+ > **Note:** `${install_path}` is the CANN installation directory. The default installation directory is
76+ > `/usr/local/Ascend`.
77+ 
78+- Run the Sample
79+ 
80+ Run the following commands in the sample directory.
81+ 
82+ ```bash
83+ mkdir -p build
84+ cd build
85+ cmake -DCMAKE_ASC_ARCHITECTURES=dav-3510 ..
86+ make -j
87+ ./demo
88+ ```
89+ 
90+- Build Options
91+ 
92+ | Option | Values | Description |
93+ | --- | --- | --- |
94+ | `CMAKE_ASC_RUN_MODE` | `npu` (default) | Run mode. This sample supports NPU execution only |
95+ | `CMAKE_ASC_ARCHITECTURES` | `dav-3510` | NPU architecture for Ascend 950PR/Ascend 950DT |
96+ 
97+- Expected Output
98+ 
99+ In a two-device run, the input elements of rank `d` are initialized to `d + 1`. The output is similar to:
100+ 
101+ ```text
102+ Found 2 NPU device(s) available
103+ rankId: 0, input: [ 1 1 1 ... ]
104+ rankId: 1, input: [ 2 2 2 ... ]
105+ rankId: 0, computeBuf: [ 9 9 9 ... 10 10 10 ... ]
106+ rankId: 1, computeBuf: [ 9 9 9 ... 10 10 10 ... ]
107+ ```
108+ 
109+ The sample succeeds when every rank completes AllGather and prints the AICore Add result.
110+ 
111+## Notes
112+ 
113+- At least two NPU devices are required to run the sample. Single-device environments support compilation only.
114+- Set `HCCL_OP_EXPANSION_MODE=CCU_SCHED` before running the sample.
115+- The sample uses `dav-3510` by default and covers Ascend 950PR/Ascend 950DT.
116+- The sample uses all visible NPU devices, and the device count must not exceed `CCU_MAX_RANK_SIZE`.
@@ -0,0 +1,73 @@
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+cmake_minimum_required(VERSION 3.16.0)
12+find_package(ASC REQUIRED)
13+project(hccl_examples_custom_ops_allgather_ccu_direct LANGUAGES CXX ASC)
14+ 
15+if(NOT DEFINED ASCEND_CANN_PACKAGE_PATH)
16+ if(DEFINED ENV{ASCEND_HOME_PATH})
17+ set(ASCEND_CANN_PACKAGE_PATH $ENV{ASCEND_HOME_PATH})
18+ elseif(DEFINED ENV{ASCEND_OPP_PATH})
19+ get_filename_component(ASCEND_CANN_PACKAGE_PATH "$ENV{ASCEND_OPP_PATH}/.." ABSOLUTE)
20+ else()
21+ message(FATAL_ERROR "ASCEND_CANN_PACKAGE_PATH or ASCEND_HOME_PATH must be set")
22+ endif()
23+endif()
24+ 
25+add_executable(demo
26+ main.asc
27+)
28+ 
29+target_include_directories(demo PRIVATE
30+ # CANN Toolkit头文件
31+ ${ASCEND_CANN_PACKAGE_PATH}/include
32+ ${ASCEND_CANN_PACKAGE_PATH}/include/hccl
33+ ${ASCEND_CANN_PACKAGE_PATH}/include/hcomm
34+ ${ASCEND_CANN_PACKAGE_PATH}/include/hcomm/ccu
B
Bbluesky9018月17日

缺少asc/include/头文件路径包含

likedislike
35+ ${ASCEND_CANN_PACKAGE_PATH}/asc/include/comm_api/ccu
36+ ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc
37+ ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/hcomm
38+ ${ASCEND_CANN_PACKAGE_PATH}/pkg_inc/hcomm/ccu
39+)
40+ 
41+target_compile_features(demo PRIVATE cxx_std_14)
42+target_compile_options(demo PRIVATE
43+ -Werror
44+ -fstack-protector-strong
45+ -fPIE
46+ -O2
47+ # -s
48+)
49+set(CMAKE_ASC_ARCHITECTURES "dav-3510" CACHE STRING "CMAKE_ASC_ARCHITECTURES, e.g. dav-3510")
50+target_compile_options(demo PRIVATE
51+ $<$<COMPILE_LANGUAGE:ASC>:--npu-arch=${CMAKE_ASC_ARCHITECTURES}>
52+)
53+ 
54+target_compile_definitions(demo PRIVATE
55+ _GLIBCXX_USE_CXX11_ABI=0
56+)
57+target_link_options(demo PRIVATE
58+ -pie
59+ -Wl,-z,relro
60+ -Wl,-z,now
61+ -Wl,-z,noexecstack
62+)
63+target_link_directories(demo PRIVATE
64+ ${ASCEND_CANN_PACKAGE_PATH}/lib64
65+)
66+target_link_libraries(demo PRIVATE
67+ hcomm
68+ asccomm_ccu
69+ c_sec
70+ ascendcl
71+ acl_rt
72+ ascendc_runtime
73+)
@@ -0,0 +1,114 @@
1+# CCU Direct Add + AllGather样例
2+ 
3+## 概述
4+ 
5+本样例展示如何先通过AICore vector kernel执行Add计算,再以计算结果作为输入,通过CCU以直调`<<<>>>`
6+方式执行AllGather通信。
7+ 
8+样例会根据当前环境中的NPU数量创建通信域,每个Device对应一个rank。每个rank先对本地输入执行AICore
9+Add计算,再将计算结果通过CCU AllGather同步到所有rank。
10+ 
11+## 本样例支持的产品及CANN软件版本
12+ 
13+| 产品 | CANN软件版本 |
14+| --- | --- |
15+| Ascend 950PR/Ascend 950DT | >= CANN 9.1.0 |
16+ 
17+## 目录结构介绍
18+ 
19+```text
20+03_add_allgather
21+├── CMakeLists.txt // 编译工程文件
22+├── README.md // 中文样例说明
23+├── README_en.md // 英文样例说明
24+└── main.asc // Host侧流程、AICore Add Kernel和CCU AllGather Kernel实现
25+```
26+ 
27+## 样例描述
28+ 
29+### 功能说明
30+ 
31+每个rank的输入为`sendCount`个FP32元素。样例先通过AICore vector kernel将本地输入写入`computeBuf`,
32+再以`computeBuf`作为CCU AllGather输入,将所有rank的计算结果同步到每个rank的`recvBuf`。
33+ 
34+```text
35+sendBuf -> AICore Add -> computeBuf -> CCU AllGather -> recvBuf
36+```
37+ 
38+### 样例规格
39+ 
40+| 项目 | 说明 |
41+| --- | --- |
42+| 通信模式 | HCCL通信域内CCU AllGather |
43+| 调用方式 | AICore Kernel直调`<<<>>>`,CCU Kernel直调`<<<>>>` |
44+| 数据类型 | FP32 |
45+| 单rank输入规模 | 256个FP32元素 |
46+| Add输出规模 | 256个FP32元素 |
47+| AllGather输出规模 | `rankSize * 256`个FP32元素 |
48+| 支持rank数 | 不超过`CCU_MAX_RANK_SIZE`,当前样例中为16 |
49+ 
50+### 实现流程
51+ 
52+1. 初始化ACL和HCCL通信域,获取当前环境中的NPU数量。
53+2. 每个Device创建一个rank,并初始化输入Buffer。
54+3. 基于HCCL通信域申请CCU Channel、CCU实例、CCU变量和CCU事件资源。
55+4. 通过`vector_add<<<1, nullptr, streamAiv>>>`直调AICore vector kernel,生成本地计算结果。
56+5. 通过`HcommCcuGetMemToken`获取`computeBuf`内存Token,并准备CCU任务参数。
57+6. 通过`CcuAllGatherMesh1DMem2MemKernel<<<schd, insHandle, streamCcu>>>`直调CCU Kernel完成AllGather。
58+7. 同步AIV和CCU Stream后将`recvBuf`拷贝回Host侧并打印。
59+8. 销毁HCCL通信域、Stream和Device侧内存。
60+ 
61+## 编译运行
62+ 
63+在本样例根目录下执行如下步骤,编译并运行样例。本样例仅支持NPU运行模式。
64+ 
65+- 配置环境变量
66+ 
67+ 请根据当前环境上CANN开发套件包的安装方式配置环境变量,并开启CCU调度模式。
68+ 
69+ ```bash
70+ source ${install_path}/cann/set_env.sh
71+ export HCCL_OP_EXPANSION_MODE=CCU_SCHED
72+ ```
73+ 
74+ > **说明:** `${install_path}`为CANN包安装目录,未指定安装目录时默认安装至`/usr/local/Ascend`。
75+ 
76+- 样例执行
77+ 
78+ 在本样例目录下执行如下命令。
79+ 
80+ ```bash
81+ mkdir -p build
82+ cd build
83+ cmake -DCMAKE_ASC_ARCHITECTURES=dav-3510 ..
84+ make -j
85+ ./demo
86+ ```
87+ 
88+- 编译选项说明
89+ 
90+ | 选项 | 可选值 | 说明 |
91+ | --- | --- | --- |
92+ | `CMAKE_ASC_RUN_MODE` | `npu`(默认) | 运行模式,本样例仅支持NPU运行 |
93+ | `CMAKE_ASC_ARCHITECTURES` | `dav-3510` | NPU架构,对应Ascend 950PR/Ascend 950DT |
94+ 
95+- 执行结果
96+ 
97+ 两卡场景下,rank `d`的输入元素初始化为`d + 1`。运行成功后终端会输出类似以下信息:
98+ 
99+ ```text
100+ Found 2 NPU device(s) available
101+ rankId: 0, input: [ 1 1 1 ... ]
102+ rankId: 1, input: [ 2 2 2 ... ]
103+ rankId: 0, recvBuf: [ 2 2 2 ... 3 3 3 ... ]
104+ rankId: 1, recvBuf: [ 2 2 2 ... 3 3 3 ... ]
105+ ```
106+ 
107+ 每个rank的`recvBuf`均包含所有rank执行AICore Add后的结果,表示样例执行成功。
108+ 
109+## 注意事项
110+ 
111+- 运行样例需要至少2张NPU;单卡环境仅支持编译验证。
112+- 运行前必须设置`HCCL_OP_EXPANSION_MODE=CCU_SCHED`。
113+- 当前样例默认使用`dav-3510`架构,仅覆盖Ascend 950PR/Ascend 950DT场景。
114+- 当前样例会使用环境中可见的全部NPU设备,设备数量不能超过`CCU_MAX_RANK_SIZE`。
@@ -0,0 +1,117 @@
1+# CCU Direct Add + AllGather Sample
2+ 
3+## Overview
4+ 
5+This sample demonstrates how to run Add computation with an AICore vector kernel first, and then use the computed
6+result as the input of AllGather communication by directly launching the CCU kernel with `<<<>>>`.
7+ 
8+The sample creates one rank for each available NPU device. Each rank first runs AICore Add on its local input, and
9+then synchronizes the computed result to all ranks through CCU AllGather.
10+ 
11+## Supported Products and CANN Software Versions
12+ 
13+| Product | CANN Software Version |
14+| --- | --- |
15+| Ascend 950PR/Ascend 950DT | >= CANN 9.1.0 |
16+ 
17+## Directory Structure
18+ 
19+```text
20+03_add_allgather
21+├── CMakeLists.txt // Build configuration file
22+├── README.md // Chinese documentation
23+├── README_en.md // English documentation
24+└── main.asc // Host flow, AICore Add kernel, and CCU AllGather kernel implementation
25+```
26+ 
27+## Sample Description
28+ 
29+### Functionality
30+ 
31+Each rank input contains `sendCount` FP32 elements. The sample first writes the local Add result to `computeBuf`
32+through an AICore vector kernel, and then uses `computeBuf` as the CCU AllGather input so that `recvBuf` on every
33+rank contains all rank computation results.
34+ 
35+```text
36+sendBuf -> AICore Add -> computeBuf -> CCU AllGather -> recvBuf
37+```
38+ 
39+### Specifications
40+ 
41+| Item | Description |
42+| --- | --- |
43+| Communication mode | CCU AllGather in an HCCL communication domain |
44+| Launch mode | Direct AICore kernel launch with `<<<>>>` and direct CCU kernel launch with `<<<>>>` |
45+| Data type | FP32 |
46+| Input size per rank | 256 FP32 elements |
47+| Add output size | 256 FP32 elements |
48+| AllGather output size | `rankSize * 256` FP32 elements |
49+| Supported ranks | No more than `CCU_MAX_RANK_SIZE`, which is 16 in this sample |
50+ 
51+### Implementation Flow
52+ 
53+1. Initialize ACL and the HCCL communication domain, and query the number of NPU devices.
54+2. Create one rank for each device and initialize the input buffer.
55+3. Acquire CCU channels, a CCU instance, CCU variables, and CCU events from the HCCL communication domain.
56+4. Directly launch the AICore vector kernel through `vector_add<<<1, nullptr, streamAiv>>>` to generate the local
57+ computation result.
58+5. Obtain the `computeBuf` memory token through `HcommCcuGetMemToken` and prepare CCU task arguments.
59+6. Directly launch the CCU kernel through `CcuAllGatherMesh1DMem2MemKernel<<<schd, insHandle, streamCcu>>>`.
60+7. Synchronize the AIV and CCU streams, copy `recvBuf` back to the host, and print it.
61+8. Destroy the HCCL communication domain, streams, and device memory.
62+ 
63+## Build and Run
64+ 
65+Perform the following steps in the sample root directory. This sample supports NPU run mode only.
66+ 
67+- Set Environment Variables
68+ 
69+ Configure CANN environment variables according to your installation and enable CCU scheduling mode.
70+ 
71+ ```bash
72+ source ${install_path}/cann/set_env.sh
73+ export HCCL_OP_EXPANSION_MODE=CCU_SCHED
74+ ```
75+ 
76+ > **Note:** `${install_path}` is the CANN installation directory. The default installation directory is
77+ > `/usr/local/Ascend`.
78+ 
79+- Run the Sample
80+ 
81+ Run the following commands in the sample directory.
82+ 
83+ ```bash
84+ mkdir -p build
85+ cd build
86+ cmake -DCMAKE_ASC_ARCHITECTURES=dav-3510 ..
87+ make -j
88+ ./demo
89+ ```
90+ 
91+- Build Options
92+ 
93+ | Option | Values | Description |
94+ | --- | --- | --- |
95+ | `CMAKE_ASC_RUN_MODE` | `npu` (default) | Run mode. This sample supports NPU execution only |
96+ | `CMAKE_ASC_ARCHITECTURES` | `dav-3510` | NPU architecture for Ascend 950PR/Ascend 950DT |
97+ 
98+- Expected Output
99+ 
100+ In a two-device run, the input elements of rank `d` are initialized to `d + 1`. The output is similar to:
101+ 
102+ ```text
103+ Found 2 NPU device(s) available
104+ rankId: 0, input: [ 1 1 1 ... ]
105+ rankId: 1, input: [ 2 2 2 ... ]
106+ rankId: 0, recvBuf: [ 2 2 2 ... 3 3 3 ... ]
107+ rankId: 1, recvBuf: [ 2 2 2 ... 3 3 3 ... ]
108+ ```
109+ 
110+ The sample succeeds when `recvBuf` on every rank contains the AICore Add result from all ranks.
111+ 
112+## Notes
113+ 
114+- At least two NPU devices are required to run the sample. Single-device environments support compilation only.
115+- Set `HCCL_OP_EXPANSION_MODE=CCU_SCHED` before running the sample.
116+- The sample uses `dav-3510` by default and covers Ascend 950PR/Ascend 950DT.
117+- The sample uses all visible NPU devices, and the device count must not exceed `CCU_MAX_RANK_SIZE`.
@@ -0,0 +1,96 @@
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+#ifndef ASC_COMM_CCU_HOST_LAUNCH_H
12+#define ASC_COMM_CCU_HOST_LAUNCH_H
13+ 
14+#include <stdint.h>
15+ 
16+#if defined(__has_include)
17+#if __has_include("hcomm/ccu/ccu_launch.h")
18+#include "hcomm/ccu/ccu_launch.h"
19+#define ASCCOMM_CCU_HOST_LAUNCH_HAS_HCOMM_TYPES 1
20+#elif __has_include("ccu/ccu_launch.h")
21+#include "ccu/ccu_launch.h"
22+#define ASCCOMM_CCU_HOST_LAUNCH_HAS_HCOMM_TYPES 1
23+#elif __has_include("ccu_launch.h")
24+#include "ccu_launch.h"
25+#define ASCCOMM_CCU_HOST_LAUNCH_HAS_HCOMM_TYPES 1
26+#endif
27+#endif
28+ 
29+#ifndef ASCCOMM_CCU_HOST_LAUNCH_HAS_HCOMM_TYPES
30+typedef enum {
31+ CCU_SUCCESS = 0,
32+ CCU_E_PARA = 1,
33+ CCU_E_PTR = 2,
34+ CCU_E_INTERNAL = 4,
35+ CCU_E_NOT_SUPPORT = 5,
36+ CCU_E_NOT_FOUND = 6,
37+ CCU_E_UNAVAIL = 7,
38+ CCU_E_RUNTIME = 15,
39+ CCU_E_DRV_START = 4096,
40+ CCU_E_DRV_INIT_FAILED = 4097,
41+ CCU_E_DRV_BUSY = 4098,
42+ CCU_E_DRV_END = 4224,
43+ CCU_E_RESERVED = 9216
44+} CcuResult;
G
Ggao_dafa8月20日

这个枚举和下面的定义不会跟hcomm的重吗?

likedislike
bluesky901
8月24日 评论:
45+ 
46+typedef uint64_t CcuInsHandle;
47+typedef void* aclrtStream;
48+#endif
49+ 
50+#ifdef __cplusplus
51+extern "C" {
52+#endif
53+ 
54+typedef struct {
55+ uint32_t num_blocks; // mission 个数
56+ uint32_t reserved;
57+ uint64_t phy_die_mask; // 按位表示 0x01表示die0 0x02表示die1
58+ uint64_t binary_cache_tag;
59+} asccomm_ccu_schd;
60+ 
61+typedef struct {
62+ asccomm_ccu_schd ccu_schd;
63+ CcuInsHandle ccu_ins;
64+ aclrtStream stream;
65+ void* attrs;
66+} asccomm_launch_kernel_cfg;
67+ 
68+typedef struct {
69+ uint32_t numBlocks; // mission 个数
70+ uint32_t reserved;
71+ uint64_t phyDieMask; // 按位表示 0x01表示die0 0x02表示die1
72+ uint64_t binaryCacheTag;
73+} HcommCcuSchd;
74+ 
75+typedef struct {
76+ HcommCcuSchd ccuSchd;
77+ CcuInsHandle ccuIns;
78+ aclrtStream stream;
79+ void* attrs;
80+} HcommLaunchKernelCfg;
81+ 
82+typedef CcuResult ccu_result;
83+ 
84+extern ccu_result asccomm_ccu_host_kernel_launch(
85+ const void* kernel_func, const asccomm_launch_kernel_cfg* cfg, void* args);
86+ 
87+extern CcuResult HcommCcuHostKernelLaunch(const void* kernel_func, const HcommLaunchKernelCfg* cfg, void* args);
88+ 
89+extern uint64_t HcommCcuGetLaunchHashTag(const char* tag);
90+extern uint64_t asccomm_ccu_get_launch_hash_tag(const char* tag);
91+ 
92+#ifdef __cplusplus
93+}
94+#endif
95+ 
96+#endif // ASC_COMM_CCU_HOST_LAUNCH_H
@@ -0,0 +1,207 @@
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+set(ASCCOMM_CCU_ROOT ${CMAKE_CURRENT_LIST_DIR})
12+get_filename_component(ASCCOMM_ROOT ${ASCCOMM_CCU_ROOT}/../.. ABSOLUTE)
13+ 
14+if(NOT ASCEND_CANN_PACKAGE_PATH)
15+ if(DEFINED ENV{ASCEND_HOME_PATH})
16+ set(ASCEND_CANN_PACKAGE_PATH "$ENV{ASCEND_HOME_PATH}")
17+ elseif(DEFINED ENV{ASCEND_CANN_PACKAGE_PATH})
18+ set(ASCEND_CANN_PACKAGE_PATH "$ENV{ASCEND_CANN_PACKAGE_PATH}")
19+ endif()
20+endif()
21+ 
22+if(NOT ASCCOMM_CANN_ARCH_DIR OR NOT EXISTS "${ASCCOMM_CANN_ARCH_DIR}")
23+ foreach(_candidate
24+ "${ASCEND_CANN_PACKAGE_PATH}/${CMAKE_SYSTEM_PROCESSOR}-linux"
25+ "${ASCEND_CANN_PACKAGE_PATH}/aarch64-linux"
26+ "${ASCEND_CANN_PACKAGE_PATH}/x86_64-linux"
27+ "${ASCEND_CANN_PACKAGE_PATH}")
28+ if(EXISTS "${_candidate}")
29+ set(ASCCOMM_CANN_ARCH_DIR "${_candidate}")
30+ break()
31+ endif()
32+ endforeach()
33+endif()
34+ 
35+if(NOT ASCCOMM_CANN_ARCH_DIR)
36+ set(ASCCOMM_CANN_ARCH_DIR "${ASCEND_CANN_PACKAGE_PATH}/${CMAKE_SYSTEM_PROCESSOR}-linux")
37+endif()
38+ 
39+function(asccomm_collect_header_dirs out_var)
40+ set(_dirs)
41+ foreach(_root IN LISTS ARGN)
42+ if(EXISTS "${_root}")
43+ file(GLOB_RECURSE _headers CONFIGURE_DEPENDS
44+ "${_root}/*.h"
45+ "${_root}/*.hpp"
46+ )
47+ foreach(_header IN LISTS _headers)
48+ get_filename_component(_dir "${_header}" DIRECTORY)
49+ list(APPEND _dirs "${_dir}")
50+ endforeach()
51+ endif()
52+ endforeach()
53+ list(REMOVE_DUPLICATES _dirs)
54+ set(${out_var} ${_dirs} PARENT_SCOPE)
55+endfunction()
56+ 
57+set(ASCCOMM_HCOMM_HEADER_DIRS)
58+if(ASCCOMM_HCOMM_SOURCE_DIR AND EXISTS "${ASCCOMM_HCOMM_SOURCE_DIR}")
59+ asccomm_collect_header_dirs(ASCCOMM_HCOMM_HEADER_DIRS
60+ ${ASCCOMM_HCOMM_SOURCE_DIR}/src
61+ ${ASCCOMM_HCOMM_SOURCE_DIR}/include
62+ ${ASCCOMM_HCOMM_SOURCE_DIR}/pkg_inc
63+ )
64+endif()
65+set(ASCCOMM_CANN_BASE_INCLUDE_DIRS)
66+if(ASCEND_CANN_PACKAGE_PATH)
67+ list(APPEND ASCCOMM_CANN_BASE_INCLUDE_DIRS
68+ ${ASCEND_CANN_PACKAGE_PATH}/include
69+ ${ASCEND_CANN_PACKAGE_PATH}/runtime/include
70+ )
71+endif()
72+if(ASCCOMM_CANN_ARCH_DIR)
73+ list(APPEND ASCCOMM_CANN_BASE_INCLUDE_DIRS
74+ ${ASCCOMM_CANN_ARCH_DIR}/include
75+ ${ASCCOMM_CANN_ARCH_DIR}/include/hcomm/ccu
76+ ${ASCCOMM_CANN_ARCH_DIR}/include/hccl
77+ ${ASCCOMM_CANN_ARCH_DIR}/pkg_inc
78+ )
79+endif()
80+asccomm_collect_header_dirs(ASCCOMM_CANN_HEADER_DIRS
81+ ${ASCCOMM_CANN_BASE_INCLUDE_DIRS}
82+)
83+ 
84+set(ASCCOMM_HCOMM_PUBLIC_INCLUDE_DIRS)
85+set(ASCCOMM_HCOMM_PRIVATE_INCLUDE_DIRS)
86+if(ASCCOMM_HCOMM_SOURCE_DIR AND EXISTS "${ASCCOMM_HCOMM_SOURCE_DIR}")
87+ set(ASCCOMM_HCOMM_PUBLIC_INCLUDE_DIRS
88+ ${ASCCOMM_HCOMM_SOURCE_DIR}/include
89+ ${ASCCOMM_HCOMM_SOURCE_DIR}/include/hccl
90+ ${ASCCOMM_HCOMM_SOURCE_DIR}/pkg_inc
91+ ${ASCCOMM_HCOMM_SOURCE_DIR}/pkg_inc/hcomm/ccu
92+ ${ASCCOMM_HCOMM_SOURCE_DIR}/pkg_inc/legacy
93+ ${ASCCOMM_HCOMM_SOURCE_DIR}/pkg_inc/legacy/hccl
94+ ${ASCCOMM_HCOMM_SOURCE_DIR}/third_party/json/include
95+ ${ASCCOMM_HCOMM_SOURCE_DIR}/third_party/json/single_include
96+ )
97+ set(ASCCOMM_HCOMM_PRIVATE_INCLUDE_DIRS
98+ ${ASCCOMM_HCOMM_SOURCE_DIR}/src
99+ ${ASCCOMM_HCOMM_SOURCE_DIR}/src/base_comm
100+ ${ASCCOMM_HCOMM_SOURCE_DIR}/src/base_comm/common
101+ ${ASCCOMM_HCOMM_SOURCE_DIR}/src/legacy/ascend910/framework/common/src
102+ ${ASCCOMM_HCOMM_SOURCE_DIR}/src/legacy/ascend910/framework/common/src/mgr
103+ ${ASCCOMM_HCOMM_SOURCE_DIR}/src/legacy/ascend950
104+ ${ASCCOMM_HCOMM_SOURCE_DIR}/src/legacy/ascend950/common
105+ ${ASCCOMM_HCOMM_SOURCE_DIR}/src/legacy/ascend950/common/utils
106+ ${ASCCOMM_HCOMM_SOURCE_DIR}/src/legacy/ascend950/common/exception
107+ ${ASCCOMM_HCOMM_SOURCE_DIR}/src/legacy/ascend950/unified_platform
108+ ${ASCCOMM_HCOMM_SOURCE_DIR}/src/legacy/ascend950/unified_platform/pub_inc
109+ ${ASCCOMM_HCOMM_SOURCE_DIR}/src/legacy/ascend910/framework/hcom
110+ ${ASCCOMM_HCOMM_SOURCE_DIR}/src/legacy/ascend910/framework/inc
111+ ${ASCCOMM_HCOMM_SOURCE_DIR}/src/legacy/ascend910/framework/common/src/exception
112+ ${ASCCOMM_HCOMM_SOURCE_DIR}/src/legacy/ascend910/pub_inc
113+ ${ASCCOMM_HCOMM_SOURCE_DIR}/src/legacy/ascend910/pub_inc/inner
114+ ${ASCCOMM_HCOMM_SOURCE_DIR}/src/legacy/ascend910/pub_inc/new
115+ ${ASCCOMM_HCOMM_SOURCE_DIR}/src/base_comm/resources
116+ ${ASCCOMM_HCOMM_SOURCE_DIR}/src/base_comm/resources/hccp/inc
117+ ${ASCCOMM_HCOMM_SOURCE_DIR}/src/base_comm/resources/endpoint_pairs/channels
118+ ${ASCCOMM_HCOMM_SOURCE_DIR}/src/base_comm/resources/common
119+ ${ASCCOMM_HCOMM_SOURCE_DIR}/src/base_comm/resources/southbound_adpt
120+ ${ASCCOMM_HCOMM_SOURCE_DIR}/src/base_comm/resources/hccp/external_depends
121+ ${ASCCOMM_HCOMM_SOURCE_DIR}/include
122+ ${ASCCOMM_HCOMM_SOURCE_DIR}/include/hccl
123+ ${ASCCOMM_HCOMM_SOURCE_DIR}/pkg_inc
124+ ${ASCCOMM_HCOMM_SOURCE_DIR}/pkg_inc/hccl
125+ ${ASCCOMM_HCOMM_SOURCE_DIR}/pkg_inc/legacy
126+ ${ASCCOMM_HCOMM_SOURCE_DIR}/pkg_inc/legacy/hccl
127+ ${ASCCOMM_HCOMM_SOURCE_DIR}/test/ut/platform/hccp/rdma_service_normal/include
128+ ${ASCCOMM_HCOMM_HEADER_DIRS}
129+ )
130+endif()
131+ 
132+add_library(asccomm_ccu_headers INTERFACE)
133+target_include_directories(asccomm_ccu_headers INTERFACE
134+ ${ASCCOMM_ROOT}/include
135+ ${ASCCOMM_HCOMM_PUBLIC_INCLUDE_DIRS}
136+)
137+ 
138+add_library(asccomm_ccu_obj OBJECT
139+ ${ASCCOMM_CCU_ROOT}/ccu_host_launch.cpp
140+)
141+target_link_libraries(asccomm_ccu_obj PRIVATE
142+ asccomm_ccu_headers
143+ $<$<TARGET_EXISTS:intf_pub>:intf_pub>
144+ $<$<TARGET_EXISTS:error_manager_headers>:error_manager_headers>
145+ $<$<TARGET_EXISTS:acl_rt_headers>:acl_rt_headers>
146+ $<$<TARGET_EXISTS:asc_host_headers>:asc_host_headers>
147+ $<$<TARGET_EXISTS:ascend_hal_headers>:ascend_hal_headers>
148+ $<$<TARGET_EXISTS:kernel_tiling_headers>:kernel_tiling_headers>
149+ $<$<TARGET_EXISTS:atrace_headers>:atrace_headers>
150+ $<$<TARGET_EXISTS:mmpa_headers>:mmpa_headers>
151+ $<$<TARGET_EXISTS:runtime_headers>:runtime_headers>
152+ $<$<TARGET_EXISTS:rdma_core_headers>:rdma_core_headers>
153+ $<$<TARGET_EXISTS:hccl_legacy_headers>:hccl_legacy_headers>
154+ $<$<TARGET_EXISTS:json>:json>
155+ $<$<TARGET_EXISTS:c_sec_headers>:c_sec_headers>
156+ $<$<TARGET_EXISTS:unified_dlog>:unified_dlog>
157+)
158+target_include_directories(asccomm_ccu_obj PRIVATE
159+ ${ASCCOMM_CCU_ROOT}
160+ ${ASCCOMM_HCOMM_PRIVATE_INCLUDE_DIRS}
161+)
162+target_include_directories(asccomm_ccu_obj SYSTEM PRIVATE
163+ ${ASCCOMM_CANN_BASE_INCLUDE_DIRS}
164+ ${ASCCOMM_CANN_HEADER_DIRS}
165+)
166+target_compile_definitions(asccomm_ccu_obj PRIVATE
167+ BUILD_OPEN_PROJECT
168+ CANN_VERSION_NUM=90100000
169+)
170+target_compile_features(asccomm_ccu_obj PUBLIC cxx_std_17)
171+target_compile_options(asccomm_ccu_obj PRIVATE
172+ -fPIC
173+ -Wall
174+ -Werror
175+)
176+ 
177+add_library(asccomm_ccu SHARED
178+ $<TARGET_OBJECTS:asccomm_ccu_obj>
179+)
180+if(NOT ASCCOMM_LIBRARY_OUTPUT_DIRECTORY)
181+ set(ASCCOMM_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
182+endif()
183+set_target_properties(asccomm_ccu PROPERTIES
184+ OUTPUT_NAME asccomm_ccu
185+ LIBRARY_OUTPUT_DIRECTORY ${ASCCOMM_LIBRARY_OUTPUT_DIRECTORY}
186+)
187+target_link_libraries(asccomm_ccu PRIVATE asccomm_ccu_headers)
188+ 
189+if(NOT INSTALL_LIBRARY_DIR)
190+ set(INSTALL_LIBRARY_DIR lib64)
191+endif()
192+if(NOT INSTALL_PKG_INCLUDE_DIR)
193+ set(INSTALL_PKG_INCLUDE_DIR pkg_inc)
194+endif()
195+ 
196+install(TARGETS asccomm_ccu
197+ LIBRARY DESTINATION ${INSTALL_LIBRARY_DIR} ${INSTALL_OPTIONAL}
198+ COMPONENT hcomm)
199+ 
200+if(EXISTS "${ASCCOMM_ROOT}/include/ccu")
201+ install(DIRECTORY ${ASCCOMM_ROOT}/include/ccu/
202+ DESTINATION ${INSTALL_PKG_INCLUDE_DIR}/ccu
203+ COMPONENT hcomm
204+ FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp")
205+endif()
206+ 
207+add_custom_target(asccomm_ccu_compile_check DEPENDS asccomm_ccu)
@@ -0,0 +1,325 @@
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+#include "ccu/ccu_host_launch.h"
12+ 
13+#include "rt_external_kernel.h"
14+ 
15+#include <algorithm>
16+#include <cstring>
17+#include <iterator>
18+#include <mutex>
19+#include <unordered_map>
20+#include <vector>
21+ 
22+#include "xxhash_impl.inc"
23+ 
24+int32_t HcclGetThreadDeviceId();
25+ 
26+#ifndef HCOMM_WEAK_SYMBOL
27+#define HCOMM_WEAK_SYMBOL __attribute__((weak))
28+#endif
29+ 
30+#ifndef ASCCOMM_CCU_HOST_LAUNCH_HAS_HCOMM_TYPES
31+typedef uint64_t CcuKernelHandle;
32+typedef void* CcuKernelArg;
33+#endif
34+ 
35+extern "C" {
36+extern CcuResult HcommCcuKernelRegisterStart(CcuInsHandle insHandle) HCOMM_WEAK_SYMBOL;
37+extern CcuResult HcommCcuKernelRegister(
38+ CcuInsHandle insHandle, uint32_t dieId, const char* kernelFuncName, const void* kernelFunc, const void** kernelArgs,
39+ uint32_t argNum, CcuKernelHandle* kernelHandle) HCOMM_WEAK_SYMBOL;
40+extern CcuResult HcommCcuKernelRegisterEnd(CcuInsHandle insHandle) HCOMM_WEAK_SYMBOL;
41+extern CcuResult HcommCcuGetTaskArgsNum(CcuKernelHandle kernelHandle, uint32_t* taskArgsNum) HCOMM_WEAK_SYMBOL;
42+}
43+ 
44+namespace hcomm {
45+constexpr uint32_t CCU_SQE_ARGS_LEN = 13;
46+ 
47+struct CcuTaskParam {
48+ uint8_t dieId;
49+ uint8_t missionId;
50+ uint16_t timeout;
51+ uint32_t instStartId;
52+ uint32_t instCnt;
53+ uint32_t key;
54+ uint32_t argSize;
55+ uint64_t args[CCU_SQE_ARGS_LEN];
56+};
57+ 
58+class CcuKernel {
59+public:
60+ CcuResult GeneTaskParams(const uint64_t* taskArgs, uint32_t argsNum, std::vector<CcuTaskParam>& taskParams);
61+};
62+ 
63+class CcuKernelMgr {
64+public:
65+ static CcuKernelMgr& GetInstance(int32_t deviceLogicId);
66+ CcuKernel* GetKernel(CcuKernelHandle kernelHandle);
67+};
68+} // namespace hcomm
69+ 
70+namespace {
71+constexpr uint32_t NOTIFY_DEFAULT_WAIT_TIME = 27U * 68U; // notifywait默认1836等待时长
72+constexpr uint64_t CCU_DIE0_MASK = 0x01U;
73+constexpr uint64_t CCU_DIE1_MASK = 0x02U;
74+constexpr uint32_t CCU_DIE0_ID = 0U;
75+constexpr uint32_t CCU_DIE1_ID = 1U;
76+constexpr uint32_t CCU_SUPPORTED_NUM_BLOCKS = 1U;
77+ 
78+bool IsCcuKernelLaunchApiAvailable()
79+{
80+ auto registerStart = HcommCcuKernelRegisterStart;
81+ auto registerKernel = HcommCcuKernelRegister;
82+ auto registerEnd = HcommCcuKernelRegisterEnd;
83+ auto getTaskArgsNum = HcommCcuGetTaskArgsNum;
84+ return registerStart != nullptr && registerKernel != nullptr && registerEnd != nullptr && getTaskArgsNum != nullptr;
85+}
86+ 
87+bool IsSupportedSingleDieMask(uint64_t phyDieMask)
88+{
89+ return phyDieMask == CCU_DIE0_MASK || phyDieMask == CCU_DIE1_MASK;
90+}
91+ 
92+uint32_t GetDieIdByMask(uint64_t phyDieMask) { return phyDieMask == CCU_DIE1_MASK ? CCU_DIE1_ID : CCU_DIE0_ID; }
93+ 
94+CcuResult ValidateLaunchCfg(const asccomm_launch_kernel_cfg* cfg)
95+{
96+ if (cfg->ccu_schd.num_blocks != CCU_SUPPORTED_NUM_BLOCKS) {
97+ return CCU_E_PARA;
98+ }
99+ if (!IsSupportedSingleDieMask(cfg->ccu_schd.phy_die_mask)) {
100+ return CCU_E_PARA;
101+ }
102+ return CCU_SUCCESS;
103+}
104+ 
105+using VoidPackedCcuKernel = void (*)(void*);
106+ 
107+struct VoidKernelRegisterCtx {
108+ const void* kernelFunc;
109+ void* packedArgs;
110+};
111+ 
112+CcuResult VoidKernelTrampoline(CcuKernelArg arg);
113+ 
114+CcuResult RegisterCcuKernel(
115+ const void* kernelFunc, const asccomm_launch_kernel_cfg* cfg, void* args, CcuKernelHandle& kernelHandle)
116+{
117+ CcuResult ret = HcommCcuKernelRegisterStart(cfg->ccu_ins);
118+ if (ret != CCU_SUCCESS) {
119+ return ret;
120+ }
121+ 
122+ const uint32_t dieId = GetDieIdByMask(cfg->ccu_schd.phy_die_mask);
123+ VoidKernelRegisterCtx registerCtx{
124+ kernelFunc,
125+ args,
126+ };
127+ 
128+ const void* kernelArgs[] = {&registerCtx};
129+ 
130+ // kernelFunc do not support func that return void , only support return CcuResult
131+ ret = HcommCcuKernelRegister(
132+ cfg->ccu_ins, dieId, nullptr, reinterpret_cast<const void*>(VoidKernelTrampoline), kernelArgs, 1,
133+ &kernelHandle);
134+ if (ret != CCU_SUCCESS) {
135+ (void)HcommCcuKernelRegisterEnd(cfg->ccu_ins);
136+ return ret;
137+ }
138+ 
139+ return HcommCcuKernelRegisterEnd(cfg->ccu_ins);
140+}
141+ 
142+class KernelHandleCache {
143+public:
144+ CcuResult Match(
145+ const void* kernelFunc, const asccomm_launch_kernel_cfg* cfg, void* args, CcuKernelHandle& kernelHandle,
146+ uint32_t& taskArgsNum)
147+ {
148+ const uint64_t cacheTag = cfg->ccu_schd.binary_cache_tag;
149+ if (cacheTag == 0U) {
150+ return RegisterAndGetTaskArgsNum(kernelFunc, cfg, args, kernelHandle, taskArgsNum);
151+ }
152+ 
153+ std::lock_guard<std::mutex> lock(mutex_);
154+ auto iter = cache_.find(cacheTag);
155+ if (iter != cache_.end()) {
156+ kernelHandle = iter->second;
157+ return HcommCcuGetTaskArgsNum(kernelHandle, &taskArgsNum);
158+ }
159+ 
160+ CcuResult ret = RegisterAndGetTaskArgsNum(kernelFunc, cfg, args, kernelHandle, taskArgsNum);
161+ if (ret != CCU_SUCCESS) {
162+ return ret;
163+ }
164+ cache_[cacheTag] = kernelHandle;
165+ return CCU_SUCCESS;
166+ }
167+ 
168+private:
169+ CcuResult RegisterAndGetTaskArgsNum(
170+ const void* kernelFunc, const asccomm_launch_kernel_cfg* cfg, void* args, CcuKernelHandle& kernelHandle,
171+ uint32_t& taskArgsNum)
172+ {
173+ CcuResult ret = RegisterCcuKernel(kernelFunc, cfg, args, kernelHandle);
174+ if (ret != CCU_SUCCESS) {
175+ return ret;
176+ }
177+ ret = HcommCcuGetTaskArgsNum(kernelHandle, &taskArgsNum);
178+ if (ret != CCU_SUCCESS) {
179+ return ret;
180+ }
181+ return CCU_SUCCESS;
182+ }
183+ 
184+ std::mutex mutex_;
185+ std::unordered_map<uint64_t, CcuKernelHandle> cache_;
186+};
187+ 
188+KernelHandleCache& GetKernelHandleCache()
189+{
190+ static KernelHandleCache cache;
191+ return cache;
192+}
193+ 
194+CcuResult VoidKernelTrampoline(CcuKernelArg arg)
195+{
196+ auto* ctx = static_cast<VoidKernelRegisterCtx*>(arg);
197+ if (ctx == nullptr || ctx->kernelFunc == nullptr || ctx->packedArgs == nullptr) {
198+ return CCU_E_PTR;
199+ }
200+ 
201+ auto fn = reinterpret_cast<VoidPackedCcuKernel>(const_cast<void*>(ctx->kernelFunc));
202+ fn(ctx->packedArgs);
203+ return CCU_SUCCESS;
204+}
205+ 
206+CcuResult GetSingleTaskParam(
207+ CcuKernelHandle kernelHandle, const void* taskArgs, uint32_t argNum, hcomm::CcuTaskParam& taskParam)
208+{
209+ if (kernelHandle == 0) {
210+ return CCU_E_PARA;
211+ }
212+ if (argNum > hcomm::CCU_SQE_ARGS_LEN) {
213+ return CCU_E_NOT_SUPPORT;
214+ }
215+ if (argNum > 0 && taskArgs == nullptr) {
216+ return CCU_E_PTR;
217+ }
218+ 
219+ try {
220+ const uint32_t devLogicId = static_cast<uint32_t>(HcclGetThreadDeviceId());
221+ auto& kernelMgr = hcomm::CcuKernelMgr::GetInstance(devLogicId);
222+ auto* kernel = kernelMgr.GetKernel(kernelHandle);
223+ if (kernel == nullptr) {
224+ return CCU_E_PTR;
225+ }
226+ 
227+ std::vector<hcomm::CcuTaskParam> taskParams{};
228+ CcuResult ret = kernel->GeneTaskParams(static_cast<const uint64_t*>(taskArgs), argNum, taskParams);
229+ if (ret != CCU_SUCCESS) {
230+ return ret;
231+ }
232+ if (taskParams.size() != 1) {
233+ return CCU_E_NOT_SUPPORT;
234+ }
235+ 
236+ taskParam = taskParams.front();
237+ } catch (...) {
238+ return CCU_E_INTERNAL;
239+ }
240+ 
241+ return CCU_SUCCESS;
242+}
243+ 
244+CcuResult LaunchSingleCcuTask(const hcomm::CcuTaskParam& param, aclrtStream stream)
245+{
246+ if (stream == nullptr) {
247+ return CCU_E_PTR;
248+ }
249+ 
250+ rtCcuTaskInfo_t taskInfo{};
251+ taskInfo.dieId = param.dieId;
252+ taskInfo.missionId = param.missionId;
253+ taskInfo.instStartId = param.instStartId;
254+ taskInfo.instCnt = param.instCnt;
255+ taskInfo.key = param.key;
256+ taskInfo.argSize = param.argSize;
257+ taskInfo.timeout = NOTIFY_DEFAULT_WAIT_TIME;
258+ std::copy(std::begin(param.args), std::end(param.args), std::begin(taskInfo.args));
259+ 
260+ auto rtRet = rtCCULaunch(&taskInfo, stream);
261+ if (rtRet != RT_ERROR_NONE) {
262+ return CCU_E_RUNTIME;
263+ }
264+ 
265+ return CCU_SUCCESS;
266+}
267+ 
268+} // namespace
269+ 
270+extern "C" uint64_t asccomm_ccu_get_launch_hash_tag(const char* tag)
271+{
272+ if (tag == nullptr) {
273+ return 0;
274+ }
275+ return static_cast<uint64_t>(XXH3_64bits(tag, std::strlen(tag)));
276+}
277+ 
278+extern "C" ccu_result asccomm_ccu_host_kernel_launch(
279+ const void* kernel_func, const asccomm_launch_kernel_cfg* cfg, void* args)
280+{
281+ if (kernel_func == nullptr || cfg == nullptr || args == nullptr) {
282+ return CCU_E_PTR;
283+ }
284+ CcuResult ret = ValidateLaunchCfg(cfg);
285+ if (ret != CCU_SUCCESS) {
286+ return ret;
287+ }
288+ if (!IsCcuKernelLaunchApiAvailable()) {
289+ return CCU_E_NOT_SUPPORT;
290+ }
291+ 
292+ CcuKernelHandle kernelHandle = 0;
293+ uint32_t taskArgsNum = 0;
294+ ret = GetKernelHandleCache().Match(kernel_func, cfg, args, kernelHandle, taskArgsNum);
295+ if (ret != CCU_SUCCESS) {
296+ return ret;
297+ }
298+ 
299+ hcomm::CcuTaskParam taskParam{};
300+ ret = GetSingleTaskParam(kernelHandle, args, taskArgsNum, taskParam);
301+ if (ret != CCU_SUCCESS) {
302+ return ret;
303+ }
304+ 
305+ return LaunchSingleCcuTask(taskParam, cfg->stream);
306+}
307+ 
308+extern "C" CcuResult HcommCcuHostKernelLaunch(const void* kernel_func, const HcommLaunchKernelCfg* cfg, void* args)
309+{
310+ if (cfg == nullptr) {
311+ return asccomm_ccu_host_kernel_launch(kernel_func, nullptr, args);
312+ }
313+ 
314+ asccomm_launch_kernel_cfg asccommCfg{};
315+ asccommCfg.ccu_schd.num_blocks = cfg->ccuSchd.numBlocks;
316+ asccommCfg.ccu_schd.reserved = cfg->ccuSchd.reserved;
317+ asccommCfg.ccu_schd.phy_die_mask = cfg->ccuSchd.phyDieMask;
318+ asccommCfg.ccu_schd.binary_cache_tag = cfg->ccuSchd.binaryCacheTag;
319+ asccommCfg.ccu_ins = cfg->ccuIns;
320+ asccommCfg.stream = cfg->stream;
321+ asccommCfg.attrs = cfg->attrs;
322+ return asccomm_ccu_host_kernel_launch(kernel_func, &asccommCfg, args);
323+}
324+ 
325+extern "C" uint64_t HcommCcuGetLaunchHashTag(const char* tag) { return asccomm_ccu_get_launch_hash_tag(tag); }
@@ -0,0 +1,333 @@
1+/*
2+ * xxHash - Extremely Fast Hash algorithm
3+ * Copyright (C) 2012-2023 Yann Collet
4+ *
5+ * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)
6+ *
7+ * Redistribution and use in source and binary forms, with or without
8+ * modification, are permitted provided that the following conditions are
9+ * met:
10+ *
11+ * * Redistributions of source code must retain the above copyright
12+ * notice, this list of conditions and the following disclaimer.
13+ * * Redistributions in binary form must reproduce the above
14+ * copyright notice, this list of conditions and the following disclaimer
15+ * in the documentation and/or other materials provided with the
16+ * distribution.
17+ *
18+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, OR FITNESS FOR
21+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29+ */
30+ 
31+// Trimmed internal implementation for XXH3_64bits(input, length) only.
32+ 
33+#include <cstddef>
34+#include <cstdint>
35+#include <cstring>
36+ 
37+namespace asccomm_xxh3_detail {
38+constexpr std::size_t XXH3_SECRETSIZE_MIN = 136;
39+constexpr std::size_t XXH_SECRET_DEFAULT_SIZE = 192;
40+constexpr std::size_t XXH_STRIPE_LEN = 64;
41+constexpr std::size_t XXH_SECRET_CONSUME_RATE = 8;
42+constexpr std::size_t XXH_ACC_NB = XXH_STRIPE_LEN / sizeof(uint64_t);
43+constexpr std::size_t XXH3_MIDSIZE_MAX = 240;
44+constexpr std::size_t XXH3_MIDSIZE_STARTOFFSET = 3;
45+constexpr std::size_t XXH3_MIDSIZE_LASTOFFSET = 17;
46+constexpr std::size_t XXH_SECRET_LASTACC_START = 7;
47+constexpr std::size_t XXH_SECRET_MERGEACCS_START = 11;
48+ 
49+constexpr uint32_t PRIME32_1 = 0x9E3779B1U;
50+constexpr uint32_t PRIME32_2 = 0x85EBCA77U;
51+constexpr uint32_t PRIME32_3 = 0xC2B2AE3DU;
52+constexpr uint64_t PRIME64_1 = 11400714785074694791ULL;
53+constexpr uint64_t PRIME64_2 = 14029467366897019727ULL;
54+constexpr uint64_t PRIME64_3 = 1609587929392839161ULL;
55+constexpr uint64_t PRIME64_4 = 9650029242287828579ULL;
56+constexpr uint64_t PRIME64_5 = 2870177450012600261ULL;
57+constexpr uint64_t PRIME_MX1 = 0x165667919E3779F9ULL;
58+constexpr uint64_t PRIME_MX2 = 0x9FB21C651E98DF25ULL;
59+ 
60+constexpr uint8_t XXH3_K_SECRET[XXH_SECRET_DEFAULT_SIZE] = {
61+ 0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c,
62+ 0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f,
63+ 0xcb, 0x79, 0xe6, 0x4e, 0xcc, 0xc0, 0xe5, 0x78, 0x82, 0x5a, 0xd0, 0x7d, 0xcc, 0xff, 0x72, 0x21,
64+ 0xb8, 0x08, 0x46, 0x74, 0xf7, 0x43, 0x24, 0x8e, 0xe0, 0x35, 0x90, 0xe6, 0x81, 0x3a, 0x26, 0x4c,
65+ 0x3c, 0x28, 0x52, 0xbb, 0x91, 0xc3, 0x00, 0xcb, 0x88, 0xd0, 0x65, 0x8b, 0x1b, 0x53, 0x2e, 0xa3,
66+ 0x71, 0x64, 0x48, 0x97, 0xa2, 0x0d, 0xf9, 0x4e, 0x38, 0x19, 0xef, 0x46, 0xa9, 0xde, 0xac, 0xd8,
67+ 0xa8, 0xfa, 0x76, 0x3f, 0xe3, 0x9c, 0x34, 0x3f, 0xf9, 0xdc, 0xbb, 0xc7, 0xc7, 0x0b, 0x4f, 0x1d,
68+ 0x8a, 0x51, 0xe0, 0x4b, 0xcd, 0xb4, 0x59, 0x31, 0xc8, 0x9f, 0x7e, 0xc9, 0xd9, 0x78, 0x73, 0x64,
69+ 0xea, 0xc5, 0xac, 0x83, 0x34, 0xd3, 0xeb, 0xc3, 0xc5, 0x81, 0xa0, 0xff, 0xfa, 0x13, 0x63, 0xeb,
70+ 0x17, 0x0d, 0xdd, 0x51, 0xb7, 0xf0, 0xda, 0x49, 0xd3, 0x16, 0x55, 0x26, 0x29, 0xd4, 0x68, 0x9e,
71+ 0x2b, 0x16, 0xbe, 0x58, 0x7d, 0x47, 0xa1, 0xfc, 0x8f, 0xf8, 0xb8, 0xd1, 0x7a, 0xd0, 0x31, 0xce,
72+ 0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e,
73+};
74+ 
75+static inline uint64_t Bswap64(uint64_t value)
76+{
77+#if defined(__GNUC__) || defined(__clang__)
78+ return __builtin_bswap64(value);
79+#else
80+ return ((value & 0x00000000000000ffULL) << 56) | ((value & 0x000000000000ff00ULL) << 40) |
81+ ((value & 0x0000000000ff0000ULL) << 24) | ((value & 0x00000000ff000000ULL) << 8) |
82+ ((value & 0x000000ff00000000ULL) >> 8) | ((value & 0x0000ff0000000000ULL) >> 24) |
83+ ((value & 0x00ff000000000000ULL) >> 40) | ((value & 0xff00000000000000ULL) >> 56);
84+#endif
85+}
86+ 
87+static inline uint32_t Bswap32(uint32_t value)
88+{
89+#if defined(__GNUC__) || defined(__clang__)
90+ return __builtin_bswap32(value);
91+#else
92+ return ((value & 0x000000ffU) << 24) | ((value & 0x0000ff00U) << 8) |
93+ ((value & 0x00ff0000U) >> 8) | ((value & 0xff000000U) >> 24);
94+#endif
95+}
96+ 
97+static inline uint64_t Read64LE(const void *ptr)
98+{
99+ uint64_t value;
100+ std::memcpy(&value, ptr, sizeof(value));
101+#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
102+ value = Bswap64(value);
103+#endif
104+ return value;
105+}
106+ 
107+static inline uint32_t Read32LE(const void *ptr)
108+{
109+ uint32_t value;
110+ std::memcpy(&value, ptr, sizeof(value));
111+#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
112+ value = Bswap32(value);
113+#endif
114+ return value;
115+}
116+ 
117+static inline uint64_t Rotl64(uint64_t value, uint32_t shift)
118+{
119+ return (value << shift) | (value >> (64U - shift));
120+}
121+ 
122+static inline uint64_t XXH64Avalanche(uint64_t hash)
123+{
124+ hash ^= hash >> 33;
125+ hash *= PRIME64_2;
126+ hash ^= hash >> 29;
127+ hash *= PRIME64_3;
128+ hash ^= hash >> 32;
129+ return hash;
130+}
131+ 
132+static inline uint64_t Mul128Fold64(uint64_t lhs, uint64_t rhs)
133+{
134+#if defined(__SIZEOF_INT128__) || (defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 128)
135+ __uint128_t product = static_cast<__uint128_t>(lhs) * static_cast<__uint128_t>(rhs);
136+ return static_cast<uint64_t>(product) ^ static_cast<uint64_t>(product >> 64);
137+#else
138+ const uint64_t loLo = (lhs & 0xFFFFFFFFULL) * (rhs & 0xFFFFFFFFULL);
139+ const uint64_t hiLo = (lhs >> 32) * (rhs & 0xFFFFFFFFULL);
140+ const uint64_t loHi = (lhs & 0xFFFFFFFFULL) * (rhs >> 32);
141+ const uint64_t hiHi = (lhs >> 32) * (rhs >> 32);
142+ const uint64_t cross = (loLo >> 32) + (hiLo & 0xFFFFFFFFULL) + loHi;
143+ const uint64_t upper = (hiLo >> 32) + (cross >> 32) + hiHi;
144+ const uint64_t lower = (cross << 32) | (loLo & 0xFFFFFFFFULL);
145+ return upper ^ lower;
146+#endif
147+}
148+ 
149+static inline uint64_t XXH3Avalanche(uint64_t hash)
150+{
151+ hash ^= hash >> 37;
152+ hash *= PRIME_MX1;
153+ hash ^= hash >> 32;
154+ return hash;
155+}
156+ 
157+static inline uint64_t Len1To3(const uint8_t *input, std::size_t len, const uint8_t *secret)
158+{
159+ const uint8_t c1 = input[0];
160+ const uint8_t c2 = input[len >> 1];
161+ const uint8_t c3 = input[len - 1];
162+ const uint32_t combined = (static_cast<uint32_t>(c1) << 16) |
163+ (static_cast<uint32_t>(c2) << 24) | static_cast<uint32_t>(c3) |
164+ (static_cast<uint32_t>(len) << 8);
165+ const uint64_t bitflip = static_cast<uint64_t>(Read32LE(secret) ^ Read32LE(secret + 4));
166+ return XXH64Avalanche(static_cast<uint64_t>(combined) ^ bitflip);
167+}
168+ 
169+static inline uint64_t Len4To8(const uint8_t *input, std::size_t len, const uint8_t *secret)
170+{
171+ const uint32_t input1 = Read32LE(input);
172+ const uint32_t input2 = Read32LE(input + len - 4);
173+ uint64_t acc = Read64LE(secret + 8) ^ Read64LE(secret + 16);
174+ const uint64_t input64 = static_cast<uint64_t>(input2) | (static_cast<uint64_t>(input1) << 32);
175+ acc ^= input64;
176+ acc ^= Rotl64(acc, 49) ^ Rotl64(acc, 24);
177+ acc *= PRIME_MX2;
178+ acc ^= (acc >> 35) + static_cast<uint64_t>(len);
179+ acc *= PRIME_MX2;
180+ return acc ^ (acc >> 28);
181+}
182+ 
183+static inline uint64_t Len9To16(const uint8_t *input, std::size_t len, const uint8_t *secret)
184+{
185+ uint64_t inputLo = Read64LE(secret + 24) ^ Read64LE(secret + 32);
186+ uint64_t inputHi = Read64LE(secret + 40) ^ Read64LE(secret + 48);
187+ inputLo ^= Read64LE(input);
188+ inputHi ^= Read64LE(input + len - 8);
189+ const uint64_t acc = static_cast<uint64_t>(len) + Bswap64(inputLo) + inputHi +
190+ Mul128Fold64(inputLo, inputHi);
191+ return XXH3Avalanche(acc);
192+}
193+ 
194+static inline uint64_t Len0To16(const uint8_t *input, std::size_t len, const uint8_t *secret)
195+{
196+ if (len > 8) {
197+ return Len9To16(input, len, secret);
198+ }
199+ if (len >= 4) {
200+ return Len4To8(input, len, secret);
201+ }
202+ if (len != 0) {
203+ return Len1To3(input, len, secret);
204+ }
205+ return XXH64Avalanche(Read64LE(secret + 56) ^ Read64LE(secret + 64));
206+}
207+ 
208+static inline uint64_t Mix16B(const uint8_t *input, const uint8_t *secret)
209+{
210+ const uint64_t lhs = Read64LE(secret) ^ Read64LE(input);
211+ const uint64_t rhs = Read64LE(secret + 8) ^ Read64LE(input + 8);
212+ return Mul128Fold64(lhs, rhs);
213+}
214+ 
215+static inline uint64_t Len17To128(const uint8_t *input, std::size_t len, const uint8_t *secret)
216+{
217+ uint64_t acc = len * PRIME64_1;
218+ uint64_t accResult = Mix16B(input + len - 16, secret + 16);
219+ acc += Mix16B(input, secret);
220+ if (len > 32) {
221+ acc += Mix16B(input + 16, secret + 32);
222+ accResult += Mix16B(input + len - 32, secret + 48);
223+ if (len > 64) {
224+ acc += Mix16B(input + 32, secret + 64);
225+ accResult += Mix16B(input + len - 48, secret + 80);
226+ if (len > 96) {
227+ acc += Mix16B(input + 48, secret + 96);
228+ accResult += Mix16B(input + len - 64, secret + 112);
229+ }
230+ }
231+ }
232+ return XXH3Avalanche(acc + accResult);
233+}
234+ 
235+static inline uint64_t Len129To240(const uint8_t *input, std::size_t len, const uint8_t *secret)
236+{
237+ uint64_t acc = static_cast<uint64_t>(len) * PRIME64_1;
238+ const std::size_t nbRounds = len / 16;
239+ for (std::size_t i = 0; i < 8; ++i) {
240+ acc += Mix16B(input + (16 * i), secret + (16 * i));
241+ }
242+ acc = XXH3Avalanche(acc);
243+ for (std::size_t i = 8; i < nbRounds; ++i) {
244+ acc += Mix16B(input + (16 * i), secret + (16 * (i - 8)) + XXH3_MIDSIZE_STARTOFFSET);
245+ }
246+ acc += Mix16B(input + len - 16, secret + XXH3_SECRETSIZE_MIN - XXH3_MIDSIZE_LASTOFFSET);
247+ return XXH3Avalanche(acc);
248+}
249+ 
250+static inline void Accumulate512(uint64_t *acc, const uint8_t *input, const uint8_t *secret)
251+{
252+ for (std::size_t i = 0; i < XXH_ACC_NB; ++i) {
253+ const uint64_t dataVal = Read64LE(input + (8 * i));
254+ const uint64_t dataKey = dataVal ^ Read64LE(secret + (8 * i));
255+ acc[i ^ 1] += dataVal;
256+ acc[i] += static_cast<uint32_t>(dataKey) * (dataKey >> 32);
257+ }
258+}
259+ 
260+static inline void ScrambleAcc(uint64_t *acc, const uint8_t *secret)
261+{
262+ for (std::size_t i = 0; i < XXH_ACC_NB; ++i) {
263+ acc[i] ^= acc[i] >> 47;
264+ acc[i] ^= Read64LE(secret + (8 * i));
265+ acc[i] *= PRIME32_1;
266+ }
267+}
268+ 
269+static inline void Accumulate(uint64_t *acc, const uint8_t *input, const uint8_t *secret,
270+ std::size_t nbStripes)
271+{
272+ for (std::size_t n = 0; n < nbStripes; ++n) {
273+ Accumulate512(acc, input + (n * XXH_STRIPE_LEN), secret + (n * XXH_SECRET_CONSUME_RATE));
274+ }
275+}
276+ 
277+static inline uint64_t Mix2Accs(const uint64_t *acc, const uint8_t *secret)
278+{
279+ return Mul128Fold64(acc[0] ^ Read64LE(secret), acc[1] ^ Read64LE(secret + 8));
280+}
281+ 
282+static inline uint64_t MergeAccs(const uint64_t *acc, const uint8_t *secret, uint64_t start)
283+{
284+ uint64_t result = start;
285+ for (std::size_t i = 0; i < 4; ++i) {
286+ result += Mix2Accs(acc + (2 * i), secret + (16 * i));
287+ }
288+ return XXH3Avalanche(result);
289+}
290+ 
291+static inline uint64_t HashLong(const uint8_t *input, std::size_t len, const uint8_t *secret,
292+ std::size_t secretSize)
293+{
294+ const std::size_t nbStripesPerBlock = (secretSize - XXH_STRIPE_LEN) / XXH_SECRET_CONSUME_RATE;
295+ const std::size_t blockLen = XXH_STRIPE_LEN * nbStripesPerBlock;
296+ const std::size_t nbBlocks = (len - 1) / blockLen;
297+ alignas(16) uint64_t acc[XXH_ACC_NB] = {
298+ PRIME32_3, PRIME64_1, PRIME64_2, PRIME64_3,
299+ PRIME64_4, PRIME32_2, PRIME64_5, PRIME32_1,
300+ };
301+ 
302+ for (std::size_t n = 0; n < nbBlocks; ++n) {
303+ Accumulate(acc, input + (n * blockLen), secret, nbStripesPerBlock);
304+ ScrambleAcc(acc, secret + secretSize - XXH_STRIPE_LEN);
305+ }
306+ 
307+ const std::size_t nbStripes = (len - 1 - (blockLen * nbBlocks)) / XXH_STRIPE_LEN;
308+ Accumulate(acc, input + (nbBlocks * blockLen), secret, nbStripes);
309+ Accumulate512(acc, input + len - XXH_STRIPE_LEN,
310+ secret + secretSize - XXH_STRIPE_LEN - XXH_SECRET_LASTACC_START);
311+ return MergeAccs(acc, secret + XXH_SECRET_MERGEACCS_START, static_cast<uint64_t>(len) * PRIME64_1);
312+}
313+ 
314+static inline uint64_t XXH3_64bitsImpl(const void *input, std::size_t length)
315+{
316+ const uint8_t *data = static_cast<const uint8_t *>(input);
317+ if (length <= 16) {
318+ return Len0To16(data, length, XXH3_K_SECRET);
319+ }
320+ if (length <= 128) {
321+ return Len17To128(data, length, XXH3_K_SECRET);
322+ }
323+ if (length <= XXH3_MIDSIZE_MAX) {
324+ return Len129To240(data, length, XXH3_K_SECRET);
325+ }
326+ return HashLong(data, length, XXH3_K_SECRET, sizeof(XXH3_K_SECRET));
327+}
328+} // namespace asccomm_xxh3_detail
329+ 
330+static inline uint64_t XXH3_64bits(const void *input, std::size_t length)
331+{
332+ return asccomm_xxh3_detail::XXH3_64bitsImpl(input, length);
333+}
@@ -164,6 +164,8 @@ add_custom_target(prepare_asccomm_ut_header_layout
164 DEPENDS ${ASCCOMM_UT_STAGE_STAMP}164 DEPENDS ${ASCCOMM_UT_STAGE_STAMP}
165)165)
166 166 
167+set(ASCCOMM_COVERAGE_SCRIPT ${ASCCOMM_ROOT}/scripts/generate_cpp_cov.sh)
168+ 
167function(run_llt_test)169function(run_llt_test)
168 cmake_parse_arguments(LLT "" "TARGET;TASK_NUM;ENV_FILE" "FILTERS;RUNTIME_DIRS" ${ARGN})170 cmake_parse_arguments(LLT "" "TARGET;TASK_NUM;ENV_FILE" "FILTERS;RUNTIME_DIRS" ${ARGN})
169 171 
@@ -224,7 +226,53 @@ function(run_llt_test)
224 )226 )
225endfunction()227endfunction()
226 228 
227-set(ASCCOMM_COVERAGE_SCRIPT ${ASCCOMM_ROOT}/scripts/generate_cpp_cov.sh)229+add_library(asccomm_ccu_host_launch STATIC
230+ ${ASCCOMM_ROOT}/src/ccu/ccu_host_launch.cpp
231+)
232+target_include_directories(asccomm_ccu_host_launch
233+ PUBLIC
234+ ${ASCCOMM_ROOT}/include
235+ PRIVATE
236+ ${ASCEND_CANN_ARCH_DIR}/include
237+ ${ASCEND_CANN_ARCH_DIR}/include/hcomm/ccu
238+ ${ASCEND_CANN_ARCH_DIR}/include/hccl
239+ ${ASCEND_CANN_ARCH_DIR}/pkg_inc
240+ ${ASCEND_CANN_ARCH_DIR}/pkg_inc/runtime
241+)
242+target_compile_features(asccomm_ccu_host_launch PUBLIC cxx_std_17)
243+target_compile_options(asccomm_ccu_host_launch PRIVATE
244+ -fPIC
245+ -Wall
246+ -Werror
247+)
248+ 
249+add_executable(asccomm_ut_ccu_host_launch
250+ ${ASCCOMM_UT_ROOT}/ccu/test_ccu_host_launch.cpp
251+)
252+target_include_directories(asccomm_ut_ccu_host_launch PRIVATE
253+ ${ASCCOMM_ROOT}/include
254+ ${ASCEND_CANN_ARCH_DIR}/include
255+ ${ASCEND_CANN_ARCH_DIR}/include/hcomm/ccu
256+ ${ASCEND_CANN_ARCH_DIR}/include/hccl
257+ ${ASCEND_CANN_ARCH_DIR}/pkg_inc
258+ ${ASCEND_CANN_ARCH_DIR}/pkg_inc/runtime
259+)
260+target_compile_features(asccomm_ut_ccu_host_launch PRIVATE cxx_std_17)
261+target_compile_options(asccomm_ut_ccu_host_launch PRIVATE
262+ -fPIC
263+ -Wall
264+ -Werror
265+)
266+target_link_libraries(asccomm_ut_ccu_host_launch PRIVATE
267+ intf_llt_pub_basic
268+ asccomm_ccu_host_launch
269+)
270+ 
271+run_llt_test(
272+ TARGET asccomm_ut_ccu_host_launch
273+ TASK_NUM 1
274+ FILTERS TestCcuHostLaunch.*
275+)
228 276 
229function(asccomm_add_product_definitions target_name product_type)277function(asccomm_add_product_definitions target_name product_type)
230 target_compile_definitions(${target_name} PRIVATE278 target_compile_definitions(${target_name} PRIVATE
@@ -0,0 +1,142 @@
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+#include <gtest/gtest.h>
12+ 
13+#include <vector>
14+ 
15+#include "ccu/ccu_host_launch.h"
16+ 
17+namespace {
18+constexpr uint32_t CCU_SQE_ARGS_LEN = 13;
19+ 
20+void DummyKernel(void*) {}
21+ 
22+asccomm_launch_kernel_cfg MakeLaunchCfg()
23+{
24+ asccomm_launch_kernel_cfg cfg{};
25+ cfg.ccu_schd = {1, 0, 0x01, 0};
26+ cfg.ccu_ins = 0x11;
27+ cfg.stream = reinterpret_cast<aclrtStream>(0x22);
28+ cfg.attrs = nullptr;
29+ return cfg;
30+}
31+} // namespace
32+ 
33+int32_t HcclGetThreadDeviceId() { return 0; }
34+ 
35+extern "C" int rtCCULaunch(void*, void* const) { return 0; }
36+ 
37+namespace hcomm {
38+struct CcuTaskParam {
39+ uint8_t dieId;
40+ uint8_t missionId;
41+ uint16_t timeout;
42+ uint32_t instStartId;
43+ uint32_t instCnt;
44+ uint32_t key;
45+ uint32_t argSize;
46+ uint64_t args[CCU_SQE_ARGS_LEN];
47+};
48+ 
49+class CcuKernel {
50+public:
51+ CcuResult GeneTaskParams(const uint64_t*, uint32_t, std::vector<CcuTaskParam>& taskParams);
52+};
53+ 
54+class CcuKernelMgr {
55+public:
56+ static CcuKernelMgr& GetInstance(int32_t);
57+ 
58+ CcuKernel* GetKernel(CcuKernelHandle);
59+};
60+ 
61+CcuResult CcuKernel::GeneTaskParams(const uint64_t*, uint32_t, std::vector<CcuTaskParam>& taskParams)
62+{
63+ taskParams.push_back({});
64+ return CCU_SUCCESS;
65+}
66+ 
67+CcuKernelMgr& CcuKernelMgr::GetInstance(int32_t)
68+{
69+ static CcuKernelMgr mgr;
70+ return mgr;
71+}
72+ 
73+CcuKernel* CcuKernelMgr::GetKernel(CcuKernelHandle)
74+{
75+ static CcuKernel kernel;
76+ return &kernel;
77+}
78+} // namespace hcomm
79+ 
80+class TestCcuHostLaunch : public testing::Test {};
81+ 
82+TEST_F(TestCcuHostLaunch, NullArgumentsReturnPtr)
83+{
84+ asccomm_launch_kernel_cfg cfg = MakeLaunchCfg();
85+ uint64_t args[] = {1, 2, 3};
86+ 
87+ EXPECT_EQ(asccomm_ccu_host_kernel_launch(nullptr, &cfg, args), CCU_E_PTR);
88+ EXPECT_EQ(asccomm_ccu_host_kernel_launch(reinterpret_cast<const void*>(DummyKernel), nullptr, args), CCU_E_PTR);
89+ EXPECT_EQ(asccomm_ccu_host_kernel_launch(reinterpret_cast<const void*>(DummyKernel), &cfg, nullptr), CCU_E_PTR);
90+ EXPECT_EQ(HcommCcuHostKernelLaunch(reinterpret_cast<const void*>(DummyKernel), nullptr, args), CCU_E_PTR);
91+}
92+ 
93+TEST_F(TestCcuHostLaunch, UnsupportedDieMaskReturnsPara)
94+{
95+ asccomm_launch_kernel_cfg cfg = MakeLaunchCfg();
96+ uint64_t args[] = {1, 2, 3};
97+ 
98+ cfg.ccu_schd.phy_die_mask = 0;
99+ EXPECT_EQ(asccomm_ccu_host_kernel_launch(reinterpret_cast<const void*>(DummyKernel), &cfg, args), CCU_E_PARA);
100+ 
101+ cfg.ccu_schd.phy_die_mask = 0x03;
102+ EXPECT_EQ(asccomm_ccu_host_kernel_launch(reinterpret_cast<const void*>(DummyKernel), &cfg, args), CCU_E_PARA);
103+ 
104+ HcommLaunchKernelCfg hcommCfg{};
105+ hcommCfg.ccuSchd.numBlocks = cfg.ccu_schd.num_blocks;
106+ hcommCfg.ccuSchd.reserved = cfg.ccu_schd.reserved;
107+ hcommCfg.ccuSchd.phyDieMask = cfg.ccu_schd.phy_die_mask;
108+ hcommCfg.ccuSchd.binaryCacheTag = cfg.ccu_schd.binary_cache_tag;
109+ hcommCfg.ccuIns = cfg.ccu_ins;
110+ hcommCfg.stream = cfg.stream;
111+ hcommCfg.attrs = cfg.attrs;
112+ EXPECT_EQ(HcommCcuHostKernelLaunch(reinterpret_cast<const void*>(DummyKernel), &hcommCfg, args), CCU_E_PARA);
113+}
114+ 
115+TEST_F(TestCcuHostLaunch, UnsupportedNumBlocksReturnsPara)
116+{
117+ asccomm_launch_kernel_cfg cfg = MakeLaunchCfg();
118+ uint64_t args[] = {1, 2, 3};
119+ 
120+ cfg.ccu_schd.num_blocks = 0;
121+ EXPECT_EQ(asccomm_ccu_host_kernel_launch(reinterpret_cast<const void*>(DummyKernel), &cfg, args), CCU_E_PARA);
122+ 
123+ cfg.ccu_schd.num_blocks = 2;
124+ EXPECT_EQ(asccomm_ccu_host_kernel_launch(reinterpret_cast<const void*>(DummyKernel), &cfg, args), CCU_E_PARA);
125+}
126+ 
127+TEST_F(TestCcuHostLaunch, LaunchHashTagReturnsStableNonZeroValue)
128+{
129+ const uint64_t tag = asccomm_ccu_get_launch_hash_tag("CcuAllGatherMesh1DMem2MemKernel");
130+ 
131+ EXPECT_EQ(asccomm_ccu_get_launch_hash_tag(nullptr), 0U);
132+ EXPECT_NE(tag, 0U);
133+ EXPECT_EQ(tag, asccomm_ccu_get_launch_hash_tag("CcuAllGatherMesh1DMem2MemKernel"));
134+ EXPECT_NE(tag, asccomm_ccu_get_launch_hash_tag("CcuAllGatherMesh1DMem2MemKernel_rank_1"));
135+ EXPECT_EQ(tag, HcommCcuGetLaunchHashTag("CcuAllGatherMesh1DMem2MemKernel"));
136+}
137+ 
138+int main(int argc, char** argv)
139+{
140+ testing::InitGoogleTest(&argc, argv);
141+ return RUN_ALL_TESTS();
142+}