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 "prof_api_reg.h" 12 : #include <mutex> 13 : #include <unordered_set> 14 : #include <map> 15 : #include "mmpa/mmpa_api.h" 16 : #include "runtime/base.h" 17 : #include "common/log_inner.h" 18 : 19 : namespace { 20 : static bool g_profRun = false; 21 : static std::mutex g_profMutex; 22 : static std::unordered_set<uint32_t> g_deviceList; 23 : constexpr uint64_t ACL_PROF_ACL_API = 0x0001U; 24 : constexpr uint32_t START_PROFILING = 1U; 25 : constexpr uint32_t STOP_PROFILING = 2U; 26 : 27 0 : static bool IsDumpToStdEnabled() { 28 0 : const char *profilingToStdOut = nullptr; 29 0 : MM_SYS_GET_ENV(MM_ENV_GE_PROFILING_TO_STD_OUT, profilingToStdOut); 30 0 : return profilingToStdOut != nullptr; 31 : } 32 : 33 : static const std::map<acl::AclTdtQueueProfType, std::string> TDT_QUEUE_PROF_TYPE_TO_NAMES = { 34 : {acl::AclTdtQueueProfType::AcltdtEnqueue, "acltdtEnqueue"}, 35 : {acl::AclTdtQueueProfType::AcltdtDequeue, "acltdtDequeue"}, 36 : {acl::AclTdtQueueProfType::AcltdtEnqueueData, "acltdtEnqueueData"}, 37 : {acl::AclTdtQueueProfType::AcltdtDequeueData, "acltdtDequeueData"}, 38 : }; 39 : 40 1 : static aclError RegisterProfType() { 41 5 : for (auto &iter : TDT_QUEUE_PROF_TYPE_TO_NAMES) { 42 4 : uint32_t typeId = static_cast<uint32_t>(iter.first); 43 4 : const auto ret = MsprofRegTypeInfo(MSPROF_REPORT_ACL_LEVEL, typeId, iter.second.c_str()); 44 4 : if (ret != MSPROF_ERROR_NONE) { 45 0 : ACL_LOG_CALL_ERROR("Registered api type [%u] failed = %d", typeId, ret); 46 0 : return ACL_ERROR_PROFILING_FAILURE; 47 : } 48 : } 49 1 : return ACL_SUCCESS; 50 : } 51 : 52 1 : static aclError AddDeviceList(const uint32_t *const deviceIdList, const uint32_t deviceNums) 53 : { 54 1 : ACL_REQUIRES_NOT_NULL(deviceIdList); 55 2 : for (size_t devId = 0U; devId < deviceNums; devId++) { 56 1 : if (g_deviceList.count(*(deviceIdList + devId)) == 0U) { 57 1 : (void)g_deviceList.insert(*(deviceIdList + devId)); 58 1 : ACL_LOG_INFO("device id %u is successfully added in acl profiling", *(deviceIdList + devId)); 59 : } 60 : } 61 1 : return ACL_SUCCESS; 62 : } 63 : 64 1 : static aclError RemoveDeviceList(const uint32_t *const deviceIdList, const uint32_t deviceNums) 65 : { 66 1 : ACL_REQUIRES_NOT_NULL(deviceIdList); 67 2 : for (size_t devId = 0U; devId < deviceNums; devId++) { 68 1 : const auto iter = g_deviceList.find(*(deviceIdList + devId)); 69 1 : if (iter != g_deviceList.end()) { 70 1 : (void)g_deviceList.erase(iter); 71 1 : ACL_LOG_INFO("device id %u is successfully deleted from acl profiling", *(deviceIdList + devId)); 72 : } 73 : } 74 1 : return ACL_SUCCESS; 75 : } 76 : 77 1 : static aclError ProfInnerStart(const rtProfCommandHandle_t *const profilerConfig) 78 : { 79 1 : ACL_LOG_INFO("start to execute ProfInnerStart"); 80 1 : if (!g_profRun) { 81 1 : RegisterProfType(); 82 1 : g_profRun = true; 83 : } 84 1 : (void)AddDeviceList(profilerConfig->devIdList, profilerConfig->devNums); 85 1 : ACL_LOG_INFO("successfully execute ProfInnerStart"); 86 1 : return ACL_SUCCESS; 87 : } 88 : 89 1 : static aclError ProfInnerStop(const rtProfCommandHandle_t *const profilerConfig) 90 : { 91 1 : ACL_LOG_INFO("start to execute ProfInnerStop"); 92 1 : (void)RemoveDeviceList(profilerConfig->devIdList, profilerConfig->devNums); 93 : 94 1 : if (g_deviceList.empty() && g_profRun) { 95 1 : g_profRun = false; 96 : } 97 1 : ACL_LOG_INFO("successfully execute ProfInnerStop"); 98 1 : return ACL_SUCCESS; 99 : } 100 : 101 2 : static aclError ProcessProfData(void *const data, const uint32_t len) 102 : { 103 2 : ACL_LOG_INFO("start to execute ProcessProfData"); 104 4 : const std::lock_guard<std::mutex> lk(g_profMutex); 105 2 : ACL_REQUIRES_NOT_NULL(data); 106 2 : constexpr size_t commandLen = sizeof(rtProfCommandHandle_t); 107 2 : if (len < commandLen) { 108 0 : ACL_LOG_INNER_ERROR("[Check][Len]len[%u] is invalid, it should not be smaller than %zu", len, commandLen); 109 0 : return ACL_ERROR_INVALID_PARAM; 110 : } 111 2 : rtProfCommandHandle_t *const profilerConfig = static_cast<rtProfCommandHandle_t *>(data); 112 2 : aclError ret = ACL_SUCCESS; 113 2 : const uint64_t profSwitch = profilerConfig->profSwitch; 114 2 : const uint32_t type = profilerConfig->type; 115 2 : if (((profSwitch & ACL_PROF_ACL_API) != 0U) && (type == START_PROFILING)) { 116 1 : ret = ProfInnerStart(profilerConfig); 117 : } 118 2 : if (((profSwitch & ACL_PROF_ACL_API) != 0U) && (type == STOP_PROFILING)) { 119 1 : ret = ProfInnerStop(profilerConfig); 120 : } 121 : 122 2 : return ret; 123 : } 124 : 125 : class AclRegProfCallback { 126 : public: 127 1 : AclRegProfCallback() { 128 1 : const auto profRet = MsprofRegisterCallback(ASCENDCL, &acl::AclTdtQueueProfCtrlHandle); 129 1 : if (profRet != 0) { 130 1 : ACL_LOG_ERROR("can not register Callback, prof result = %d", profRet); 131 : } 132 1 : } 133 1 : ~AclRegProfCallback() {} 134 : }; 135 : static AclRegProfCallback g_profCbReg; 136 : } 137 : 138 : namespace acl { 139 2 : aclError AclTdtQueueProfCtrlHandle(uint32_t dataType, void *data, uint32_t dataLen) 140 : { 141 2 : ACL_REQUIRES_NOT_NULL(data); 142 : 143 2 : if (dataType == RT_PROF_CTRL_SWITCH) { 144 2 : const aclError ret = ProcessProfData(data, dataLen); 145 2 : if (ret != ACL_SUCCESS) { 146 0 : ACL_LOG_INNER_ERROR("[Process][ProfSwitch]failed to call ProcessProfData, result is %u", ret); 147 0 : return ret; 148 : } 149 2 : return ACL_SUCCESS; 150 : } 151 : 152 0 : ACL_LOG_INFO("get unsupported dataType %u while processing profiling data", dataType); 153 0 : return ACL_SUCCESS; 154 : } 155 : 156 4 : AclTdtQueueProfilingReporter::AclTdtQueueProfilingReporter(const AclTdtQueueProfType apiId) : aclApi_(apiId) 157 : { 158 4 : if (g_profRun && (!IsDumpToStdEnabled())) { 159 0 : startTime_ = MsprofSysCycleTime(); 160 : } 161 4 : } 162 : 163 8 : AclTdtQueueProfilingReporter::~AclTdtQueueProfilingReporter() noexcept 164 : { 165 4 : if (g_profRun && (!IsDumpToStdEnabled()) && (startTime_ != 0UL)) { 166 : // 1000 ^ 3 converts second to nanosecond 167 0 : const uint64_t endTime = MsprofSysCycleTime(); 168 0 : MsprofApi api{}; 169 0 : api.beginTime = startTime_; 170 0 : api.endTime = endTime; 171 0 : thread_local static auto tid = mmGetTid(); 172 0 : api.threadId = static_cast<uint32_t>(tid); 173 0 : api.level = MSPROF_REPORT_ACL_LEVEL; 174 0 : api.type = static_cast<uint32_t>(aclApi_); 175 0 : (void)MsprofReportApi(true, &api); 176 : } 177 4 : } 178 : } // namespace acl