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 "aicpusd_model_statistic.h"
11 :
12 : #include <sstream>
13 : namespace AicpuSchedule {
14 14 : std::string AicpuSdModelStatistic::FormatShapeToString(const std::vector<int64_t>& shape) const
15 : {
16 14 : bool first = true;
17 14 : std::stringstream ss;
18 14 : ss << "[";
19 28 : for (const int64_t& x : shape) {
20 14 : if (first) {
21 10 : first = false;
22 10 : ss << x;
23 : } else {
24 4 : ss << ", " << x;
25 : }
26 : }
27 14 : ss << "]";
28 28 : return ss.str();
29 14 : }
30 :
31 2 : std::string AicpuSdModelStatistic::GetRangeString(
32 : const std::vector<InAndOutParamStatInfo>& statInfos, size_t startIdx, size_t endIdx) const
33 : {
34 2 : std::stringstream minSizeStream;
35 2 : std::stringstream maxSizeStream;
36 2 : std::stringstream minShapeStream;
37 2 : std::stringstream maxShapeStream;
38 9 : for (size_t idx = startIdx; idx <= endIdx; ++idx) {
39 7 : const auto& curInfo = statInfos[idx];
40 7 : if (idx != startIdx) {
41 5 : minSizeStream << ", ";
42 5 : maxSizeStream << ", ";
43 5 : minShapeStream << ", ";
44 5 : maxShapeStream << ", ";
45 : }
46 7 : minSizeStream << curInfo.minSize;
47 7 : maxSizeStream << curInfo.maxSize;
48 7 : minShapeStream << FormatShapeToString(curInfo.minShape);
49 7 : maxShapeStream << FormatShapeToString(curInfo.maxShape);
50 : }
51 2 : std::stringstream strStream;
52 2 : strStream << "min_size=[" << minSizeStream.str() << "], max_size=[" << maxSizeStream.str() << "], min_shape=["
53 2 : << minShapeStream.str() << "], max_shape=[" << maxShapeStream.str() << "]";
54 4 : return strStream.str();
55 2 : }
56 :
57 2050 : AicpuSdModelStatistic::~AicpuSdModelStatistic() {}
58 :
59 2050 : AicpuSdModelStatistic::AicpuSdModelStatistic() {}
60 :
61 66 : AicpuSdModelStatistic& AicpuSdModelStatistic::GetInstance()
62 : {
63 66 : static AicpuSdModelStatistic instance;
64 66 : return instance;
65 : }
66 :
67 4 : void AicpuSdModelStatistic::StatNNModelExecTime(const uint32_t modelId)
68 : {
69 4 : if (modelId >= MAX_MODEL_COUNT) {
70 1 : aicpusd_err("invalid modelId:%u, max:%u", modelId, MAX_MODEL_COUNT);
71 3 : return;
72 : }
73 3 : aicpusd_info(
74 : "enter curMax:%llu, curMin:%llu", modelStatArray_[modelId].maxExecTime, modelStatArray_[modelId].minExecTime);
75 3 : if (!modelStatArray_[modelId].useFlag) {
76 2 : aicpusd_info("only stat static model, dynamic model no need stat");
77 2 : return;
78 : }
79 1 : modelStatArray_[modelId].totalCnt++;
80 1 : auto curTime = std::chrono::steady_clock::now();
81 1 : auto timeGap = curTime - modelStatArray_[modelId].modelStartTime;
82 : const uint64_t curExecTime =
83 1 : static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::microseconds>(timeGap).count());
84 1 : modelStatArray_[modelId].totalTime += curExecTime;
85 1 : AicpuUtil::UpdateMaxAndSubMaxData(
86 1 : modelStatArray_[modelId].maxExecTime, modelStatArray_[modelId].subMaxExecTime, curExecTime);
87 1 : AicpuUtil::UpdateMinData(modelStatArray_[modelId].minExecTime, curExecTime);
88 1 : aicpusd_info(
89 : "after update curMax:%llu, curMin:%llu, curStat:%llu", modelStatArray_[modelId].maxExecTime,
90 : modelStatArray_[modelId].minExecTime, curExecTime);
91 : }
92 :
93 4 : void AicpuSdModelStatistic::UpdateStatVecInfo(
94 : InAndOutParamStatInfo& dstStat, const uint64_t totalSize, const int64_t* shapes) const
95 : {
96 4 : if ((dstStat.minSize == 0) || (totalSize < dstStat.minSize)) {
97 1 : dstStat.minSize = totalSize;
98 1 : dstStat.minShape.assign(&(shapes[1]), &(shapes[1]) + shapes[0]);
99 : }
100 :
101 4 : if (totalSize > dstStat.maxSize) {
102 2 : dstStat.maxSize = totalSize;
103 2 : dstStat.maxShape.assign(&(shapes[1]), &(shapes[1]) + shapes[0]);
104 : }
105 4 : }
106 :
107 5 : void AicpuSdModelStatistic::AddNewDataToStatVec(
108 : std::vector<InAndOutParamStatInfo>& delVec, const uint64_t totalSize, const int64_t* shapes) const
109 : {
110 5 : InAndOutParamStatInfo tempNode;
111 5 : tempNode.minSize = totalSize;
112 5 : tempNode.minShape.assign(&(shapes[1]), &(shapes[1]) + shapes[0]);
113 5 : tempNode.maxSize = totalSize;
114 5 : tempNode.maxShape.assign(&(shapes[1]), &(shapes[1]) + shapes[0]);
115 5 : aicpusd_info(
116 : "max size:%llu, min size:%llu, min shape size:%zu, max shape size:%zu", tempNode.maxSize, tempNode.minSize,
117 : tempNode.minShape.size(), tempNode.maxShape.size());
118 5 : delVec.emplace_back(tempNode);
119 5 : }
120 :
121 4 : void AicpuSdModelStatistic::StatNNModelInput(
122 : const uint32_t modelId, const std::vector<uint64_t>& totalSizeList, std::vector<ModelConfigTensorDesc>& curStatVec)
123 : {
124 4 : if ((modelId >= MAX_MODEL_COUNT) || (totalSizeList.size() != curStatVec.size())) {
125 1 : aicpusd_err(
126 : "invalid modelId:%u, max:%u, size list:%zu, stat list:%zu", modelId, MAX_MODEL_COUNT, totalSizeList.size(),
127 : curStatVec.size());
128 1 : return;
129 : }
130 3 : std::vector<InAndOutParamStatInfo>& delVec = modelStatArray_[modelId].inputStatVec;
131 3 : const size_t delVecSize = delVec.size();
132 3 : const size_t curVecSize = curStatVec.size();
133 3 : const size_t curMinSize = delVecSize < curVecSize ? delVecSize : curVecSize;
134 5 : for (size_t index = 0; index < curMinSize; index++) {
135 2 : UpdateStatVecInfo(delVec[index], totalSizeList[index], &(curStatVec[index].shape[0]));
136 2 : aicpusd_info(
137 : "index:%zu max size:%llu, min size:%llu, min shape size:%zu, max shape size:%zu", index,
138 : delVec[index].maxSize, delVec[index].minSize, delVec[index].minShape.size(), delVec[index].maxShape.size());
139 : }
140 :
141 3 : if (delVecSize < curVecSize) {
142 4 : for (size_t i = curMinSize; i < curVecSize; i++) {
143 2 : AddNewDataToStatVec(delVec, totalSizeList[i], &(curStatVec[i].shape[0]));
144 : }
145 : }
146 : }
147 :
148 7 : void AicpuSdModelStatistic::InitModelStatInfo()
149 : {
150 7175 : for (uint32_t index = 0; index < MAX_MODEL_COUNT; index++) {
151 7168 : modelStatArray_[index].useFlag = false;
152 7168 : modelStatArray_[index].maxExecTime = 0UL;
153 7168 : modelStatArray_[index].minExecTime = 0UL;
154 7168 : modelStatArray_[index].subMaxExecTime = 0UL;
155 7168 : modelStatArray_[index].totalTime = 0UL;
156 7168 : modelStatArray_[index].totalCnt = 0UL;
157 7168 : modelStatArray_[index].inputStatVec.clear();
158 7168 : modelStatArray_[index].outputStatVec.clear();
159 : }
160 7 : }
161 :
162 10 : void AicpuSdModelStatistic::MarNNModelStartTime(const uint32_t modelId)
163 : {
164 10 : if (modelId >= MAX_MODEL_COUNT) {
165 1 : aicpusd_err("invalid modelId:%u, max:%u", modelId, MAX_MODEL_COUNT);
166 1 : return;
167 : }
168 9 : modelStatArray_[modelId].modelStartTime = std::chrono::steady_clock::now();
169 9 : modelStatArray_[modelId].useFlag = true;
170 9 : aicpusd_info("mark mode:%u started", modelId);
171 : }
172 :
173 7 : void AicpuSdModelStatistic::StatNNModelOutput(
174 : const uint32_t modelId, const RuntimeTensorDesc* const tensorDesc, const int32_t nextIndex)
175 : {
176 7 : if ((modelId >= MAX_MODEL_COUNT) || (nextIndex <= 0) || (tensorDesc == nullptr)) {
177 1 : aicpusd_err("invalid modelId:%u, max:%u, nextIndex:%d", modelId, MAX_MODEL_COUNT, nextIndex);
178 2 : return;
179 : }
180 6 : const uint32_t curIndex = static_cast<uint32_t>(nextIndex) - 1U;
181 6 : std::vector<InAndOutParamStatInfo>& delVec = modelStatArray_[modelId].outputStatVec;
182 6 : const size_t curDelSize = delVec.size();
183 6 : int64_t curTotalSize = 0;
184 : const int32_t ret =
185 6 : AicpuUtil::CalcDataSizeByShape(&(tensorDesc->shape[1]), tensorDesc->shape[0], tensorDesc->dtype, curTotalSize);
186 6 : if ((ret != AICPU_SCHEDULE_OK) || (curTotalSize < 0)) {
187 1 : aicpusd_warn("cannot get size from tensordesc, ret[%d], size[%lld]", ret, curTotalSize);
188 1 : return;
189 : }
190 5 : const uint64_t dataSize = static_cast<uint64_t>(curTotalSize);
191 5 : if (curIndex < curDelSize) {
192 2 : UpdateStatVecInfo(delVec[curIndex], dataSize, &(tensorDesc->shape[0]));
193 2 : aicpusd_info(
194 : "max size:%llu, min size:%llu, min shape size:%zu, max shape size:%zu", delVec[curIndex].maxSize,
195 : delVec[curIndex].minSize, delVec[curIndex].minShape.size(), delVec[curIndex].maxShape.size());
196 3 : } else if (curIndex == curDelSize) {
197 2 : AddNewDataToStatVec(delVec, dataSize, &(tensorDesc->shape[0]));
198 : } else {
199 1 : delVec.resize(curIndex);
200 1 : AddNewDataToStatVec(delVec, dataSize, &(tensorDesc->shape[0]));
201 : }
202 : }
203 :
204 25 : void AicpuSdModelStatistic::PrintOutModelStatInfo()
205 : {
206 25625 : for (uint32_t modelId = 0U; modelId < MAX_MODEL_COUNT; modelId++) {
207 25600 : if (modelStatArray_[modelId].useFlag) {
208 1 : DumpOutModelMetrics(modelId);
209 : }
210 : }
211 25 : }
212 1 : void AicpuSdModelStatistic::DumpOutModelMetrics(const uint32_t modelId)
213 : {
214 1 : ModelStatInfo& curModeInfo = modelStatArray_[modelId];
215 1 : aicpusd_run_info(
216 : "model_metrics:name=%s, min_exec_time=%llu us, max_exec_time=%llu us, "
217 : "sub_max_exec_time=%llu us, total_exec_time=%llu us, total_exec_num=%llu.",
218 : std::to_string(modelId).c_str(), curModeInfo.minExecTime, curModeInfo.maxExecTime, curModeInfo.subMaxExecTime,
219 : curModeInfo.totalTime, curModeInfo.totalCnt);
220 1 : constexpr size_t maxCntPrintPreLine = 10;
221 1 : const size_t inputSize = curModeInfo.inputStatVec.size();
222 1 : const size_t outputSize = curModeInfo.outputStatVec.size();
223 2 : for (size_t inputIdx = 0; inputIdx < inputSize; inputIdx += maxCntPrintPreLine) {
224 1 : const size_t startIdx = inputIdx;
225 1 : const size_t endIdx =
226 1 : (inputIdx + maxCntPrintPreLine) > inputSize ? (inputSize - 1) : (inputIdx + maxCntPrintPreLine - 1);
227 1 : aicpusd_run_info(
228 : "model_metrics:name=%s, input[%zu-%zu], %s.", std::to_string(modelId).c_str(), startIdx, endIdx,
229 : GetRangeString(curModeInfo.inputStatVec, startIdx, endIdx).c_str());
230 : }
231 :
232 2 : for (size_t outputIdx = 0; outputIdx < outputSize; outputIdx += maxCntPrintPreLine) {
233 1 : const size_t startIdx = outputIdx;
234 1 : const size_t endIdx =
235 1 : (outputIdx + maxCntPrintPreLine) > outputSize ? (outputSize - 1) : (outputIdx + maxCntPrintPreLine - 1);
236 1 : aicpusd_run_info(
237 : "model_metrics:name=%s, output[%zu-%zu], %s.", std::to_string(modelId).c_str(), startIdx, endIdx,
238 : GetRangeString(curModeInfo.outputStatVec, startIdx, endIdx).c_str());
239 : }
240 1 : }
241 : } // namespace AicpuSchedule
|