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