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