1 /**
2 * Copyright 2023 Huawei Technologies Co., Ltd
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "transform/acl_ir/op_api_exec.h"
18 #include <dirent.h>
19 #include <sys/stat.h>
20 #include <unistd.h>
21 #include <iostream>
22 #include <vector>
23 #include <string>
24
25 namespace mindspore::transform {
26 namespace {
27 using InitHugeMemThreadLocalCast = int (*)(void *, bool);
28 using UnInitHugeMemThreadLocalCast = void (*)(void *, bool);
29 using ReleaseHugeMemCast = void (*)(void *, bool);
30 } // namespace
31
32 static std::mutex init_mutex;
33 static bool aclnn_init = false;
34 std::vector<std::pair<void *, std::string>> opapi_lib_handle;
35
GetInstance()36 OpApiDefaultResource &OpApiDefaultResource::GetInstance() {
37 static OpApiDefaultResource instance;
38 return instance;
39 }
40
init_mem_func()41 InitHugeMemThreadLocal OpApiDefaultResource::init_mem_func() {
42 if (init_mem_func_ != nullptr) {
43 return init_mem_func_;
44 }
45 auto init_mem_func = GetOpApiFunc("InitHugeMemThreadLocal");
46 if (init_mem_func == nullptr) {
47 MS_LOG(EXCEPTION) << "InitHugeMemThreadLocal not in " << GetOpApiLibName() << ", please check!";
48 }
49 init_mem_func_ = reinterpret_cast<InitHugeMemThreadLocalCast>(init_mem_func);
50 return init_mem_func_;
51 }
52
uninit_mem_func()53 UnInitHugeMemThreadLocal OpApiDefaultResource::uninit_mem_func() {
54 if (uninit_mem_func_ != nullptr) {
55 return uninit_mem_func_;
56 }
57 auto uninit_mem_func = GetOpApiFunc("UnInitHugeMemThreadLocal");
58 if (uninit_mem_func == nullptr) {
59 MS_LOG(EXCEPTION) << "UnInitHugeMemThreadLocal not in " << GetOpApiLibName() << ", please check!";
60 }
61 uninit_mem_func_ = reinterpret_cast<UnInitHugeMemThreadLocalCast>(uninit_mem_func);
62 return uninit_mem_func_;
63 }
64
release_mem_func()65 ReleaseHugeMem OpApiDefaultResource::release_mem_func() {
66 if (release_mem_func_ != nullptr) {
67 return release_mem_func_;
68 }
69 auto release_mem_func = GetOpApiFunc("ReleaseHugeMem");
70 if (release_mem_func == nullptr) {
71 MS_LOG(EXCEPTION) << "ReleaseHugeMem not in " << GetOpApiLibName() << ", please check!";
72 }
73 release_mem_func_ = reinterpret_cast<ReleaseHugeMemCast>(release_mem_func);
74 return release_mem_func_;
75 }
76
UpdateOutputShape(const aclTensor * tensor)77 ShapeVector UpdateOutputShape(const aclTensor *tensor) {
78 MS_EXCEPTION_IF_NULL(tensor);
79 static const auto op_api_func = GetOpApiFunc("aclGetViewShape");
80 if (op_api_func == nullptr) {
81 MS_LOG(EXCEPTION) << "aclGetViewShape not in " << GetOpApiLibName() << ", please check!";
82 }
83 using aclGetViewShapeFunc = int (*)(const aclTensor *tensor, int64_t **view_dims, uint64_t *view_dims_num);
84 auto aclGetViewShape = reinterpret_cast<aclGetViewShapeFunc>(op_api_func);
85 int64_t *view_dims = nullptr;
86 uint64_t view_dim_num = 0;
87 auto ret = aclGetViewShape(tensor, &view_dims, &view_dim_num);
88 if (ret != 0) {
89 MS_LOG(EXCEPTION) << "aclGetViewShape failed!";
90 }
91 ShapeVector output_shape(view_dims, view_dims + view_dim_num);
92 delete view_dims;
93 view_dims = nullptr;
94 return output_shape;
95 }
96
ParseCustomPriority(std::string file_name)97 std::vector<std::string> ParseCustomPriority(std::string file_name) {
98 std::ifstream file(file_name);
99 std::string line;
100 std::vector<std::string> vendor_names;
101
102 if (!file.is_open()) {
103 MS_LOG(INFO) << "Could not open the file " << file_name;
104 return vendor_names;
105 }
106
107 while (std::getline(file, line)) {
108 if (line.empty() || line[0] == ';' || line[0] == '#') {
109 continue;
110 }
111 auto pos = line.find('=');
112 if (pos == std::string::npos) {
113 MS_LOG(ERROR) << "Can not parse file: " << file_name;
114 break;
115 }
116
117 pos = pos + 1;
118 while (pos < line.size()) {
119 auto new_pos = line.find(',', pos);
120 if (new_pos == std::string::npos) {
121 (void)vendor_names.emplace_back(line.substr(pos));
122 break;
123 }
124 (void)vendor_names.emplace_back(line.substr(pos, new_pos - pos));
125 pos = new_pos + 1;
126 }
127 break;
128 }
129 return vendor_names;
130 }
131
GetAscendDefaultCustomPath(std::vector<std::string> * cust_paths)132 void GetAscendDefaultCustomPath(std::vector<std::string> *cust_paths) {
133 MS_EXCEPTION_IF_NULL(cust_paths);
134 auto ascend_path = mindspore::transform::GetAscendPath();
135 std::string custom_path = ascend_path + "opp/vendors/";
136 DIR *dir = opendir(custom_path.c_str());
137 if (dir == nullptr) {
138 MS_LOG(INFO) << "There is no custom path [" << custom_path << "] in ascend path [" << ascend_path << "].";
139 return;
140 }
141 std::string config_file = custom_path + "config.ini";
142 auto custom_priority = ParseCustomPriority(config_file);
143
144 for (auto &item_custom : custom_priority) {
145 std::string custom_opapi = custom_path + item_custom + GetCustOpApiLibName();
146 std::ifstream file(custom_opapi);
147 if (!file.good()) {
148 MS_LOG(WARNING) << "Checking whether the so exists or if permission to access it is available: " << custom_opapi;
149 continue;
150 }
151 cust_paths->emplace_back(custom_opapi);
152 MS_LOG(INFO) << "Add path [" << custom_opapi << " to custom opapi paths.";
153 }
154 closedir(dir);
155 }
156
LoadOpApiLib()157 void LoadOpApiLib() {
158 auto cust_paths = common::GetEnv("ASCEND_CUSTOM_OPP_PATH");
159 std::vector<std::string> cust_path_vec;
160 if (!cust_paths.empty()) {
161 MS_LOG(DEBUG) << "ASCEND_CUSTOM_OPP_PATH: " << cust_paths;
162 std::regex re{":"};
163 std::vector<std::string> split_path_vec(std::sregex_token_iterator(cust_paths.begin(), cust_paths.end(), re, -1),
164 std::sregex_token_iterator());
165 for (const auto &cust_path : split_path_vec) {
166 if (cust_path.empty()) {
167 continue;
168 }
169 auto lib_path = cust_path + GetCustOpApiLibName();
170 auto ret = access(lib_path.c_str(), F_OK);
171 if (ret == 0) {
172 cust_path_vec.push_back(lib_path);
173 }
174 }
175 }
176
177 GetAscendDefaultCustomPath(&cust_path_vec);
178
179 for (const auto &cust_lib_path : cust_path_vec) {
180 auto cust_handler = GetOpApiLibHandler(cust_lib_path);
181 if (cust_handler != nullptr) {
182 MS_LOG(DEBUG) << "Load cust open api lib " << cust_lib_path << " success";
183 (void)opapi_lib_handle.emplace_back(std::make_pair(cust_handler, cust_lib_path));
184 }
185 }
186
187 auto ascend_path = mindspore::transform::GetAscendPath();
188 const std::vector<std::string> depend_libs = {"libdummy_tls.so", "libnnopbase.so"};
189 for (const auto &dep_lib : depend_libs) {
190 (void)GetOpApiLibHandler(ascend_path + "lib64/" + dep_lib);
191 }
192
193 auto lib_path = ascend_path + GetOpApiLibName();
194 auto handle = GetOpApiLibHandler(lib_path);
195 if (handle != nullptr) {
196 MS_LOG(DEBUG) << "Load open api lib " << lib_path << " success";
197 (void)opapi_lib_handle.emplace_back(std::make_pair(handle, lib_path));
198 }
199 MS_LOG(DEBUG) << "Load all open api lib success";
200 }
201
AclnnInit()202 void AclnnInit() {
203 std::lock_guard<std::mutex> lock(init_mutex);
204 if (aclnn_init) {
205 return;
206 }
207 static const auto aclnn_init_func = GetOpApiFunc("aclnnInit");
208 if (aclnn_init_func == nullptr) {
209 MS_LOG(EXCEPTION) << "aclnnInit not in " << GetOpApiLibName() << ", please check!";
210 }
211 using aclnnInitFunc = int (*)(const char *);
212 auto aclnnInit = reinterpret_cast<aclnnInitFunc>(aclnn_init_func);
213
214 auto ret = aclnnInit(nullptr);
215 if (ret != 0) {
216 MS_LOG(EXCEPTION) << "aclnnInit failed!";
217 }
218 aclnn_init = true;
219 MS_LOG(DEBUG) << "aclnn init success!";
220 }
221
AclnnFinalize()222 void AclnnFinalize() {
223 if (!aclnn_init) {
224 return;
225 }
226 static const auto aclnn_finalize_func = GetOpApiFunc("aclnnFinalize");
227 if (aclnn_finalize_func == nullptr) {
228 MS_LOG(EXCEPTION) << "aclnnFinalize not in " << GetOpApiLibName() << ", please check!";
229 }
230 using aclnnFinalizeFunc = int (*)();
231 auto aclnnFinalize = reinterpret_cast<aclnnFinalizeFunc>(aclnn_finalize_func);
232
233 auto ret = aclnnFinalize();
234 if (ret != 0) {
235 MS_LOG(EXCEPTION) << "aclnnFinalize failed!";
236 }
237 aclnn_init = false;
238 MS_LOG(DEBUG) << "aclnn finalize success!";
239 }
240 } // namespace mindspore::transform
241