LCOV - code coverage report
Current view: top level - aicpu_cust_schedule/core/dfx - dump_task.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 81.5 % 777 633
Test Date: 2026-07-28 10:54:05 Functions: 97.6 % 42 41

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

Generated by: LCOV version 2.0-1