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 "dump_task.h"
11 :
12 : #include <algorithm>
13 : #include <regex>
14 : #include <sstream>
15 : #include <vector>
16 : #include <sys/time.h>
17 :
18 : #include "aicpusd_drv_manager.h"
19 : #include "aicpusd_status.h"
20 : #include "common/aicpusd_util.h"
21 : #include "securec.h"
22 : #include "metadef_types.h"
23 :
24 : namespace AicpuSchedule {
25 : // slice size for dump file, 128MByes
26 : const uint64_t DUMP_SLICE_SIZE = 128UL << 20U;
27 : const size_t INTERNAL_STEP_SIZE = 2U;
28 :
29 2 : static inline uint64_t GetCurrentTime()
30 : {
31 2 : uint64_t ret = 0U;
32 : struct timeval tv;
33 2 : if (gettimeofday(&tv, nullptr) == 0) {
34 2 : ret = (static_cast<uint64_t>(tv.tv_sec) * 1000000UL) + static_cast<uint64_t>(tv.tv_usec);
35 : }
36 :
37 2 : return ret;
38 : }
39 :
40 22 : OpDumpTask::OpDumpTask(const int32_t hostPid, const uint32_t deviceId)
41 22 : : taskDumpNum_(0U),
42 22 : endGraph_(false),
43 22 : inputTotalSize_(0U),
44 22 : outputTotalSize_(0U),
45 22 : opBufferTotalSize_(0U),
46 22 : opWorkspaceTotalSize_(0U),
47 22 : buff_(nullptr),
48 22 : buffSize_(0U),
49 22 : offset_(0U),
50 22 : skipAddressConversion_(false),
51 22 : hostPid_(hostPid),
52 22 : deviceId_(deviceId)
53 22 : {}
54 :
55 16 : static inline void ReplaceStringElem(std::string& str)
56 : {
57 16 : (void)for_each(str.begin(), str.end(), [](char_t& ch) {
58 206 : if ((ch == ' ') || (ch == '.') || (ch == '/') || (ch == '\\')) {
59 66 : ch = '_';
60 : }
61 206 : });
62 16 : }
63 :
64 8 : StatusCode OpDumpTask::GetDumpNumber(uint64_t& dumpNum)
65 : {
66 8 : if (optionalParam_.hasStepId) {
67 7 : if (optionalParam_.stepIdAddr == nullptr) {
68 1 : aicpusd_err("op name[%s], step id addr is null", opName_.c_str());
69 1 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
70 : }
71 :
72 6 : const uint64_t stepId = *(optionalParam_.stepIdAddr);
73 6 : aicpusd_info("op name[%s], step id is[%llu]", opName_.c_str(), stepId);
74 6 : uint64_t iterationsPerLoop = 0U;
75 6 : uint64_t loopCond = 0U;
76 6 : if (optionalParam_.hasIterationsPerLoop) {
77 5 : if (optionalParam_.iterationsPerLoopAddr == nullptr) {
78 1 : aicpusd_err("op name[%s], iterations per loop addr is null", opName_.c_str());
79 1 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
80 : }
81 4 : iterationsPerLoop = *(optionalParam_.iterationsPerLoopAddr);
82 4 : aicpusd_info("op name[%s], iterations per loop is[%llu]", opName_.c_str(), iterationsPerLoop);
83 : }
84 5 : if (optionalParam_.hasLoopCond) {
85 3 : if (optionalParam_.loopCondAddr == nullptr) {
86 2 : aicpusd_err("op name[%s], loop cond addr is null", opName_.c_str());
87 2 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
88 : }
89 1 : loopCond = *(optionalParam_.loopCondAddr);
90 1 : aicpusd_info("op name[%s], loop cond is[%llu]", opName_.c_str(), loopCond);
91 : }
92 3 : aicpusd_info(
93 : "op name[%s], step id[%llu], iterations per loop[%llu], loop cond[%llu]", opName_.c_str(), stepId,
94 : iterationsPerLoop, loopCond);
95 : // overflow does not matter
96 3 : dumpNum = (stepId * (iterationsPerLoop + 1U)) + loopCond;
97 : } else {
98 1 : dumpNum = taskDumpNum_;
99 : }
100 :
101 4 : return AICPU_SCHEDULE_OK;
102 : }
103 :
104 7 : StatusCode OpDumpTask::PreProcessOutput(const aicpu::dump::Task& task, ::toolkit::dumpdata::DumpData& dumpData)
105 : {
106 7 : const auto& outputsFromMapInfo = task.output();
107 17 : for (int32_t index = 0; index < outputsFromMapInfo.size(); ++index) {
108 10 : const auto& item = outputsFromMapInfo.at(index);
109 10 : ::toolkit::dumpdata::OpOutput* const opOutput = dumpData.add_output();
110 10 : if (opOutput == nullptr) {
111 0 : aicpusd_err("op name[%s], call protobuf function to add output elem failed", opName_.c_str());
112 0 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
113 : }
114 10 : opOutput->set_data_type(static_cast<::toolkit::dumpdata::OutputDataType>(item.data_type()));
115 10 : const auto format = item.format();
116 10 : opOutput->set_format(static_cast<::toolkit::dumpdata::OutputFormat>(ge::GetPrimaryFormat(format)));
117 10 : opOutput->set_sub_format(ge::GetSubFormat(format));
118 10 : const auto dims = item.shape().dim();
119 10 : ::toolkit::dumpdata::Shape* const outShape = opOutput->mutable_shape();
120 30 : for (const auto dim : dims) {
121 20 : outShape->add_dim(dim);
122 : }
123 10 : const auto originalDims = item.origin_shape().dim();
124 10 : ::toolkit::dumpdata::Shape* const outOriginalShape = opOutput->mutable_original_shape();
125 15 : for (const auto dim : originalDims) {
126 5 : outOriginalShape->add_dim(dim);
127 : }
128 10 : if (!item.original_name().empty()) {
129 7 : ::toolkit::dumpdata::OriginalOp* const orgOp = opOutput->mutable_original_op();
130 7 : orgOp->set_name(item.original_name());
131 7 : orgOp->set_output_index(static_cast<uint32_t>(item.original_output_index()));
132 7 : orgOp->set_data_type(static_cast<::toolkit::dumpdata::OutputDataType>(item.original_output_data_type()));
133 7 : orgOp->set_format(static_cast<::toolkit::dumpdata::OutputFormat>(item.original_output_format()));
134 : }
135 10 : const auto& dim_rangeFromOutput = item.dim_range();
136 14 : for (int32_t i = 0; i < dim_rangeFromOutput.size(); ++i) {
137 4 : const auto& item = dim_rangeFromOutput.at(i);
138 4 : ::toolkit::dumpdata::DimRange* const dimRange = opOutput->add_dim_range();
139 4 : if (dimRange == nullptr) {
140 0 : aicpusd_err(
141 : "op name[%s], call protobuf function to add dim_range elem failed, i[%d],"
142 : " dim_range_size[%zu]",
143 : opName_.c_str(), i, dim_rangeFromOutput.size());
144 0 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
145 : }
146 4 : dimRange->set_dim_start(item.dim_start());
147 4 : dimRange->set_dim_end(item.dim_end());
148 : }
149 10 : opOutput->set_size(item.size());
150 10 : outputTotalSize_ += item.size();
151 10 : outputsBaseAddr_.push_back(item.address());
152 10 : }
153 7 : return AICPU_SCHEDULE_OK;
154 : }
155 :
156 7 : StatusCode OpDumpTask::PreProcessInput(const aicpu::dump::Task& task, ::toolkit::dumpdata::DumpData& dumpData)
157 : {
158 7 : const auto& inputsFromMapInfo = task.input();
159 14 : for (int32_t i = 0; i < inputsFromMapInfo.size(); ++i) {
160 7 : const auto& item = inputsFromMapInfo.at(i);
161 7 : ::toolkit::dumpdata::OpInput* const opInput = dumpData.add_input();
162 7 : if (opInput == nullptr) {
163 0 : aicpusd_err("op name[%s], call protobuf function to add input elem failed", opName_.c_str());
164 0 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
165 : }
166 7 : opInput->set_data_type(static_cast<::toolkit::dumpdata::OutputDataType>(item.data_type()));
167 7 : const auto format = item.format();
168 7 : opInput->set_format(static_cast<::toolkit::dumpdata::OutputFormat>(ge::GetPrimaryFormat(format)));
169 7 : opInput->set_sub_format(ge::GetSubFormat(format));
170 7 : const auto dims = item.shape().dim();
171 7 : ::toolkit::dumpdata::Shape* const inShape = opInput->mutable_shape();
172 21 : for (const auto dim : dims) {
173 14 : inShape->add_dim(dim);
174 : }
175 7 : const auto originalDims = item.origin_shape().dim();
176 7 : ::toolkit::dumpdata::Shape* const inOriginalShape = opInput->mutable_original_shape();
177 12 : for (const auto dim : originalDims) {
178 5 : inOriginalShape->add_dim(dim);
179 : }
180 :
181 7 : opInput->set_size(item.size());
182 7 : inputTotalSize_ += item.size();
183 7 : inputsBaseAddr_.push_back(item.address());
184 7 : }
185 7 : return AICPU_SCHEDULE_OK;
186 : }
187 :
188 7 : StatusCode OpDumpTask::PreProcessOpBuffer(const aicpu::dump::Task& task, ::toolkit::dumpdata::DumpData& dumpData)
189 : {
190 7 : const auto& opsBufferFromMapInfo = task.buffer();
191 11 : for (int32_t i = 0; i < opsBufferFromMapInfo.size(); ++i) {
192 4 : const auto& item = opsBufferFromMapInfo.at(i);
193 4 : ::toolkit::dumpdata::OpBuffer* const opBuffer = dumpData.add_buffer();
194 4 : if (opBuffer == nullptr) {
195 0 : aicpusd_err("op name[%s], call protobuf function to add op buffer elem failed", opName_.c_str());
196 0 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
197 : }
198 :
199 4 : opBuffer->set_buffer_type(static_cast<::toolkit::dumpdata::BufferType>(item.buffer_type()));
200 4 : opBuffer->set_size(item.size());
201 4 : opBufferTotalSize_ += item.size();
202 4 : opBufferAddr_.push_back(item.address());
203 : }
204 7 : return AICPU_SCHEDULE_OK;
205 : }
206 :
207 8 : StatusCode OpDumpTask::PreProcessWorkspace(const aicpu::dump::Task& task, ::toolkit::dumpdata::DumpData& dumpData)
208 : {
209 8 : const auto& opsWorkspaceFromMapInfo = task.space();
210 10 : for (int64_t i = 0; i < opsWorkspaceFromMapInfo.size(); ++i) {
211 2 : const auto& item = opsWorkspaceFromMapInfo.at(i);
212 2 : ::toolkit::dumpdata::Workspace* const opWorkspace = dumpData.add_space();
213 2 : if (opWorkspace == nullptr) {
214 0 : aicpusd_err("op name[%s], call protobuf function to add op Workspace elem failed", opName_.c_str());
215 0 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
216 : }
217 :
218 2 : opWorkspace->set_type(static_cast<::toolkit::dumpdata::Workspace::SpaceType>(item.type()));
219 2 : opWorkspace->set_size(item.size());
220 2 : opWorkspaceTotalSize_ += item.size();
221 2 : opWorkspaceAddr_.push_back(item.data_addr());
222 : }
223 8 : return AICPU_SCHEDULE_OK;
224 : }
225 :
226 6 : StatusCode OpDumpTask::PreProcessOpMappingInfo(
227 : const aicpu::dump::Task& task, const std::string& basePath, const MappingInfoOptionalParam& param,
228 : const DumpStep& dumpStep, const bool skipAddressConversion)
229 : {
230 6 : aicpusd_info(
231 : "Base path[%s], has model name[%d], model name[%s], has model id[%d], model id[%u].", basePath.c_str(),
232 : static_cast<int32_t>(param.hasModelName), param.modelName.c_str(), static_cast<int32_t>(param.hasModelId),
233 : param.modelId);
234 6 : aicpusd_debug("task info[%s].", task.DebugString().c_str());
235 6 : const std::lock_guard<std::mutex> queLock(dumpMtx_);
236 6 : baseDumpPath_ = basePath;
237 6 : optionalParam_ = param;
238 6 : dumpStep_ = dumpStep;
239 6 : skipAddressConversion_ = skipAddressConversion;
240 : // single op no task id and stream id
241 6 : taskInfo_.taskId_ = (skipAddressConversion_ && optionalParam_.hasStepId) ? 0U : task.task_id();
242 6 : taskInfo_.streamId_ = (skipAddressConversion_ && optionalParam_.hasStepId) ? 0U : task.stream_id();
243 6 : endGraph_ = task.end_graph();
244 :
245 6 : ::toolkit::dumpdata::DumpData dumpData;
246 : // version 2.0
247 : dumpData.set_version("2.0");
248 6 : StatusCode ret = PreProcessInput(task, dumpData);
249 6 : if (ret != AICPU_SCHEDULE_OK) {
250 0 : return ret;
251 : }
252 6 : ret = PreProcessOutput(task, dumpData);
253 6 : if (ret != AICPU_SCHEDULE_OK) {
254 0 : return ret;
255 : }
256 6 : ret = PreProcessOpBuffer(task, dumpData);
257 6 : if (ret != AICPU_SCHEDULE_OK) {
258 0 : return ret;
259 : }
260 6 : ret = PreProcessWorkspace(task, dumpData);
261 6 : if (ret != AICPU_SCHEDULE_OK) {
262 0 : return ret;
263 : }
264 6 : opName_ = task.op().op_name();
265 6 : opType_ = task.op().op_type();
266 6 : dumpData.set_op_name(opName_);
267 6 : aicpusd_info(
268 : "[stream id:%u, task id:%u], op name[%s], op type[%s]", taskInfo_.streamId_, taskInfo_.taskId_, opName_.c_str(),
269 : opType_.c_str());
270 6 : baseDumpData_ = std::move(dumpData);
271 6 : taskDumpNum_ = 0U;
272 :
273 6 : return AICPU_SCHEDULE_OK;
274 6 : }
275 :
276 6 : StatusCode OpDumpTask::ProcessInputDump(
277 : const ::toolkit::dumpdata::DumpData& dumpData, const std::string& path, const IDE_SESSION ideSession)
278 : {
279 6 : uint64_t dumpedSize = 0U;
280 11 : for (int32_t i = 0; i < dumpData.input_size(); ++i) {
281 6 : auto& input = dumpData.input(i);
282 6 : const uint64_t len = input.size();
283 6 : if (len == 0U) {
284 1 : aicpusd_info("op name[%s], input[%d] data size is zero", opName_.c_str(), i);
285 1 : continue;
286 : }
287 5 : const uint64_t baseAddr = inputsBaseAddr_.at(static_cast<size_t>(i));
288 5 : uint64_t dataAddr = baseAddr;
289 5 : if (!skipAddressConversion_) {
290 3 : if (baseAddr == 0U) {
291 1 : aicpusd_info("op name[%s], input[%d] base addr is null", opName_.c_str(), i);
292 1 : continue;
293 : }
294 : // baseAddr is a pointer point to data addr
295 2 : dataAddr = *(PtrToPtr<void, uint64_t>(ValueToPtr(baseAddr)));
296 : }
297 4 : aicpusd_info("op name[%s], input[%d] size[%llu]", opName_.c_str(), i, len);
298 4 : if (dataAddr == 0U) {
299 1 : aicpusd_info("op name[%s], input[%d] addr is null", opName_.c_str(), i);
300 1 : continue;
301 : }
302 3 : uint64_t innerOffset = 0U;
303 5 : while (innerOffset < len) {
304 3 : const uint64_t emptyBufferSize = buffSize_ - offset_;
305 3 : const uint64_t actSize = std::min(emptyBufferSize, len - innerOffset);
306 3 : const uint64_t srcAddr = dataAddr + innerOffset;
307 3 : aicpusd_info(
308 : "op name[%s], begin to copy data from HBM to DDR for input[%d], size[%llu]", opName_.c_str(), i,
309 : actSize);
310 3 : const errno_t eRet = memcpy_s(buff_.get() + offset_, emptyBufferSize, ValueToPtr(srcAddr), actSize);
311 3 : if (eRet != EOK) {
312 0 : aicpusd_err(
313 : "op name[%s], input[%d] memcpy failed, desSize[%llu], srcSize[%llu]", opName_.c_str(), i,
314 : emptyBufferSize, actSize);
315 1 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
316 : }
317 3 : aicpusd_info(
318 : "op name[%s], end of copy data from HBM to DDR for input[%d], size[%llu]", opName_.c_str(), i, actSize);
319 3 : offset_ += actSize;
320 3 : innerOffset += actSize;
321 3 : dumpedSize += actSize;
322 2 : const bool isLastSilce = (dumpedSize == inputTotalSize_) && (outputTotalSize_ == 0U) &&
323 5 : (opBufferTotalSize_ == 0U) && (opWorkspaceTotalSize_ == 0U);
324 3 : if ((offset_ >= buffSize_) || isLastSilce) {
325 1 : const StatusCode ret = Dump(path, buff_.get(), offset_, ideSession, isLastSilce);
326 1 : if (ret != AICPU_SCHEDULE_OK) {
327 1 : aicpusd_err("op name[%s], dump input failed", opName_.c_str());
328 1 : return ret;
329 : }
330 0 : offset_ = 0U;
331 : }
332 : }
333 2 : aicpusd_info("op name[%s], process input[%d] data dump success.", opName_.c_str(), i);
334 : }
335 5 : return AICPU_SCHEDULE_OK;
336 : }
337 :
338 2 : StatusCode OpDumpTask::ProcessOutputDump(
339 : const ::toolkit::dumpdata::DumpData& dumpData, const std::string& path, const IDE_SESSION ideSession)
340 : {
341 2 : uint64_t dumpedSize = 0U;
342 4 : for (int32_t i = 0; i < dumpData.output_size(); ++i) {
343 2 : auto& output = dumpData.output(i);
344 2 : const uint64_t len = output.size();
345 2 : if (len == 0U) {
346 0 : aicpusd_info("op name[%s], output[%d] data size is zero", opName_.c_str(), i);
347 0 : continue;
348 : }
349 2 : const uint64_t baseAddr = outputsBaseAddr_.at(static_cast<size_t>(i));
350 2 : uint64_t dataAddr = baseAddr;
351 2 : if (!skipAddressConversion_) {
352 1 : if (baseAddr == 0U) {
353 0 : aicpusd_info("op name[%s], output[%d] base addr is null.", opName_.c_str(), i);
354 0 : continue;
355 : }
356 : // baseAddr is a pointer point to data addr
357 1 : dataAddr = *(PtrToPtr<void, uint64_t>(ValueToPtr(baseAddr)));
358 1 : aicpusd_info("op name[%s], output[%d].", opName_.c_str(), i);
359 : }
360 2 : aicpusd_info("op name[%s], output[%d] size[%llu].", opName_.c_str(), i, len);
361 :
362 2 : if (dataAddr == 0U) {
363 0 : aicpusd_info("op name[%s], output[%d] addr is null", opName_.c_str(), i);
364 0 : continue;
365 : }
366 2 : uint64_t innerOffset = 0U;
367 4 : while (innerOffset < len) {
368 2 : const uint64_t emptyBufferSize = buffSize_ - offset_;
369 2 : const uint64_t actSize = std::min(emptyBufferSize, len - innerOffset);
370 2 : const uint64_t srcAddr = dataAddr + innerOffset;
371 2 : aicpusd_info(
372 : "op name[%s], begin to copy data from HBM to DDR for output[%d], size[%llu]", opName_.c_str(), i,
373 : actSize);
374 2 : const errno_t eRet = memcpy_s(buff_.get() + offset_, emptyBufferSize, ValueToPtr(srcAddr), actSize);
375 2 : if (eRet != EOK) {
376 0 : aicpusd_err(
377 : "op name[%s], output[%d] memcpy failed, des[%llu], src[%llu]", opName_.c_str(), i,
378 : PtrToValue(buff_.get() + offset_), srcAddr);
379 0 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
380 : }
381 2 : aicpusd_info(
382 : "op name[%s], end of copy data from HBM to DDR for output[%d], size[%llu]", opName_.c_str(), i,
383 : actSize);
384 2 : offset_ += actSize;
385 2 : innerOffset += actSize;
386 2 : dumpedSize += actSize;
387 2 : const bool isLastSilce =
388 2 : (offset_ >= buffSize_) ||
389 0 : ((dumpedSize == outputTotalSize_) && (opBufferTotalSize_ == 0U) && (opWorkspaceTotalSize_ == 0U));
390 2 : if (isLastSilce) {
391 2 : const StatusCode ret = Dump(path, buff_.get(), offset_, ideSession, isLastSilce);
392 2 : if (ret != AICPU_SCHEDULE_OK) {
393 0 : aicpusd_err("op name[%s], dump output failed", opName_.c_str());
394 0 : return ret;
395 : }
396 2 : offset_ = 0U;
397 : }
398 : }
399 :
400 2 : aicpusd_info("op name[%s], process output[%d] data dump success.", opName_.c_str(), i);
401 : }
402 2 : return AICPU_SCHEDULE_OK;
403 : }
404 :
405 4 : StatusCode OpDumpTask::ProcessOpBufferDump(
406 : const ::toolkit::dumpdata::DumpData& dumpData, const std::string& path, const IDE_SESSION ideSession)
407 : {
408 4 : uint64_t dumpedSize = 0U;
409 5 : for (int32_t i = 0; i < dumpData.buffer_size(); ++i) {
410 2 : auto& buffer = dumpData.buffer(i);
411 2 : if (buffer.size() == 0U) {
412 0 : aicpusd_info("op name[%s], op buffer[%d] data size is zero", opName_.c_str(), i);
413 0 : continue;
414 : }
415 2 : const size_t opBufferAddrIndex = static_cast<size_t>(i);
416 2 : if (opBufferAddr_[opBufferAddrIndex] == 0U) {
417 1 : aicpusd_info("op name[%s], op buffer[%d] addr is null", opName_.c_str(), i);
418 1 : continue;
419 : }
420 1 : uint64_t innerOffset = 0U;
421 1 : while (innerOffset < buffer.size()) {
422 1 : const uint64_t emptyBufferSize = buffSize_ - offset_;
423 1 : const uint64_t actSize = std::min(emptyBufferSize, buffer.size() - innerOffset);
424 1 : const uint64_t srcAddr = opBufferAddr_[opBufferAddrIndex] + innerOffset;
425 1 : aicpusd_info(
426 : "op name[%s], begin to copy data from HBM to DDR for op buffer[%d], size[%llu]", opName_.c_str(), i,
427 : actSize);
428 1 : const errno_t eRet = memcpy_s(buff_.get() + offset_, emptyBufferSize, ValueToPtr(srcAddr), actSize);
429 1 : if (eRet != EOK) {
430 1 : aicpusd_err(
431 : "op name[%s], op buffer[%d] memcpy failed, desSize[%llu], srcSize[%llu]", opName_.c_str(), i,
432 : emptyBufferSize, actSize);
433 1 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
434 : }
435 0 : aicpusd_info(
436 : "op name[%s], end of copy data from HBM to DDR for op buffer[%d], size[%llu]", opName_.c_str(), i,
437 : actSize);
438 0 : offset_ += actSize;
439 0 : innerOffset += actSize;
440 0 : dumpedSize += actSize;
441 0 : const bool isLastSilce =
442 0 : (offset_ >= buffSize_) || ((dumpedSize == opBufferTotalSize_) && (opWorkspaceTotalSize_ == 0U));
443 0 : if (isLastSilce) {
444 0 : const StatusCode ret = Dump(path, buff_.get(), offset_, ideSession, isLastSilce);
445 0 : if (ret != AICPU_SCHEDULE_OK) {
446 0 : aicpusd_err("op name[%s], dump op buffer failed", opName_.c_str());
447 0 : return ret;
448 : }
449 0 : offset_ = 0U;
450 : }
451 : }
452 0 : aicpusd_info("op name[%s], process op buffer[%d] data success.", opName_.c_str(), i);
453 : }
454 3 : return AICPU_SCHEDULE_OK;
455 : }
456 :
457 8 : StatusCode OpDumpTask::ProcessOpWorkspaceDump(
458 : const ::toolkit::dumpdata::DumpData& dumpData, const std::string& path, const IDE_SESSION ideSession)
459 : {
460 8 : uint64_t dumpedSize = 0U;
461 12 : for (int64_t i = 0; i < dumpData.space_size(); ++i) {
462 6 : auto& space = dumpData.space(i);
463 6 : if (space.size() == 0U) {
464 1 : aicpusd_err("op name[%s], op space[%d] data size is zero", opName_.c_str(), i);
465 1 : continue;
466 : }
467 5 : const size_t opWorkspaceAddrIndex = static_cast<size_t>(i);
468 5 : if (opWorkspaceAddr_[opWorkspaceAddrIndex] == 0U) {
469 1 : aicpusd_err("op name[%s], op space[%d] workspace is null", opName_.c_str(), i);
470 1 : continue;
471 : }
472 4 : uint64_t innerOffset = 0U;
473 6 : while (innerOffset < space.size()) {
474 4 : const uint64_t emptyWorkspaceSize = buffSize_ - offset_;
475 4 : const uint64_t actSize = std::min(emptyWorkspaceSize, space.size() - innerOffset);
476 4 : const uint64_t srcAddr = opWorkspaceAddr_[opWorkspaceAddrIndex] + innerOffset;
477 4 : aicpusd_info(
478 : "op name[%s], begin to copy data from HBM to DDR for spaceIndex[%d],"
479 : " srcSize[%llu], innerOffset[%llu], offset[%llu], dstSize[%llu]",
480 : opName_.c_str(), i, actSize, innerOffset, offset_, emptyWorkspaceSize);
481 12 : const errno_t eRet = memcpy_s(
482 4 : buff_.get() + offset_, emptyWorkspaceSize, PtrToPtr<void, char_t>(ValueToPtr(srcAddr)), actSize);
483 4 : if (eRet != EOK) {
484 1 : aicpusd_err(
485 : "op name[%s], op spaceIndex[%d] memcpy failed, dstSize[%llu], srcSize[%llu]", opName_.c_str(), i,
486 : emptyWorkspaceSize, actSize);
487 2 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
488 : }
489 3 : aicpusd_info(
490 : "op name[%s], op spaceIndex[%d] end copy, dstSize[%llu], srcSize[%llu]", opName_.c_str(), i,
491 : emptyWorkspaceSize, actSize);
492 3 : offset_ += actSize;
493 3 : innerOffset += actSize;
494 3 : dumpedSize += actSize;
495 3 : const bool isLastSilce = (dumpedSize == opWorkspaceTotalSize_);
496 3 : if (!((offset_ >= buffSize_) || isLastSilce)) {
497 0 : continue;
498 : }
499 3 : const StatusCode ret = Dump(path, buff_.get(), offset_, ideSession, isLastSilce);
500 3 : if (ret != AICPU_SCHEDULE_OK) {
501 1 : aicpusd_err("op name[%s], dump op space failed", opName_.c_str());
502 1 : return ret;
503 : }
504 2 : offset_ = 0U;
505 : }
506 2 : aicpusd_info("op name[%s], process op space[%d] data success.", opName_.c_str(), i);
507 : }
508 6 : return AICPU_SCHEDULE_OK;
509 : }
510 :
511 6 : StatusCode OpDumpTask::Dump(
512 : const std::string& path, char_t* const data, const uint64_t len, const IDE_SESSION ideSession,
513 : const bool isLastSlice) const
514 : {
515 6 : if (ideSession != nullptr) {
516 6 : IdeDumpChunk ideDumpChunk = {};
517 6 : ideDumpChunk.fileName = const_cast<char_t*>(path.c_str());
518 6 : ideDumpChunk.dataBuf = reinterpret_cast<uint8_t*>(data);
519 6 : ideDumpChunk.bufLen = static_cast<uint32_t>(len);
520 6 : ideDumpChunk.isLastChunk = isLastSlice ? 1U : 0U;
521 6 : ideDumpChunk.offset = -1; // append
522 6 : ideDumpChunk.flag = IDE_DUMP_NONE_FLAG;
523 6 : aicpusd_info(
524 : "op name[%s], start to call IdeDumpData, size[%u], isLastChunk[%u]", opName_.c_str(), len,
525 : ideDumpChunk.isLastChunk);
526 6 : const IdeErrorT ideState = IdeDumpData(ideSession, &ideDumpChunk);
527 6 : if (ideState != IDE_DAEMON_NONE_ERROR) {
528 2 : aicpusd_err("op name[%s], call IdeDumpData failed, size[%u].", opName_.c_str(), len);
529 2 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
530 : }
531 4 : aicpusd_info("op name[%s], end of call IdeDumpData, size[%u]", opName_.c_str(), len);
532 : } else {
533 0 : aicpusd_err("op name[%s], ide session is null, size[%u].", opName_.c_str(), len);
534 0 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
535 : }
536 4 : return AICPU_SCHEDULE_OK;
537 : }
538 :
539 3 : StatusCode OpDumpTask::DumpOpInfo(const uint32_t streamId, const uint32_t taskId, const std::string& dumpDebugInfo)
540 : {
541 3 : const std::lock_guard<std::mutex> queLock(dumpMtx_);
542 3 : uint64_t dumpNumber = 0U;
543 3 : if (GetDumpNumber(dumpNumber) != AICPU_SCHEDULE_OK) {
544 1 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
545 : }
546 2 : if (!NeedDump(dumpNumber)) {
547 0 : return AICPU_SCHEDULE_OK;
548 : }
549 :
550 2 : const uint64_t nowTime = GetCurrentTime();
551 2 : baseDumpData_.set_dump_time(nowTime);
552 :
553 2 : if ((baseDumpData_.ByteSizeLong() > static_cast<uint64_t>(INT_MAX)) || (baseDumpData_.ByteSizeLong() == 0U)) {
554 0 : aicpusd_err(
555 : "op name[%s], dump data size[%zuB] should be in [1B, 2GB)].", opName_.c_str(),
556 : baseDumpData_.ByteSizeLong());
557 0 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
558 : }
559 2 : aicpusd_info("op name[%s], proto buffer total bytes[%llu]", opName_.c_str(), baseDumpData_.ByteSizeLong());
560 2 : buffSize_ = baseDumpData_.ByteSizeLong() + sizeof(uint64_t) + inputTotalSize_ + outputTotalSize_ +
561 2 : opBufferTotalSize_ + opWorkspaceTotalSize_;
562 2 : buffSize_ = std::min(buffSize_, DUMP_SLICE_SIZE);
563 2 : buffSize_ = std::max(buffSize_, baseDumpData_.ByteSizeLong() + sizeof(uint64_t));
564 2 : buff_.reset(new (std::nothrow) char_t[buffSize_]);
565 2 : if (buff_ == nullptr) {
566 0 : aicpusd_err("op name[%s], malloc buffer for data dump failed, size[%llu]", opName_.c_str(), buffSize_);
567 0 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
568 : }
569 : // for memory statistic
570 2 : aicpusd_memory_log(
571 : "op name[%s], MallocMemory, func=new, size=%llu, purpose=data dump buffer", opName_.c_str(), buffSize_);
572 2 : uint64_t* const sizePtr = PtrToPtr<char_t, uint64_t>(buff_.get());
573 2 : *sizePtr = baseDumpData_.ByteSizeLong();
574 2 : offset_ = sizeof(uint64_t);
575 2 : if (!baseDumpData_.SerializeToArray(
576 2 : buff_.get() + sizeof(uint64_t), static_cast<int32_t>(baseDumpData_.ByteSizeLong()))) {
577 0 : aicpusd_err(
578 : "op name[%s], serialize dump data to string failed, data size[%zuB].", opName_.c_str(),
579 : baseDumpData_.ByteSizeLong());
580 0 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
581 : }
582 2 : offset_ += baseDumpData_.ByteSizeLong();
583 : // dump file path name
584 2 : const std::string dumpFilePath = DumpPath(nowTime, dumpNumber, streamId, taskId);
585 2 : std::string dumpDebugFilePath;
586 2 : if (!(dumpDebugInfo.empty())) {
587 0 : dumpDebugFilePath = DumpPath(nowTime, dumpNumber, streamId, taskId, true);
588 : }
589 2 : return DoDump(dumpFilePath, dumpDebugFilePath, dumpDebugInfo);
590 3 : }
591 :
592 2 : StatusCode OpDumpTask::DoDump(
593 : const std::string& dumpFilePath, const std::string& dumpDebugFilePath, const std::string& dumpDebugInfo)
594 : {
595 2 : aicpusd_info("op name[%s], start to dump data, path[%s]", opName_.c_str(), dumpFilePath.c_str());
596 : // the port is not used in ide module, just for privateInfo format check
597 2 : const std::string privateInfo = "127.0.0.1:22118;" + std::to_string(deviceId_) + ";" + std::to_string(hostPid_);
598 2 : aicpusd_info("op name[%s], ide dump start private info[%s]", opName_.c_str(), privateInfo.c_str());
599 2 : const IDE_SESSION ideSession = IdeDumpStart(privateInfo.c_str());
600 2 : if (ideSession == nullptr) {
601 0 : aicpusd_err("op name[%s], call IdeDumpStart failed, path[%s].", opName_.c_str(), dumpFilePath.c_str());
602 0 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
603 : }
604 4 : const ScopeGuard ideSessGuard([&ideSession]() { IdeDumpEnd(ideSession); });
605 2 : StatusCode ret = AICPU_SCHEDULE_OK;
606 2 : if (offset_ == buffSize_) {
607 0 : ret = Dump(dumpFilePath, buff_.get(), buffSize_, ideSession, false);
608 0 : if (ret != AICPU_SCHEDULE_OK) {
609 0 : aicpusd_err("op name[%s], dump proto failed, path[%s].", opName_.c_str(), dumpFilePath.c_str());
610 0 : return ret;
611 : }
612 0 : offset_ = 0U;
613 : }
614 :
615 2 : ret = ProcessInputDump(baseDumpData_, dumpFilePath, ideSession);
616 2 : if (ret != AICPU_SCHEDULE_OK) {
617 0 : return ret;
618 : }
619 2 : ret = ProcessOutputDump(baseDumpData_, dumpFilePath, ideSession);
620 2 : if (ret != AICPU_SCHEDULE_OK) {
621 0 : return ret;
622 : }
623 2 : ret = ProcessOpBufferDump(baseDumpData_, dumpFilePath, ideSession);
624 2 : if (ret != AICPU_SCHEDULE_OK) {
625 0 : return ret;
626 : }
627 2 : ret = ProcessOpWorkspaceDump(baseDumpData_, dumpFilePath, ideSession);
628 2 : if (ret != AICPU_SCHEDULE_OK) {
629 0 : return ret;
630 : }
631 : // release buffer
632 2 : buff_.reset(nullptr);
633 :
634 2 : if (!(dumpDebugInfo.empty())) {
635 : ret =
636 0 : Dump(dumpDebugFilePath, const_cast<char_t*>(dumpDebugInfo.c_str()), dumpDebugInfo.size(), ideSession, true);
637 0 : if (ret != AICPU_SCHEDULE_OK) {
638 0 : aicpusd_err("op name[%s], dump debug info failed, path[%s].", opName_.c_str(), dumpDebugFilePath.c_str());
639 0 : return ret;
640 : }
641 : }
642 2 : aicpusd_info("op name[%s], dump data success, path[%s]", opName_.c_str(), dumpFilePath.c_str());
643 2 : return AICPU_SCHEDULE_OK;
644 2 : }
645 :
646 1 : void OpDumpTask::UpdateDumpNum()
647 : {
648 1 : const std::lock_guard<std::mutex> queLock(dumpMtx_);
649 1 : taskDumpNum_++;
650 1 : aicpusd_info("op name[%s], dump number is updated, dump number[%llu].", opName_.c_str(), taskDumpNum_);
651 1 : }
652 :
653 1 : bool OpDumpTask::IsEndGraph() const { return endGraph_; }
654 :
655 1 : bool OpDumpTask::GetModelId(uint32_t& modelId) const
656 : {
657 1 : if (optionalParam_.hasModelId) {
658 1 : modelId = optionalParam_.modelId;
659 1 : return true;
660 : }
661 0 : return false;
662 : }
663 :
664 0 : std::string OpDumpTask::GetOpName() const { return opName_; }
665 :
666 7 : bool OpDumpTask::NeedDump(const uint64_t step)
667 : {
668 7 : if (endGraph_) {
669 1 : aicpusd_run_info("op name[%s], end graph dump task.", opName_.c_str());
670 1 : return false;
671 : }
672 :
673 6 : bool stepNeedDump = false;
674 6 : if (dumpStep_.singleStep.empty() && dumpStep_.intervalStep.empty()) {
675 2 : stepNeedDump = true;
676 : }
677 6 : if (dumpStep_.singleStep.find(step) != dumpStep_.singleStep.end()) {
678 1 : stepNeedDump = true;
679 : }
680 6 : for (const auto item : dumpStep_.intervalStep) {
681 2 : if ((step >= item.start) && (step <= item.end)) {
682 2 : stepNeedDump = true;
683 2 : break;
684 : }
685 : }
686 6 : if (!stepNeedDump) {
687 1 : aicpusd_run_info(
688 : "op name[%s], the step[%llu] is not in dump list %s.", opName_.c_str(), step,
689 : dumpStep_.DebugString().c_str());
690 1 : return false;
691 : }
692 :
693 5 : if ((inputTotalSize_ == 0U) && (outputTotalSize_ == 0U) && (opBufferTotalSize_ == 0U) &&
694 1 : (opWorkspaceTotalSize_ == 0U)) {
695 1 : aicpusd_run_info("op name[%s], no data need to dump.", opName_.c_str());
696 1 : return false;
697 : }
698 :
699 4 : return true;
700 : }
701 :
702 4 : std::string OpDumpTask::DumpPath(
703 : const uint64_t nowTime, const uint64_t dumpNumber, const uint32_t streamId, const uint32_t taskId,
704 : const bool debugFlag)
705 : {
706 4 : std::ostringstream oss;
707 4 : oss << baseDumpPath_;
708 4 : if (optionalParam_.hasModelName) {
709 3 : oss << "/" << optionalParam_.modelName;
710 : }
711 4 : if (optionalParam_.hasModelId) {
712 3 : oss << "/" << optionalParam_.modelId;
713 : }
714 : // single op dump
715 4 : if (!((skipAddressConversion_) && (!optionalParam_.hasStepId))) {
716 3 : oss << "/" << dumpNumber;
717 : }
718 :
719 4 : std::string opName = opName_;
720 4 : std::string opType = opType_;
721 4 : ReplaceStringElem(opName);
722 4 : ReplaceStringElem(opType);
723 4 : if (debugFlag) {
724 1 : opName += "Debug";
725 : }
726 4 : if ((streamId != INVALID_VAL) && (taskId != INVALID_VAL)) {
727 1 : oss << "/" << opType << "." << opName << "." << taskId << "." << streamId << "." << nowTime;
728 : } else {
729 3 : oss << "/" << opType << "." << opName << "." << taskInfo_.taskId_ << "." << taskInfo_.streamId_ << "."
730 3 : << nowTime;
731 : }
732 8 : return oss.str();
733 4 : }
734 :
735 2 : void OpDumpTask::ClearBaseDumpData()
736 : {
737 2 : baseDumpData_.Clear();
738 2 : return;
739 : }
740 :
741 1 : std::string DumpStep::DebugString()
742 : {
743 1 : std::ostringstream oss;
744 1 : for (const auto step : singleStep) {
745 0 : oss << "[" << step << "] ";
746 : }
747 1 : for (const auto step : intervalStep) {
748 0 : oss << "[" << step.start << ", " << step.end << "] ";
749 : }
750 :
751 2 : return oss.str();
752 1 : }
753 :
754 7 : OpDumpTaskManager& OpDumpTaskManager::GetInstance()
755 : {
756 7 : static OpDumpTaskManager instance;
757 7 : return instance;
758 : }
759 :
760 9 : void OpDumpTaskManager::GetOptionalParam(
761 : const aicpu::dump::OpMappingInfo& opMappingInfo, MappingInfoOptionalParam& optionalParam) const
762 : {
763 9 : if (opMappingInfo.model_name_param_case() == aicpu::dump::OpMappingInfo::kModelName) {
764 8 : optionalParam.modelName = opMappingInfo.model_name();
765 8 : ReplaceStringElem(optionalParam.modelName);
766 8 : optionalParam.hasModelName = true;
767 : }
768 9 : if (opMappingInfo.model_id_param_case() == aicpu::dump::OpMappingInfo::kModelId) {
769 8 : optionalParam.modelId = opMappingInfo.model_id();
770 8 : optionalParam.hasModelId = true;
771 : }
772 9 : if (opMappingInfo.step_id_case() == aicpu::dump::OpMappingInfo::kStepIdAddr) {
773 8 : optionalParam.stepIdAddr = PtrToPtr<void, uint64_t>(ValueToPtr(opMappingInfo.step_id_addr()));
774 8 : optionalParam.hasStepId = true;
775 : }
776 9 : if (opMappingInfo.iterations_per_loop_case() == aicpu::dump::OpMappingInfo::kIterationsPerLoopAddr) {
777 7 : optionalParam.iterationsPerLoopAddr =
778 7 : PtrToPtr<void, uint64_t>(ValueToPtr(opMappingInfo.iterations_per_loop_addr()));
779 7 : optionalParam.hasIterationsPerLoop = true;
780 : }
781 9 : if (opMappingInfo.loop_cond_case() == aicpu::dump::OpMappingInfo::kLoopCondAddr) {
782 7 : optionalParam.loopCondAddr = PtrToPtr<void, uint64_t>(ValueToPtr(opMappingInfo.loop_cond_addr()));
783 7 : optionalParam.hasLoopCond = true;
784 : }
785 9 : }
786 :
787 6 : int32_t OpDumpTaskManager::Load(const aicpu::dump::OpMappingInfo& opMappingInfo)
788 : {
789 6 : const std::string dumpPath = opMappingInfo.dump_path();
790 6 : MappingInfoOptionalParam optionalParam;
791 6 : GetOptionalParam(opMappingInfo, optionalParam);
792 6 : const std::string dumpStepStr = opMappingInfo.dump_step();
793 6 : DumpStep dumpStep;
794 6 : if (!GetDumpStepFromString(dumpStepStr, dumpStep)) {
795 1 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
796 : }
797 5 : const int32_t hostPid = static_cast<int32_t>(AicpuSchedule::AicpuDrvManager::GetInstance().GetHostPid());
798 5 : const uint32_t deviceId = AicpuSchedule::AicpuDrvManager::GetInstance().GetDeviceId();
799 5 : std::set<TaskInfo> tasksInfo;
800 : {
801 5 : const std::lock_guard<std::mutex> mapLock(dumpTaskMapMtx_);
802 10 : for (int32_t i = 0; i < opMappingInfo.task_size(); ++i) {
803 5 : const aicpu::dump::Task task = opMappingInfo.task(i);
804 5 : const uint32_t taskId = task.task_id() & 0xFFFF;
805 5 : const uint32_t streamId = task.stream_id();
806 5 : std::shared_ptr<OpDumpTask> opDumpTaskPtr = nullptr;
807 : try {
808 5 : opDumpTaskPtr = std::make_shared<OpDumpTask>(hostPid, deviceId);
809 0 : } catch (...) {
810 0 : aicpusd_err("make shared for OpDumpTask failed.");
811 0 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
812 0 : }
813 5 : aicpusd_memory_log("MallocMemory, func=new, size=%zu, purpose=data dumper", sizeof(OpDumpTask));
814 5 : if (opDumpTaskPtr == nullptr) {
815 0 : aicpusd_err("malloc memory for OpDumpTask object failed");
816 0 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
817 : }
818 5 : const int32_t ret = opDumpTaskPtr->PreProcessOpMappingInfo(task, dumpPath, optionalParam, dumpStep);
819 5 : if (ret != AICPU_SCHEDULE_OK) {
820 : // when error occur, ge call unload op mapping info
821 0 : aicpusd_err("pre process op mapping info failed");
822 0 : return ret;
823 : }
824 5 : TaskInfo taskInfo(streamId, taskId);
825 5 : (void)dumpTaskMap_.insert(std::make_pair(taskInfo, std::move(opDumpTaskPtr)));
826 5 : (void)tasksInfo.insert(taskInfo);
827 5 : }
828 5 : if (optionalParam.hasModelId) {
829 5 : const auto iter = modelIdToTask_.find(optionalParam.modelId);
830 5 : if (iter == modelIdToTask_.end()) {
831 2 : (void)modelIdToTask_.insert(std::make_pair(optionalParam.modelId, std::move(tasksInfo)));
832 : } else {
833 6 : for (const auto item : tasksInfo) {
834 3 : (void)iter->second.insert(item);
835 : }
836 : }
837 : }
838 5 : }
839 5 : return AICPU_SCHEDULE_OK;
840 6 : }
841 :
842 3 : void OpDumpTaskManager::UnloadClearTaskInfo(const TaskInfo& taskInfo)
843 : {
844 3 : const auto range = dumpTaskMap_.equal_range(taskInfo);
845 3 : if (range.first != range.second) {
846 3 : for (auto item = range.first; item != range.second; ++item) {
847 2 : item->second->ClearBaseDumpData();
848 : }
849 : }
850 3 : (void)dumpTaskMap_.erase(taskInfo);
851 6 : return;
852 : }
853 :
854 2 : int32_t OpDumpTaskManager::Unload(const aicpu::dump::OpMappingInfo& opMappingInfo)
855 : {
856 2 : const std::lock_guard<std::mutex> mapLock(dumpTaskMapMtx_);
857 4 : for (int32_t i = 0; i < opMappingInfo.task_size(); ++i) {
858 2 : const aicpu::dump::Task task = opMappingInfo.task(i);
859 2 : const uint32_t taskId = task.task_id();
860 2 : const uint32_t streamId = task.stream_id();
861 2 : const TaskInfo taskInfo(streamId, taskId);
862 2 : UnloadClearTaskInfo(taskInfo);
863 2 : aicpusd_info("Unload op mapping info, stream id[%u], task id[%u].", streamId, taskId);
864 2 : }
865 2 : MappingInfoOptionalParam optionalParam;
866 2 : GetOptionalParam(opMappingInfo, optionalParam);
867 2 : if (optionalParam.hasModelId) {
868 2 : const auto iter = modelIdToTask_.find(optionalParam.modelId);
869 2 : if (iter == modelIdToTask_.end()) {
870 1 : aicpusd_warn("no model id[%u], unload dump model failed", optionalParam.modelId);
871 1 : return AICPU_SCHEDULE_OK;
872 : }
873 2 : for (const auto taskInfo : iter->second) {
874 1 : UnloadClearTaskInfo(taskInfo);
875 1 : aicpusd_info(
876 : "Check and clean data dump task resource, stream id[%u], task id[%u].", taskInfo.streamId_,
877 : taskInfo.taskId_);
878 : }
879 1 : (void)modelIdToTask_.erase(iter);
880 1 : aicpusd_info("Unloaded model id[%u] successfully", optionalParam.modelId);
881 : }
882 1 : return AICPU_SCHEDULE_OK;
883 2 : }
884 :
885 10 : int32_t OpDumpTaskManager::LoadOpMappingInfo(const char_t* const infoAddr, const uint32_t len)
886 : {
887 10 : aicpusd_info("Load op mapping info, size[%u].", len);
888 10 : if (infoAddr == nullptr) {
889 1 : aicpusd_err("op mapping info addr is null");
890 1 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
891 : }
892 9 : aicpu::dump::OpMappingInfo opMappingInfo;
893 9 : const std::string protoInfo(infoAddr, static_cast<unsigned long>(len));
894 9 : const bool parseRet = opMappingInfo.ParseFromString(protoInfo);
895 9 : if (!parseRet) {
896 1 : aicpusd_err("parse op mapping info failed");
897 1 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
898 : }
899 8 : if (opMappingInfo.flag() == 0x01U) {
900 6 : return Load(opMappingInfo);
901 2 : } else if (opMappingInfo.flag() == 0x00U) {
902 2 : return Unload(opMappingInfo);
903 : } else {
904 0 : aicpusd_info("Flag [%d] invalid, allow [0x00, 0x01]", opMappingInfo.flag());
905 0 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
906 : }
907 : return AICPU_SCHEDULE_OK;
908 9 : }
909 :
910 2 : int32_t OpDumpTaskManager::DumpOpInfo(
911 : const uint32_t streamId, const uint32_t taskId, const uint32_t streamId1, const uint32_t taskId1,
912 : const std::string& dumpDebugInfo)
913 : {
914 2 : const TaskInfo taskInfo(streamId, taskId);
915 2 : dumpTaskMapMtx_.lock();
916 2 : const auto range = dumpTaskMap_.equal_range(taskInfo);
917 2 : if (range.first == range.second) {
918 1 : dumpTaskMapMtx_.unlock();
919 1 : aicpusd_run_info("task required to dump does not exist, stream id[%u], task id[%u].", streamId, taskId);
920 1 : return AICPU_SCHEDULE_OK;
921 : } else {
922 1 : std::vector<std::shared_ptr<OpDumpTask>> opDumptasks;
923 3 : for (auto item = range.first; item != range.second; ++item) {
924 2 : std::shared_ptr<OpDumpTask> opDumpTask = item->second;
925 2 : opDumptasks.push_back(std::move(opDumpTask));
926 2 : }
927 1 : int32_t ret = AICPU_SCHEDULE_OK;
928 1 : dumpTaskMapMtx_.unlock();
929 1 : aicpusd_run_info(
930 : "require to dump op info, stream id=%u, task id=%u, task number=%zu", streamId, taskId, opDumptasks.size());
931 2 : for (auto item : opDumptasks) {
932 2 : aicpusd_run_info(
933 : "start to dump op info, stream id=%u, task id=%u, op name=%s", streamId, taskId,
934 : item->GetOpName().c_str());
935 2 : ret = item->DumpOpInfo(streamId1, taskId1, dumpDebugInfo);
936 2 : aicpusd_run_info(
937 : "end of dump op info, result=%d, stream id=%u, task id=%u, op name=%s", ret, streamId, taskId,
938 : item->GetOpName().c_str());
939 2 : if (ret != AICPU_SCHEDULE_OK) {
940 1 : return ret;
941 : }
942 2 : }
943 : // process if task is end graph
944 0 : ProcessEndGraph(opDumptasks);
945 1 : }
946 0 : return AICPU_SCHEDULE_OK;
947 : }
948 :
949 2 : int32_t OpDumpTaskManager::DumpOpInfoForUnknowShape(
950 : const uint64_t opMappingInfoAddr, const uint64_t opMappingInfoLen) const
951 : {
952 2 : aicpusd_info("load op mapping info for single op or unknown shape op, size[%llu]", opMappingInfoLen);
953 2 : if (opMappingInfoAddr == 0U) {
954 1 : aicpusd_err("op mapping info addr is null");
955 1 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
956 : }
957 1 : aicpu::dump::OpMappingInfo opMappingInfo;
958 1 : const std::string protoInfo(PtrToPtr<const void, const char_t>(ValueToPtr(opMappingInfoAddr)), opMappingInfoLen);
959 1 : const bool parseRet = opMappingInfo.ParseFromString(protoInfo);
960 1 : if (!parseRet) {
961 0 : aicpusd_err("parse op mapping info failed, size[%u]", opMappingInfoLen);
962 0 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
963 : }
964 1 : const int32_t taskSize = opMappingInfo.task_size();
965 1 : if (taskSize != 1) {
966 0 : aicpusd_err(
967 : "task number[%d] should be only one, op mapping info: %s", opMappingInfo.task_size(),
968 : opMappingInfo.DebugString().c_str());
969 0 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
970 : }
971 1 : return DoDump(opMappingInfo);
972 1 : }
973 :
974 1 : int32_t OpDumpTaskManager::DoDump(const aicpu::dump::OpMappingInfo& opMappingInfo) const
975 : {
976 1 : const std::string dumpPath = opMappingInfo.dump_path();
977 1 : MappingInfoOptionalParam optionalParam;
978 1 : GetOptionalParam(opMappingInfo, optionalParam);
979 1 : const std::string dumpStepStr = opMappingInfo.dump_step();
980 :
981 1 : DumpStep dumpStep;
982 1 : if (!GetDumpStepFromString(dumpStepStr, dumpStep)) {
983 0 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
984 : }
985 1 : const int32_t hostPid = static_cast<int32_t>(AicpuSchedule::AicpuDrvManager::GetInstance().GetHostPid());
986 1 : const uint32_t deviceId = AicpuSchedule::AicpuDrvManager::GetInstance().GetDeviceId();
987 1 : std::shared_ptr<OpDumpTask> opDumpTaskPtr = nullptr;
988 : try {
989 1 : opDumpTaskPtr = std::make_shared<OpDumpTask>(hostPid, deviceId);
990 0 : } catch (const std::bad_alloc& err) {
991 0 : aicpusd_err("malloc memory for OpDumpTask object failed, reason is [%s]", err.what());
992 0 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
993 0 : } catch (...) {
994 0 : aicpusd_err("malloc memory for OpDumpTask object failed");
995 0 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
996 0 : }
997 1 : aicpusd_memory_log("MallocMemory, func=new, size=%zu, purpose=data dumper", sizeof(OpDumpTask));
998 1 : if (opDumpTaskPtr == nullptr) {
999 0 : aicpusd_err("malloc memory for OpDumpTask object failed");
1000 0 : return AICPU_SCHEDULE_ERROR_DUMP_FAILED;
1001 : }
1002 1 : int32_t ret = AICPU_SCHEDULE_OK;
1003 1 : const aicpu::dump::Task task = opMappingInfo.task(0);
1004 1 : ret = opDumpTaskPtr->PreProcessOpMappingInfo(task, dumpPath, optionalParam, dumpStep, true);
1005 1 : if (ret != AICPU_SCHEDULE_OK) {
1006 0 : aicpusd_err("pre process op mapping info failed, op mapping info: %s", opMappingInfo.DebugString().c_str());
1007 0 : return ret;
1008 : }
1009 1 : auto startTime = std::chrono::steady_clock::now();
1010 1 : aicpusd_run_info("start to dump op info, op name=%s", opDumpTaskPtr->GetOpName().c_str());
1011 2 : ret = opDumpTaskPtr->DumpOpInfo();
1012 1 : auto endTime = std::chrono::steady_clock::now();
1013 1 : double drUs = std::chrono::duration<double, std::micro>(endTime - startTime).count();
1014 1 : aicpusd_run_info(
1015 : "end of dump op info, result=%d, op name=%s, cost time is [%.2lf]us", ret, opDumpTaskPtr->GetOpName().c_str(),
1016 : drUs);
1017 : UNUSED(drUs);
1018 1 : return ret;
1019 1 : }
1020 :
1021 1 : void OpDumpTaskManager::ProcessEndGraph(const std::vector<std::shared_ptr<OpDumpTask>>& opDumptasks)
1022 : {
1023 2 : for (const auto& item : opDumptasks) {
1024 1 : if (item->IsEndGraph()) {
1025 : uint32_t modelId;
1026 0 : if (item->GetModelId(modelId)) {
1027 0 : UpdateDumpNumByModelId(modelId);
1028 : } else {
1029 0 : item->UpdateDumpNum();
1030 : }
1031 : }
1032 : }
1033 1 : }
1034 :
1035 1 : void OpDumpTaskManager::UpdateDumpNumByModelId(const uint32_t modelId)
1036 : {
1037 1 : std::vector<std::shared_ptr<OpDumpTask>> opDumptasks;
1038 : {
1039 1 : const std::lock_guard<std::mutex> mapLock(dumpTaskMapMtx_);
1040 1 : const auto iter = modelIdToTask_.find(modelId);
1041 1 : if (iter != modelIdToTask_.end()) {
1042 0 : for (auto& taskInfo : iter->second) {
1043 0 : const auto range = dumpTaskMap_.equal_range(taskInfo);
1044 0 : for (auto item = range.first; item != range.second; ++item) {
1045 0 : std::shared_ptr<OpDumpTask> opDumpTask = item->second;
1046 0 : opDumptasks.push_back(std::move(opDumpTask));
1047 0 : }
1048 : }
1049 : }
1050 1 : }
1051 :
1052 1 : for (auto& dumpTask : opDumptasks) {
1053 0 : dumpTask->UpdateDumpNum();
1054 : }
1055 1 : }
1056 :
1057 1 : static void DoSplit(const std::string& externStr, std::vector<std::string>& ret, const std::string& delim)
1058 : {
1059 1 : size_t i = 0UL;
1060 2 : while (i < externStr.size()) {
1061 1 : const size_t pos = externStr.find(delim, i);
1062 1 : if (pos != std::string::npos) {
1063 1 : std::string s = externStr.substr(i, pos - i);
1064 1 : if (!s.empty()) {
1065 1 : ret.push_back(std::move(s));
1066 : }
1067 1 : i = pos + delim.size() - 1UL;
1068 1 : }
1069 1 : ++i;
1070 : }
1071 1 : }
1072 :
1073 7 : static std::vector<std::string> Split(const std::string& str, const std::string& delim)
1074 : {
1075 7 : std::vector<std::string> ret;
1076 7 : if (!str.empty()) {
1077 1 : const std::string externStr = str + delim;
1078 1 : DoSplit(externStr, ret, delim);
1079 1 : }
1080 7 : return ret;
1081 0 : }
1082 :
1083 1 : bool OpDumpTaskManager::MatchAndInsert(const std::string& step, DumpStep& tmpDumpStep) const
1084 : {
1085 : // smatch result
1086 1 : const std::regex singleStepPatten("(\\s*)(\\d+)(\\s*)");
1087 1 : const std::regex intervalStepPatten("((\\s*)(\\d+)(\\s*)){1}(-(\\s*)(\\d+)(\\s*))");
1088 1 : if (std::regex_match(step, singleStepPatten)) {
1089 1 : (void)tmpDumpStep.singleStep.insert(static_cast<uint64_t>(std::stoull(step)));
1090 0 : } else if (std::regex_match(step, intervalStepPatten)) {
1091 0 : const std::vector<std::string> intervalStepStr = Split(step, "-");
1092 0 : if (intervalStepStr.size() == INTERNAL_STEP_SIZE) {
1093 : IntervalStep intervalStep;
1094 0 : intervalStep.start = static_cast<uint64_t>(std::stoull(intervalStepStr[0U]));
1095 0 : intervalStep.end = static_cast<uint64_t>(std::stoull(intervalStepStr[1U]));
1096 0 : if (intervalStep.start > intervalStep.end) {
1097 0 : std::swap(intervalStep.start, intervalStep.end);
1098 : }
1099 0 : tmpDumpStep.intervalStep.push_back(std::move(intervalStep));
1100 : }
1101 0 : } else {
1102 0 : aicpusd_err("invalid step[%s], please check.", step.c_str());
1103 0 : return false;
1104 : }
1105 0 : return true;
1106 2 : }
1107 :
1108 7 : bool OpDumpTaskManager::GetDumpStepFromString(const std::string& str, DumpStep& dumpStep) const
1109 : {
1110 : // split by |, such as "0|5-10"
1111 7 : aicpusd_info("Step need to dump[%s].", str.c_str());
1112 7 : const std::vector<std::string> steps = Split(str, "|");
1113 7 : DumpStep tmpDumpStep;
1114 7 : for (const auto& step : steps) {
1115 : try {
1116 1 : if (!MatchAndInsert(step, tmpDumpStep)) {
1117 1 : return false;
1118 : }
1119 1 : } catch (std::out_of_range& e) {
1120 1 : aicpusd_err(
1121 : "out of range of uint64_max[%llu], invalid step[%s], msg[%s], please check.", UINT64_MAX, step.c_str(),
1122 : e.what());
1123 1 : return false;
1124 1 : } catch (...) {
1125 0 : aicpusd_err("invalid step[%s], please check.", step.c_str());
1126 0 : return false;
1127 0 : }
1128 : }
1129 6 : dumpStep = std::move(tmpDumpStep);
1130 6 : return true;
1131 7 : }
1132 :
1133 1 : void OpDumpTaskManager::ClearResource()
1134 : {
1135 1 : const std::lock_guard<std::mutex> mapLock(dumpTaskMapMtx_);
1136 1 : aicpusd_run_info("clear all resource of data dump");
1137 1 : dumpTaskMap_.clear();
1138 1 : modelIdToTask_.clear();
1139 1 : }
1140 : } // namespace AicpuSchedule
|