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 "utils/cann_info_utils.h"
12 :
13 : #include <fstream>
14 : #include "acl_rt_impl.h"
15 : #include "utils/file_utils.h"
16 : #include "common/json_parser.h"
17 :
18 : namespace acl {
19 : namespace {
20 : #if defined(ONLY_ENABLE_ACL_UT)
21 : constexpr const char_t *const SW_CONFIG_FILE = "tmp_run_data/ascendcl_config/swFeatureList.json";
22 : constexpr const char_t *const RUNTIME_VERSION_PATH = "tests/tmp_run_data/share/info/runtime/version.info";
23 : #else
24 : constexpr const char_t *const SW_CONFIG_FILE = "data/ascendcl_config/swFeatureList.json";
25 : constexpr const char_t *const RUNTIME_VERSION_PATH = "share/info/runtime/version.info";
26 : #endif
27 : constexpr const char_t *const VERSION_INFO_KEY = "Version=";
28 : } // namespace
29 :
30 : std::mutex CannInfoUtils::mutex_;
31 : bool CannInfoUtils::initFlag_ = false;
32 : int32_t CannInfoUtils::currentRuntimeVersion_ = UNKNOWN_VERSION;
33 : std::string CannInfoUtils::swConfigPath_;
34 : std::string CannInfoUtils::defaultInstallPath_;
35 : aclCannAttr CannInfoUtils::attrArray_[MAX_CANN_ATTR_SIZE];
36 : size_t CannInfoUtils::attrNum_ = 0;
37 :
38 : std::map<aclCannAttr, CannInfo> CannInfoUtils::attrToCannInfo_ = {
39 : {ACL_CANN_ATTR_INF_NAN, CannInfo("INF_NAN", "SoCInfo", "support_inf_nan")},
40 : {ACL_CANN_ATTR_BF16, CannInfo("BF16", "SoCInfo", "support_bf16")},
41 : {ACL_CANN_ATTR_JIT_COMPILE, CannInfo("JIT_COMPILE", "", "")},
42 : };
43 :
44 3 : aclError CannInfoUtils::GetAttributeList(const aclCannAttr **cannAttr, size_t *num)
45 : {
46 3 : const aclError ret = Initialize();
47 3 : if (ret != ACL_SUCCESS) {
48 2 : ACL_LOG_INNER_ERROR("initialize CannInfoUtils failed, ret = %d", static_cast<int32_t>(ret));
49 2 : return ret;
50 : }
51 1 : *cannAttr = attrArray_;
52 1 : *num = attrNum_;
53 1 : return ACL_SUCCESS;
54 : }
55 :
56 9 : aclError CannInfoUtils::GetAttribute(aclCannAttr cannAttr, int32_t *value)
57 : {
58 9 : const aclError ret = Initialize();
59 9 : if (ret != ACL_SUCCESS) {
60 7 : ACL_LOG_INNER_ERROR("initialize CannInfoUtils failed, ret = %d", static_cast<int32_t>(ret));
61 7 : return ret;
62 : }
63 :
64 2 : auto iter = attrToCannInfo_.find(cannAttr);
65 2 : if (iter == attrToCannInfo_.end()) {
66 1 : ACL_LOG_WARN("find cann attr failed, attr value = %d", static_cast<int32_t>(cannAttr));
67 1 : return ACL_ERROR_INVALID_PARAM;
68 : }
69 1 : *value = iter->second.isAvailable;
70 1 : return ACL_SUCCESS;
71 : }
72 :
73 12 : aclError CannInfoUtils::Initialize()
74 : {
75 12 : std::lock_guard<std::mutex> lock(mutex_);
76 12 : if (initFlag_) {
77 2 : ACL_LOG_INFO("CannInfoUtils has already initialized.");
78 2 : return ACL_SUCCESS;
79 : }
80 10 : ACL_LOG_INFO("Start to initialize CannInfoUtils.");
81 : // init config path and CANN install path
82 10 : auto ret = GetConfigInstallPath();
83 10 : if (ret != ACL_SUCCESS) {
84 4 : ACL_LOG_INNER_ERROR("Failed to get swFeatureList.json, please check ascendcl_config path.");
85 4 : return ret;
86 : }
87 :
88 : // parse requirments of each attributes
89 6 : ret = JsonParser::GetAttrConfigFromFile(swConfigPath_.c_str(), attrToCannInfo_);
90 6 : if (ret != ACL_SUCCESS) {
91 0 : ACL_LOG_INNER_ERROR("Failed to parse requirements of Cann attrs, ret = %d.", ret);
92 0 : return ret;
93 : }
94 :
95 : // parse current CannInfo
96 6 : const std::string runtimeVersionPath = defaultInstallPath_ + RUNTIME_VERSION_PATH;
97 6 : ret = ParseVersionInfo(runtimeVersionPath, ¤tRuntimeVersion_);
98 6 : if (ret != ACL_SUCCESS) {
99 5 : ACL_LOG_WARN("cannot get runtime version in current environment!");
100 5 : return ACL_ERROR_INTERNAL_ERROR;
101 : }
102 :
103 : // check and update attr availability
104 1 : CheckAndUpdateAttrAvailability();
105 1 : initFlag_ = true;
106 1 : ACL_LOG_INFO("Successfully initialized CannInfoUtils: current CannInfo[runtime = %d, attrNum = %zu]",
107 : currentRuntimeVersion_, attrNum_);
108 :
109 1 : return ACL_SUCCESS;
110 12 : }
111 :
112 10 : aclError CannInfoUtils::GetConfigInstallPath()
113 : {
114 10 : std::string path;
115 10 : const aclError ret = file_utils::GetSoRealPath(path);
116 10 : if (ret != ACL_SUCCESS) {
117 4 : ACL_LOG_WARN("Failed to get libascendcl.so file path.");
118 4 : return ret;
119 : }
120 6 : ACL_LOG_DEBUG("current path = %s", path.c_str());
121 6 : path = path.substr(0, path.rfind('/'));
122 6 : path = path.substr(0, path.rfind('/') + 1UL);
123 6 : swConfigPath_ = path + SW_CONFIG_FILE;
124 6 : ACL_LOG_DEBUG("swConfigPath = %s", swConfigPath_.c_str());
125 6 : path.pop_back();
126 6 : defaultInstallPath_ = path.substr(0, path.rfind('/') + 1UL);
127 6 : ACL_LOG_DEBUG("defaultInstallPath = %s", defaultInstallPath_.c_str());
128 6 : return ACL_SUCCESS;
129 10 : }
130 :
131 6 : aclError CannInfoUtils::ParseVersionInfo(const std::string &path, int32_t *version)
132 : {
133 6 : std::ifstream ifs(path, std::ifstream::in);
134 6 : if (!ifs.is_open()) {
135 2 : ACL_LOG_WARN("Open file [%s] failed.", path.c_str());
136 2 : return ACL_ERROR_INTERNAL_ERROR;
137 : }
138 4 : std::string line;
139 5 : while (std::getline(ifs, line)) {
140 4 : if (line.find(VERSION_INFO_KEY) != std::string::npos) {
141 3 : ACL_LOG_DEBUG("Parse version success, content is [%s].", line.c_str());
142 3 : ifs.close();
143 3 : const size_t prefixLen = strlen(VERSION_INFO_KEY);
144 3 : line = line.substr(prefixLen);
145 3 : const size_t pos = line.find('.', line.find('.') + 1UL);
146 3 : line = line.substr(0, pos);
147 3 : return ParseVersionValue(line, version);
148 : }
149 : }
150 1 : ifs.close();
151 1 : ACL_LOG_WARN("cannot find valid Version info, please check path = %s", path.c_str());
152 1 : return ACL_ERROR_INTERNAL_ERROR;
153 6 : }
154 :
155 17 : aclError CannInfoUtils::ParseVersionValue(const std::string &str, int32_t *value)
156 : {
157 17 : const size_t pos = str.find('.');
158 : try {
159 19 : const int32_t major = std::stoi(str.substr(0, pos));
160 15 : const int32_t minor = std::stoi(str.substr(pos + 1UL));
161 15 : *value = 1000 * major + 10 * minor;
162 2 : } catch (...) {
163 2 : ACL_LOG_WARN("strVal[%s] can not be converted to version value", str.c_str());
164 2 : return ACL_ERROR_INTERNAL_ERROR;
165 2 : }
166 15 : return ACL_SUCCESS;
167 : }
168 :
169 3 : bool CannInfoUtils::MatchVersionInfo(const CannInfo &configCannInfo)
170 : {
171 : // if version is not set, skip matching and return true
172 3 : if (configCannInfo.minimumRuntimeVersion == UNKNOWN_VERSION) {
173 0 : return true;
174 : }
175 3 : return (currentRuntimeVersion_ >= configCannInfo.minimumRuntimeVersion);
176 : }
177 :
178 3 : bool CannInfoUtils::CheckNPUFeatures(const CannInfo &configInfo)
179 : {
180 3 : if (configInfo.socSpecLabel.empty() || configInfo.socSpecKey.empty()) {
181 : // label 或 key 为空说明特性与芯片无关, 无需查询
182 1 : return true;
183 : }
184 2 : constexpr uint32_t kMaxValueLen = 16U;
185 2 : char_t value[kMaxValueLen] = {0};
186 2 : const auto ret = rtGetSocSpec(configInfo.socSpecLabel.c_str(), configInfo.socSpecKey.c_str(), value,
187 : kMaxValueLen);
188 2 : if (ret != RT_ERROR_NONE) {
189 0 : ACL_LOG_WARN("Cannot get platform info, label = [%s], key = [%s]", configInfo.socSpecLabel.c_str(),
190 : configInfo.socSpecKey.c_str());
191 0 : return false;
192 : }
193 : // value "0" 或空 或非法内容 都认为 false
194 2 : const std::string strVal(value);
195 2 : return strVal == "1";
196 2 : }
197 :
198 1 : void CannInfoUtils::CheckAndUpdateAttrAvailability()
199 : {
200 4 : for (auto &item : attrToCannInfo_) {
201 3 : auto &swConfigInfo = item.second;
202 3 : if (MatchVersionInfo(swConfigInfo) && CheckNPUFeatures(swConfigInfo)) {
203 3 : ACL_LOG_INFO("support cann attribute [%s]", swConfigInfo.readableAttrName.c_str());
204 3 : swConfigInfo.isAvailable = 1;
205 3 : attrArray_[attrNum_] = item.first;
206 3 : ++attrNum_;
207 : }
208 : }
209 1 : }
210 : } // namespace acl
|