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 <iostream>
11 : #include <fstream>
12 : #include <string>
13 : #include "launch_device.h"
14 : #include "log.h"
15 : #include "mmpa_api.h"
16 : #include "sal.h"
17 : #include "exception_util.h"
18 : #include "invalid_params_exception.h"
19 : #include "runtime_api_exception.h"
20 : #include "hccl/base.h"
21 :
22 :
23 : using namespace std;
24 :
25 : namespace Hccl {
26 67 : void GetKernelFilePath(std::string &binaryPath)
27 : {
28 67 : std::string libPath = SalGetEnv("ASCEND_HOME_PATH");
29 67 : if (libPath.empty() || libPath == "EmptyString") {
30 0 : HCCL_WARNING("[GetKernelFilePath]ENV:ASCEND_HOME_PATH is not set, use default:/usr/local/Ascend/cann/");
31 0 : libPath = "/usr/local/Ascend/cann/";
32 : }
33 67 : libPath += "/opp/built-in/op_impl/aicpu/config/";
34 67 : binaryPath = libPath;
35 201 : HCCL_DEBUG("[GetKernelFilePath]kernel folder path[%s]", binaryPath.c_str());
36 67 : }
37 :
38 68 : void LoadBinaryFromFile(const char *binPath, aclrtBinaryLoadOptionType optionType, uint32_t cpuKernelMode,
39 : aclrtBinHandle &binHandle)
40 : {
41 68 : if(binPath == nullptr)
42 : {
43 0 : THROW<InvalidParamsException>(StringFormat("[LoadBinaryFromFile]binary path is nullptr", binPath));
44 : }
45 68 : char realPath[PATH_MAX] = {0};
46 68 : if(realpath(binPath, realPath) == nullptr)
47 : {
48 0 : THROW<InvalidParamsException>(StringFormat("[LoadBinaryFromFile]binPath:%s is not a valid real path,"
49 0 : "err[%d]", binPath,errno));
50 : }
51 204 : HCCL_INFO("[LoadBinaryFromFile]realPath: %s", realPath);
52 :
53 68 : aclrtBinaryLoadOptions loadOptions = {0};
54 : aclrtBinaryLoadOption option;
55 68 : loadOptions.numOpt = 1;
56 68 : loadOptions.options = &option;
57 68 : option.type = optionType;
58 68 : option.value.cpuKernelMode = cpuKernelMode;
59 : // ACL_RT_BINARY_LOAD_OPT_CPU_KERNEL_MODE
60 68 : aclError aclRet = aclrtBinaryLoadFromFile(realPath, &loadOptions, &binHandle);
61 68 : if(aclRet != ACL_SUCCESS)
62 : {
63 0 : THROW<RuntimeApiException>(StringFormat("[LoadBinaryFromFile]:errNo[0x%016llx]load binary from file error.",
64 : aclRet));
65 : }
66 68 : }
67 :
68 846 : AicpuBinaryHolder::AicpuBinaryHolder(): handle_(nullptr), loaded_(false)
69 : {
70 846 : }
71 :
72 846 : AicpuBinaryHolder::~AicpuBinaryHolder() noexcept
73 : {
74 846 : Unload();
75 846 : }
76 :
77 : namespace {
78 : struct LoadCleanupGuard {
79 67 : explicit LoadCleanupGuard(AicpuBinaryHolder &holder) : holder_(holder), active_(true)
80 : {
81 67 : }
82 :
83 67 : ~LoadCleanupGuard()
84 : {
85 67 : if (active_) {
86 0 : holder_.Unload();
87 : }
88 67 : }
89 :
90 67 : void Dismiss()
91 : {
92 67 : active_ = false;
93 67 : }
94 :
95 : AicpuBinaryHolder &holder_;
96 : bool active_;
97 : };
98 : } // namespace
99 :
100 67 : void AicpuBinaryHolder::Load()
101 : {
102 67 : if(loaded_)
103 : {
104 0 : HCCL_WARNING("[AicpuBinaryHolder::%s] has registered aicpu kernel, skip register again.", __func__);
105 0 : return;
106 : }
107 201 : HCCL_INFO("[AicpuBinaryHolder::%s] start.", __func__);
108 67 : std::string jsonPath;
109 67 : GetKernelFilePath(jsonPath);
110 67 : jsonPath += "ccl_kernel.json";
111 67 : aclrtBinHandle tempHandle = nullptr;
112 67 : LoadBinaryFromFile(jsonPath.c_str(),
113 : ACL_RT_BINARY_LOAD_OPT_CPU_KERNEL_MODE,
114 : 0,
115 : tempHandle);
116 67 : handle_ = tempHandle;
117 67 : loaded_ = true; // 提前设置loaded_为true,确保下方触发异常后aicpuKernelGuard里面能正确释放handle_资源
118 67 : LoadCleanupGuard aicpuKernelGuard(*this);
119 201 : HCCL_INFO("[AicpuBinaryHolder::%s] LoadBinaryFromFile success [%s]", __func__, jsonPath.c_str());
120 : //register base Func
121 67 : constexpr std::array<const char *, 3> kernelFunction{
122 : "HcclKernelEntrance", "HcclUpdateCommKernelEntrance", "HcclDpuTaskexpShmemRestore"};
123 268 : for (const auto &kernelName : kernelFunction) {
124 201 : if (strlen(kernelName) == 0 ||
125 201 : strlen(kernelName) >= KERNEL_PARAM_NAME_SIZE) {
126 0 : HCCL_ERROR("[AicpuBinaryHolder::%s] invalid kernel name", __func__);
127 0 : THROW<InvalidParamsException>("kernel name is invalid");
128 : }
129 : aclrtFuncHandle funcHandle;
130 : const aclError aclRet =
131 201 : aclrtBinaryGetFunction(handle_, kernelName, &funcHandle);
132 201 : if (aclRet != ACL_SUCCESS) {
133 0 : THROW<RuntimeApiException>(StringFormat(
134 : "Call aclrtBinaryGetFunction failed, with ret[%d]", aclRet));
135 : }
136 603 : HCCL_INFO("[AicpuBinaryHolder::%s] getting funcHandle for kernel[%s]",
137 : __func__, kernelName);
138 201 : const std::string kernelNameStr = std::string(kernelName);
139 201 : aicpuFuncMap_[kernelNameStr] = funcHandle;
140 201 : }
141 67 : aicpuKernelGuard.Dismiss();
142 201 : HCCL_INFO("[AicpuBinaryHolder::%s] end.", __func__);
143 67 : }
144 846 : void AicpuBinaryHolder::Unload()
145 : {
146 846 : if (loaded_ && handle_ != nullptr)
147 : {
148 0 : const aclError aclRet = aclrtBinaryUnLoad(handle_);
149 0 : if (aclRet != ACL_SUCCESS) {
150 0 : HCCL_ERROR("[~AicpuBinaryHolder] failed to unload binary, ret[%d]", aclRet);
151 : }
152 0 : handle_ = nullptr;
153 0 : loaded_ = false;
154 0 : aicpuFuncMap_.clear();
155 : }
156 846 : }
157 6 : aclrtFuncHandle AicpuBinaryHolder::GetAicpuKernelFuncHandle(const char* kernelName) const
158 : {
159 6 : if (kernelName == nullptr || strlen(kernelName) == 0 || strlen(kernelName) >= KERNEL_PARAM_NAME_SIZE) {
160 0 : HCCL_ERROR("[AicpuBinaryHolder::%s] invalid kernel name", __func__);
161 0 : THROW<InvalidParamsException>("kernel name is invalid");
162 : }
163 6 : if (!loaded_) {
164 0 : HCCL_ERROR("[AicpuBinaryHolder::%s] aicpu kernel not registered, kernelName[%s]", __func__, kernelName);
165 0 : THROW<RuntimeApiException>("aicpu kernel not registered");
166 : }
167 6 : const auto kernelNameStr = std::string(kernelName);
168 6 : const auto it = aicpuFuncMap_.find(kernelNameStr);
169 6 : if (it == aicpuFuncMap_.end()) {
170 0 : HCCL_ERROR("[AicpuBinaryHolder::%s] function handle of kernelName[%s] is not get before", __func__, kernelName);
171 0 : THROW<RuntimeApiException>(StringFormat("function handle of kernelName[%s] is not get before", kernelName));
172 : }
173 12 : return it->second;
174 6 : }
175 : } // namespace Hccl
|