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 :
11 : #include <iostream>
12 : #include <fstream>
13 : #include <string>
14 : #include "launch_device_v2.h"
15 : #include "log.h"
16 : #include "mmpa_api.h"
17 : #include "sal.h"
18 : #include "exception_util.h"
19 : #include "invalid_params_exception.h"
20 : #include "runtime_api_exception.h"
21 : #include "hccl/base.h"
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(
39 : const char* binPath, aclrtBinaryLoadOptionType optionType, uint32_t cpuKernelMode, aclrtBinHandle& binHandle)
40 : {
41 68 : if (binPath == nullptr) {
42 0 : THROW<InvalidParamsException>(StringFormat("[LoadBinaryFromFile]binary path is nullptr", binPath));
43 : }
44 68 : char realPath[PATH_MAX] = {0};
45 68 : if (realpath(binPath, realPath) == nullptr) {
46 0 : THROW<InvalidParamsException>(StringFormat(
47 : "[LoadBinaryFromFile]binPath:%s is not a valid real path,"
48 : "err[%d]",
49 0 : binPath, errno));
50 : }
51 204 : HCCL_INFO("[LoadBinaryFromFile]realPath: %s", realPath);
52 :
53 68 : aclrtBinaryLoadOptions loadOptions = {};
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 0 : THROW<RuntimeApiException>(
63 0 : StringFormat("[LoadBinaryFromFile]:errNo[0x%016llx]load binary from file error.", aclRet));
64 : }
65 68 : }
66 :
67 848 : AicpuBinaryHolder::AicpuBinaryHolder() : handle_(nullptr), loaded_(false) {}
68 :
69 848 : AicpuBinaryHolder::~AicpuBinaryHolder() noexcept { Unload(); }
70 :
71 : namespace {
72 : struct LoadCleanupGuard {
73 67 : explicit LoadCleanupGuard(AicpuBinaryHolder& holder) : holder_(holder), active_(true) {}
74 :
75 67 : ~LoadCleanupGuard()
76 : {
77 67 : if (active_) {
78 0 : holder_.Unload();
79 : }
80 67 : }
81 :
82 67 : void Dismiss() { active_ = false; }
83 :
84 : AicpuBinaryHolder& holder_;
85 : bool active_;
86 : };
87 : } // namespace
88 :
89 67 : void AicpuBinaryHolder::Load()
90 : {
91 67 : if (loaded_) {
92 0 : HCCL_WARNING("[AicpuBinaryHolder::%s] has registered aicpu kernel, skip register again.", __func__);
93 0 : return;
94 : }
95 201 : HCCL_INFO("[AicpuBinaryHolder::%s] start.", __func__);
96 67 : std::string jsonPath;
97 67 : GetKernelFilePath(jsonPath);
98 67 : jsonPath += "ccl_kernel.json";
99 67 : aclrtBinHandle tempHandle = nullptr;
100 67 : LoadBinaryFromFile(jsonPath.c_str(), ACL_RT_BINARY_LOAD_OPT_CPU_KERNEL_MODE, 0, tempHandle);
101 67 : handle_ = tempHandle;
102 67 : loaded_ = true; // 提前设置loaded_为true,确保下方触发异常后aicpuKernelGuard里面能正确释放handle_资源
103 67 : LoadCleanupGuard aicpuKernelGuard(*this);
104 201 : HCCL_INFO("[AicpuBinaryHolder::%s] LoadBinaryFromFile success [%s]", __func__, jsonPath.c_str());
105 : // register base Func
106 67 : constexpr std::array<const char*, 3> kernelFunction{
107 : "HcclKernelEntrance", "HcclUpdateCommKernelEntrance", "HcclDpuTaskexpShmemRestore"};
108 268 : for (const auto& kernelName : kernelFunction) {
109 201 : if (strlen(kernelName) == 0 || strlen(kernelName) >= KERNEL_PARAM_NAME_SIZE) {
110 0 : HCCL_ERROR("[AicpuBinaryHolder::%s] invalid kernel name", __func__);
111 0 : THROW<InvalidParamsException>("kernel name is invalid");
112 : }
113 : aclrtFuncHandle funcHandle;
114 201 : const aclError aclRet = aclrtBinaryGetFunction(handle_, kernelName, &funcHandle);
115 201 : if (aclRet != ACL_SUCCESS) {
116 0 : THROW<RuntimeApiException>(StringFormat("Call aclrtBinaryGetFunction failed, with ret[%d]", aclRet));
117 : }
118 603 : HCCL_INFO("[AicpuBinaryHolder::%s] getting funcHandle for kernel[%s]", __func__, kernelName);
119 201 : const std::string kernelNameStr = std::string(kernelName);
120 201 : aicpuFuncMap_[kernelNameStr] = funcHandle;
121 201 : }
122 67 : aicpuKernelGuard.Dismiss();
123 201 : HCCL_INFO("[AicpuBinaryHolder::%s] end.", __func__);
124 67 : }
125 848 : void AicpuBinaryHolder::Unload()
126 : {
127 848 : if (loaded_ && handle_ != nullptr) {
128 0 : const aclError aclRet = aclrtBinaryUnLoad(handle_);
129 0 : if (aclRet != ACL_SUCCESS) {
130 0 : HCCL_ERROR("[~AicpuBinaryHolder] failed to unload binary, ret[%d]", aclRet);
131 : }
132 0 : handle_ = nullptr;
133 0 : loaded_ = false;
134 0 : aicpuFuncMap_.clear();
135 : }
136 848 : }
137 6 : aclrtFuncHandle AicpuBinaryHolder::GetAicpuKernelFuncHandle(const char* kernelName) const
138 : {
139 6 : if (kernelName == nullptr || strlen(kernelName) == 0 || strlen(kernelName) >= KERNEL_PARAM_NAME_SIZE) {
140 0 : HCCL_ERROR("[AicpuBinaryHolder::%s] invalid kernel name", __func__);
141 0 : THROW<InvalidParamsException>("kernel name is invalid");
142 : }
143 6 : if (!loaded_) {
144 0 : HCCL_ERROR("[AicpuBinaryHolder::%s] aicpu kernel not registered, kernelName[%s]", __func__, kernelName);
145 0 : THROW<RuntimeApiException>("aicpu kernel not registered");
146 : }
147 6 : const auto kernelNameStr = std::string(kernelName);
148 6 : const auto it = aicpuFuncMap_.find(kernelNameStr);
149 6 : if (it == aicpuFuncMap_.end()) {
150 0 : HCCL_ERROR("[AicpuBinaryHolder::%s] function handle of kernelName[%s] is not get before", __func__, kernelName);
151 0 : THROW<RuntimeApiException>(StringFormat("function handle of kernelName[%s] is not get before", kernelName));
152 : }
153 12 : return it->second;
154 6 : }
155 : } // namespace Hccl
|