forked from huawei/mindspore2022
283 lines
11 KiB
C++
283 lines
11 KiB
C++
/**
|
|
* Copyright 2020 Huawei Technologies Co., Ltd
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
#ifdef ENABLE_DATA_DUMP
|
|
#include "device/ascend/dump/data_dumper.h"
|
|
|
|
#include <map>
|
|
#include <memory>
|
|
#include <string>
|
|
#include "utility"
|
|
#include "session/anf_runtime_algorithm.h"
|
|
#include "runtime/mem.h"
|
|
#include "runtime/kernel.h"
|
|
#include "device/ascend/dump/ge_dump.h"
|
|
#include "proto/op_mapping_info.pb.h"
|
|
#include "utils/context/ms_context.h"
|
|
#include "debug/data_dump_parser.h"
|
|
|
|
constexpr uint32_t kAicpuLoadFlag = 1;
|
|
constexpr uint32_t kAicpuUnloadFlag = 0;
|
|
constexpr uint32_t kTupleTaskId = 0;
|
|
constexpr uint32_t kTupleStreamId = 1;
|
|
constexpr uint32_t kTupleArgs = 2;
|
|
constexpr uint32_t kCurrentStepTensorIndex = 0;
|
|
constexpr uint32_t kCurrentEpochTensorIndex = 1;
|
|
constexpr uint32_t kStepsPerEpochTensorIndex = 2;
|
|
|
|
namespace mindspore {
|
|
namespace device {
|
|
namespace ascend {
|
|
void DumpKernelOutput(const CNodePtr &kernel, void *args, NotNull<aicpu::dump::Task *> task);
|
|
void DumpKernelInput(const CNodePtr &kernel, void *args, NotNull<aicpu::dump::Task *> task);
|
|
void RtLoadDumpData(const aicpu::dump::OpMappingInfo &dump_info, void **ptr);
|
|
|
|
DataDumper::~DataDumper() {
|
|
ReleaseDevMem(&dev_load_mem_);
|
|
ReleaseDevMem(&dev_unload_mem_);
|
|
}
|
|
|
|
void DataDumper::LoadDumpInfo() {
|
|
MS_LOG(INFO) << "[DataDump] LoadDumpInfo start";
|
|
MS_EXCEPTION_IF_NULL(kernel_graph_);
|
|
aicpu::dump::OpMappingInfo dump_info;
|
|
SetOpMappingInfo(NOT_NULL(&dump_info));
|
|
|
|
auto kernels = kernel_graph_->execution_order();
|
|
for (const auto &kernel : kernels) {
|
|
MS_EXCEPTION_IF_NULL(kernel);
|
|
if (!KernelNeedDump(kernel)) {
|
|
continue;
|
|
}
|
|
MS_LOG(INFO) << "[DataDump] LoadDumpInfo kernel:" << kernel->fullname_with_scope();
|
|
dump_kernel_names_.emplace_back(kernel->fullname_with_scope());
|
|
|
|
aicpu::dump::Task task;
|
|
ConstructDumpTask(NOT_NULL(kernel), NOT_NULL(&task));
|
|
MS_EXCEPTION_IF_NULL(dump_info.mutable_task());
|
|
dump_info.mutable_task()->Add(std::move(task));
|
|
}
|
|
RtLoadDumpData(dump_info, &dev_load_mem_);
|
|
load_flag_ = true;
|
|
MS_LOG(INFO) << "[DataDump] LoadDumpInfo end";
|
|
}
|
|
|
|
void DataDumper::SetOpMappingInfo(NotNull<aicpu::dump::OpMappingInfo *> dump_info) const {
|
|
auto context_ptr = MsContext::GetInstance();
|
|
MS_EXCEPTION_IF_NULL(context_ptr);
|
|
MS_EXCEPTION_IF_NULL(kernel_graph_);
|
|
auto dump_path = DataDumpParser::GetInstance().GetDumpPath();
|
|
if (!dump_path.has_value()) {
|
|
MS_LOG(EXCEPTION) << "Dump path invalid";
|
|
}
|
|
auto device_id = context_ptr->device_id();
|
|
dump_info->set_dump_path(dump_path.value() + "_" + std::to_string(device_id) + "/");
|
|
MS_LOG(INFO) << "[DataDump] dump_path:" << dump_path.value();
|
|
|
|
dump_info->set_model_name(DataDumpParser::GetInstance().net_name() + "_" + std::to_string(kernel_graph_->graph_id()));
|
|
dump_info->set_dump_step(std::to_string(DataDumpParser::GetInstance().dump_step()));
|
|
dump_info->set_model_id(kernel_graph_->graph_id());
|
|
dump_info->set_flag(kAicpuLoadFlag);
|
|
|
|
const auto &input_ctrl_tensors = kernel_graph_->input_ctrl_tensors();
|
|
if (input_ctrl_tensors == nullptr || input_ctrl_tensors->size() < 3) {
|
|
MS_LOG(INFO) << "[DataDump] Not data sink mode, input_ctrl_tensor";
|
|
return;
|
|
}
|
|
const auto ¤t_step_tensor = input_ctrl_tensors->at(kCurrentStepTensorIndex);
|
|
const auto &currnet_epoch_tensor = input_ctrl_tensors->at(kCurrentEpochTensorIndex);
|
|
const auto &steps_per_epoch_tensor = input_ctrl_tensors->at(kStepsPerEpochTensorIndex);
|
|
|
|
MS_EXCEPTION_IF_NULL(current_step_tensor);
|
|
MS_EXCEPTION_IF_NULL(currnet_epoch_tensor);
|
|
MS_EXCEPTION_IF_NULL(steps_per_epoch_tensor);
|
|
MS_EXCEPTION_IF_NULL(current_step_tensor->device_address());
|
|
MS_EXCEPTION_IF_NULL(currnet_epoch_tensor->device_address());
|
|
MS_EXCEPTION_IF_NULL(steps_per_epoch_tensor->device_address());
|
|
|
|
void *current_step = current_step_tensor->device_address()->ptr_;
|
|
void *current_epoch = currnet_epoch_tensor->device_address()->ptr_;
|
|
void *steps_per_epoch = steps_per_epoch_tensor->device_address()->ptr_;
|
|
|
|
if (current_epoch != nullptr && current_step != nullptr && steps_per_epoch != nullptr) {
|
|
dump_info->set_step_id_addr(reinterpret_cast<uint64_t>(current_epoch));
|
|
dump_info->set_loop_cond_addr(reinterpret_cast<uint64_t>(current_step));
|
|
dump_info->set_iterations_per_loop_addr(reinterpret_cast<uint64_t>(steps_per_epoch));
|
|
} else {
|
|
MS_LOG(INFO) << "Invalid ctrl tensor device address";
|
|
}
|
|
}
|
|
|
|
bool DataDumper::KernelNeedDump(const CNodePtr &kernel) const {
|
|
if (AnfAlgo::GetKernelType(kernel) != TBE_KERNEL && AnfAlgo::GetKernelType(kernel) != AICPU_KERNEL &&
|
|
AnfAlgo::GetKernelType(kernel) != AKG_KERNEL) {
|
|
return false;
|
|
}
|
|
MS_EXCEPTION_IF_NULL(kernel);
|
|
const auto &kernel_set = DataDumpParser::GetInstance().kernel_set();
|
|
return kernel_set.find(kernel->fullname_with_scope()) != kernel_set.end();
|
|
}
|
|
|
|
void DataDumper::UnloadDumpInfo() {
|
|
if (!load_flag_) {
|
|
MS_LOG(WARNING) << "Load not success, no need to unload";
|
|
return;
|
|
}
|
|
MS_EXCEPTION_IF_NULL(kernel_graph_);
|
|
MS_LOG(INFO) << "[DataDump] UnloadDumpInfo start. graphId:" << kernel_graph_->graph_id();
|
|
|
|
aicpu::dump::OpMappingInfo op_mapping_info;
|
|
op_mapping_info.set_model_id(kernel_graph_->graph_id());
|
|
op_mapping_info.set_flag(kAicpuUnloadFlag);
|
|
|
|
for (const auto &kernel_name : dump_kernel_names_) {
|
|
aicpu::dump::Task task;
|
|
auto iter = runtime_info_map_.find(kernel_name);
|
|
if (iter == runtime_info_map_.end()) {
|
|
MS_LOG(EXCEPTION) << "[DataDump] kernel name not found in runtime_info_map";
|
|
}
|
|
MS_EXCEPTION_IF_NULL(iter->second);
|
|
auto task_id = std::get<kTupleTaskId>(*iter->second);
|
|
task.set_task_id(task_id);
|
|
MS_EXCEPTION_IF_NULL(op_mapping_info.mutable_task());
|
|
op_mapping_info.mutable_task()->Add(std::move(task));
|
|
}
|
|
|
|
RtLoadDumpData(op_mapping_info, &dev_unload_mem_);
|
|
}
|
|
|
|
void DataDumper::ReleaseDevMem(void **ptr) const {
|
|
if (ptr == nullptr) {
|
|
return;
|
|
}
|
|
if (*ptr != nullptr) {
|
|
rtError_t rt_error = rtFree(*ptr);
|
|
if (rt_error != RT_ERROR_NONE) {
|
|
MS_LOG(ERROR) << "[DataDump] Call rtFree failed, ret:" << rt_error;
|
|
}
|
|
*ptr = nullptr;
|
|
}
|
|
}
|
|
|
|
void DataDumper::ConstructDumpTask(NotNull<const CNodePtr &> kernel, NotNull<aicpu::dump::Task *> dump_task) const {
|
|
dump_task->set_end_graph(false);
|
|
auto iter = runtime_info_map_.find(kernel->fullname_with_scope());
|
|
if (iter == runtime_info_map_.end()) {
|
|
MS_LOG(EXCEPTION) << "[DataDump] kernel name not found in runtime_info_map";
|
|
}
|
|
MS_EXCEPTION_IF_NULL(iter->second);
|
|
auto task_id = std::get<kTupleTaskId>(*iter->second);
|
|
auto stream_id = std::get<kTupleStreamId>(*iter->second);
|
|
auto args = std::get<kTupleArgs>(*iter->second);
|
|
MS_LOG(INFO) << "[DataDump] Get runtime info task_id:" << task_id << " stream_id:" << stream_id;
|
|
|
|
dump_task->set_task_id(task_id);
|
|
dump_task->set_stream_id(stream_id);
|
|
MS_EXCEPTION_IF_NULL(dump_task->mutable_op());
|
|
dump_task->mutable_op()->set_op_name(kernel->fullname_with_scope());
|
|
dump_task->mutable_op()->set_op_type(AnfAlgo::GetCNodeName(kernel.get()));
|
|
|
|
DumpKernelOutput(kernel, args, dump_task);
|
|
DumpKernelInput(kernel, args, dump_task);
|
|
}
|
|
|
|
void RtLoadDumpData(const aicpu::dump::OpMappingInfo &dump_info, void **ptr) {
|
|
std::string proto_str;
|
|
size_t proto_size = dump_info.ByteSizeLong();
|
|
bool ret = dump_info.SerializeToString(&proto_str);
|
|
if (!ret || proto_size == 0) {
|
|
MS_LOG(EXCEPTION) << "[DataDump] Protobuf SerializeToString failed, proto size %zu.";
|
|
}
|
|
|
|
rtError_t rt_ret = rtMalloc(ptr, proto_size, RT_MEMORY_HBM);
|
|
if (rt_ret != RT_ERROR_NONE) {
|
|
MS_LOG(EXCEPTION) << "[DataDump] Call rtMalloc failed";
|
|
}
|
|
|
|
if (ptr == nullptr) {
|
|
MS_LOG(ERROR) << "[DataDump] rtMalloc failed, ptr is nullptr";
|
|
return;
|
|
}
|
|
rt_ret = rtMemcpy(*ptr, proto_size, proto_str.c_str(), proto_size, RT_MEMCPY_HOST_TO_DEVICE);
|
|
if (rt_ret != RT_ERROR_NONE) {
|
|
MS_LOG(EXCEPTION) << "[DataDump] Call rtMemcpy failed";
|
|
}
|
|
|
|
MS_LOG(INFO) << "[DataDump] rtDatadumpInfoLoad start";
|
|
rt_ret = rtDatadumpInfoLoad(*ptr, proto_size);
|
|
if (rt_ret != RT_ERROR_NONE) {
|
|
MS_LOG(EXCEPTION) << "[DataDump] Call rtDatadumpInfoLoad failed";
|
|
}
|
|
}
|
|
|
|
void DumpKernelOutput(const CNodePtr &kernel, void *args, NotNull<aicpu::dump::Task *> task) {
|
|
MS_LOG(INFO) << "[DataDump] DumpKernelOutput start. Kernel:" << kernel->fullname_with_scope();
|
|
auto input_size = AnfAlgo::GetInputTensorNum(kernel);
|
|
auto output_size = AnfAlgo::GetOutputTensorNum(kernel);
|
|
uint64_t offset = sizeof(void *) * input_size;
|
|
for (size_t i = 0; i < output_size; ++i) {
|
|
auto data_type = AnfAlgo::GetOutputDeviceDataType(kernel, i);
|
|
auto output_format = AnfAlgo::GetOutputFormat(kernel, i);
|
|
auto output_shape = AnfAlgo::GetOutputDeviceShape(kernel, i);
|
|
|
|
aicpu::dump::Output output;
|
|
output.set_data_type(GetGeDataType(data_type));
|
|
output.set_format(GetGeFormat(output_format, output_shape.size()));
|
|
MS_EXCEPTION_IF_NULL(output.mutable_shape());
|
|
for (auto dim : output_shape) {
|
|
output.mutable_shape()->add_dim(dim);
|
|
}
|
|
output.set_original_output_format(GetGeFormat(output_format, output_shape.size()));
|
|
output.set_address(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(args)) + offset);
|
|
MS_EXCEPTION_IF_NULL(task->mutable_output());
|
|
task->mutable_output()->Add(std::move(output));
|
|
offset += sizeof(void *);
|
|
}
|
|
}
|
|
|
|
void DumpKernelInput(const CNodePtr &kernel, void *args, NotNull<aicpu::dump::Task *> task) {
|
|
MS_LOG(INFO) << "[DataDump] DumpKernelInput start. Kernel:" << kernel->fullname_with_scope();
|
|
auto input_size = AnfAlgo::GetInputTensorNum(kernel);
|
|
uint64_t offset = 0;
|
|
for (size_t i = 0; i < input_size; ++i) {
|
|
aicpu::dump::Input input;
|
|
auto input_node_with_index = AnfAlgo::GetPrevNodeOutput(kernel, i);
|
|
auto input_node = input_node_with_index.first;
|
|
auto input_index = input_node_with_index.second;
|
|
std::string output_format = AnfAlgo::GetOutputFormat(input_node, input_index);
|
|
auto output_type = AnfAlgo::GetOutputDeviceDataType(input_node, input_index);
|
|
if (output_type == kTypeUnknown) {
|
|
MS_LOG(WARNING) << "[DataDump] It is not suggested to use a lonely weight parameter as the output of graph";
|
|
output_type = AnfAlgo::GetOutputInferDataType(input_node, input_index);
|
|
}
|
|
auto output_shape = AnfAlgo::GetOutputDeviceShape(input_node, input_index);
|
|
|
|
input.set_data_type(GetGeDataType(output_type));
|
|
input.set_format(GetGeFormat(output_format, output_shape.size()));
|
|
MS_EXCEPTION_IF_NULL(input.mutable_shape());
|
|
for (auto dim : output_shape) {
|
|
input.mutable_shape()->add_dim(dim);
|
|
}
|
|
input.set_address(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(args)) + offset);
|
|
MS_EXCEPTION_IF_NULL(task->mutable_input());
|
|
task->mutable_input()->Add(std::move(input));
|
|
offset += sizeof(void *);
|
|
}
|
|
}
|
|
} // namespace ascend
|
|
} // namespace device
|
|
} // namespace mindspore
|
|
#endif
|