Line data Source code
1 : /**
2 : * Copyright (c) 2025 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 : #include "launch_context.h"
11 : #include "new/hccl_primitive_local.h"
12 :
13 : constexpr u32 THREAD_VECTOR_DEFAULT_SIZE = 128; // 设置vector初始长度,避免频繁扩容
14 : constexpr u32 NOTIFY_WAIT_TIMEOUT_OFFSET = 27; // AICPU device侧notify等待超时偏移量
15 :
16 : extern HcclResult CommTaskLaunch(ThreadHandle* threads, uint32_t threadNum); // host ffts+或aicpu stars使用"
17 : extern HcclResult CommTaskPrepare(char* key, uint32_t keyLen); // host ffts+使用
18 : extern HcclResult DispatchAllStreams(ThreadHandle* threads, uint32_t threadNum);
19 :
20 5 : LaunchContext::LaunchContext() { threadVec_.reserve(THREAD_VECTOR_DEFAULT_SIZE); }
21 :
22 1 : HcclResult LaunchContext::HandleEagerMode()
23 : {
24 : // 带launchTag部分
25 1 : if (!launchModeMap_.empty()) {
26 1 : auto it = launchModeMap_.find(launchTag_);
27 1 : if (it != launchModeMap_.end()) {
28 1 : std::vector<ThreadHandle> threadVec(it->second.begin(), it->second.end());
29 1 : CHK_RET(CommTaskLaunch(threadVec.data(), threadVec.size()));
30 1 : HCCL_INFO("[%s]success, launchTag[%s], size[%zu]", __func__, launchTag_.c_str(), threadVec.size());
31 1 : }
32 : }
33 :
34 : // 不带launchTag部分
35 1 : if (!threadVec_.empty()) {
36 1 : CHK_RET(CommTaskLaunch(threadVec_.data(), threadVec_.size()));
37 1 : HCCL_INFO("[%s]success, size[%zu]", __func__, threadVec_.size());
38 : }
39 1 : return HCCL_SUCCESS;
40 : }
41 :
42 2 : HcclResult LaunchContext::HandleDispatchAllStreams()
43 : {
44 : // 带launchTag部分
45 2 : if (!launchModeMap_.empty()) {
46 1 : auto it = launchModeMap_.find(launchTag_);
47 1 : if (it != launchModeMap_.end()) {
48 1 : std::vector<ThreadHandle> threadVec(it->second.begin(), it->second.end());
49 1 : CHK_RET(DispatchAllStreams(threadVec.data(), threadVec.size()));
50 1 : }
51 : }
52 :
53 : // 不带launchTag部分
54 2 : if (!threadVec_.empty()) {
55 1 : CHK_RET(DispatchAllStreams(threadVec_.data(), threadVec_.size()));
56 : }
57 2 : return HCCL_SUCCESS;
58 : }
59 :
60 2 : HcclResult LaunchContext::HandleClear()
61 : {
62 2 : threadVec_.clear();
63 2 : if (!launchModeMap_.empty()) {
64 2 : launchModeMap_.erase(launchTag_);
65 : }
66 2 : HCCL_INFO(
67 : "[%s] begin clear, launchTag[%s], launchMode[%d].", __func__, launchTag_.c_str(), static_cast<int32_t>(mode_));
68 :
69 2 : DevType devType = DevType::DEV_TYPE_COUNT;
70 2 : hrtGetDeviceType(devType);
71 2 : if (devType == DevType::DEV_TYPE_950 || devType == DevType::DEV_TYPE_960) {
72 2 : HCCL_INFO("[%s] Running on A5/A6, HcclTaskClear skipped.", __func__);
73 2 : return HCCL_SUCCESS;
74 : }
75 0 : return HcclTaskClear(launchTag_);
76 : }
77 :
78 5 : HcclResult LaunchContext::SetNotifyWaitTimeOut(uint32_t timeout)
79 : {
80 5 : notifyWaitTimeoutConfig_.notifyWaitTimeout = timeout;
81 5 : notifyWaitTimeoutConfig_.isSet = true;
82 5 : return HCCL_SUCCESS;
83 : }
84 :
85 5 : HcclResult LaunchContext::GetNotifyWaitTimeOut(uint32_t& timeout)
86 : {
87 5 : timeout = notifyWaitTimeoutConfig_.notifyWaitTimeout;
88 : #ifndef CCL_KERNEL_AICPU
89 5 : if (!notifyWaitTimeoutConfig_.isSet) {
90 0 : timeout = timeout + NOTIFY_WAIT_TIMEOUT_OFFSET;
91 : }
92 : #endif
93 5 : return HCCL_SUCCESS;
94 : }
95 :
96 3 : HcclResult LaunchContext::SetSqFullTimeOut(uint32_t timeout)
97 : {
98 3 : sqFullTimeoutConfig_.sqFullTimeout = timeout;
99 3 : sqFullTimeoutConfig_.isSet = true;
100 3 : return HCCL_SUCCESS;
101 : }
102 :
103 0 : uint32_t LaunchContext::GetSqFullTimeOut() { return sqFullTimeoutConfig_.sqFullTimeout; }
104 :
105 : /*
106 : 1 AICPU_TS模式
107 : AICPU上执行
108 : 告知后面的CommWrite等任务进入批量模式,(只写任务的SQE,但是不触发执行)
109 : 举例:
110 : HcommSetLaunchMode("abc", HCOMM_LAUNCH_MODE_BATCH);
111 : HcommAclrtNotifyWaitOnThread(thread, notifyId, 0);
112 : HcommAclrtNotifyRecordOnThread(thread, notifyId);
113 : HcommSetLaunchMode("abc", HCOMM_LAUNCH_MODE_EAGER);
114 :
115 : 2 CPU_TS模式
116 : FFTS+子图,最后批量提交。在HOST CPU上执行
117 : 告知后面的CommWrite等任务进入批量模式(开始ffts+子图)
118 :
119 : 1)复用task子图缓存
120 : 增加 launchTag 的原因,进入批量模式之后,缓存要执行的一些task,最后提交。缓
121 : 存的标识采用launchTag。在第二次执行想要复用子图执行时,只需要拿着相同的
122 : launchTag,调用 HcommSetLaunchMode接口,传入HCOMM_LAUNCH_MODE_EAGER参数,即可复用执行。
123 : 比如下面的: HcommSetLaunchMode ("abc", HCOMM_LAUNCH_MODE_EAGER);
124 : 执行之前缓存到"abc"下的几个数据面操作。
125 :
126 : 2)清理
127 : 如果不需要"abc"标识的这个子图的task 缓存了,可以采用如下方式清理该子图内容:
128 : HcommSetLaunchMode ("abc", HCOMM_LAUNCH_MODE_RESERVED)
129 :
130 : 3)缺省 launchTag
131 : launchTag 如果为 nullptr,表示缺省值,标识不需要缓存到 FFTS+子图。
132 : */
133 2 : HcclResult LaunchContext::SetLaunchMode(const char* launchTag, HcommLaunchMode mode)
134 : {
135 2 : mode_ = mode;
136 : // 统一处理 launchTag
137 2 : bool defaultTag = (launchTag == nullptr);
138 6 : launchTag_ = defaultTag ? "" : std::string(launchTag);
139 2 : HCCL_INFO(
140 : "[%s] SetLaunchMode begin, launchTag[%s], launchMode[%d].", __func__, launchTag_.c_str(),
141 : static_cast<int32_t>(mode));
142 :
143 : #ifndef CCL_KERNEL_AICPU
144 2 : DevType devType = DevType::DEV_TYPE_COUNT;
145 : #endif
146 2 : switch (mode_) {
147 2 : case HCOMM_LAUNCH_MODE_BATCH:
148 : #ifndef CCL_KERNEL_AICPU
149 2 : hrtGetDeviceType(devType);
150 2 : if (devType == DevType::DEV_TYPE_950 || devType == DevType::DEV_TYPE_960) {
151 2 : HCCL_INFO("[%s] Running on A5, CommTaskPrepare skipped.", __func__);
152 2 : return HCCL_SUCCESS;
153 : }
154 0 : HCCL_INFO("[%s]host mode, need CommTaskPrepare", __func__);
155 0 : if (!defaultTag) {
156 : // 仅非缺省 tag 需要准备任务缓存
157 0 : return CommTaskPrepare(const_cast<char*>(launchTag_.c_str()), launchTag_.length());
158 : }
159 : #endif
160 0 : return HCCL_SUCCESS;
161 0 : case HCOMM_LAUNCH_MODE_EAGER:
162 0 : CHK_RET(HandleEagerMode());
163 : // 缺省 tag 模式下清理缓存
164 0 : return HandleClear();
165 0 : case HCOMM_LAUNCH_MODE_RESERVED:
166 0 : if (!defaultTag) {
167 0 : return HandleClear();
168 : }
169 0 : return HCCL_SUCCESS;
170 0 : default:
171 0 : return HCCL_SUCCESS;
172 : }
173 : }
|