* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This file is part of the MindStudio project.
*
* MindStudio is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* -------------------------------------------------------------------------*/
#include "analysis/csrc/application/timeline/hccl_assembler.h"
namespace Analysis
{
namespace Application
{
std::string HcclAssembler::TransEnumToType(uint64_t key, const std::unordered_map<std::string, uint16_t> &enumTable)
{
for (const auto &node : enumTable)
{
if (node.second == key)
{
return node.first;
}
}
return "";
}
HcclAssembler::HcclAssembler() : JsonAssembler(PROCESS_HCCL, {{MSPROF_JSON_FILE, FileCategory::MSPROF}}) {}
void HcclOpTraceEvent::ProcessArgs(JsonWriter &ostream)
{
ostream["rank_size"] << rankSize_;
ostream["connection_id"] << connectionId_;
ostream["model id"] << modelId_;
ostream["data_type"] << dataType_;
ostream["alg_type"] << algType_;
ostream["count"] << count_;
ostream["relay"] << relay_;
ostream["retry"] << retry_;
}
void HcclTaskTraceEvent::ProcessArgs(JsonWriter &ostream)
{
ostream["notify_id"] << notifyId_;
ostream["duration estimated(us)"] << esDur_;
ostream["stream id"] << streamId_;
ostream["task id"] << taskId_;
ostream["context id"] << contextId_;
ostream["task type"] << taskType;
ostream["src rank"] << srcRank_;
ostream["dst rank"] << dstRank_;
ostream["transport type"] << transportType_;
ostream["size(Byte)"] << size_;
ostream["data type"] << dataType_;
ostream["link type"] << linkType_;
ostream["bandwidth(GB/s)"] << bandwidth_;
ostream["model id"] << modelId_;
}
void HcclAssembler::GenerateMetaDataEvent(std::unordered_map<uint16_t, uint32_t> &pidMap, const LayerInfo &layerInfo,
const std::string &profPath)
{
uint32_t formatPid;
int32_t index = 0;
for (auto &it : groupIndex_)
{
formatPid = GetDevicePid(pidMap, it.first, profPath, layerInfo.sortIndex);
std::shared_ptr<MetaDataNameEvent> processName;
MAKE_SHARED_RETURN_VOID(processName, MetaDataNameEvent, formatPid, DEFAULT_TID, META_DATA_PROCESS_NAME,
layerInfo.component);
res_.push_back(processName);
std::shared_ptr<MetaDataLabelEvent> processLabel;
MAKE_SHARED_RETURN_VOID(processLabel, MetaDataLabelEvent, formatPid, DEFAULT_TID, META_DATA_PROCESS_LABEL,
GetLayerInfoLabelWithDeviceId(layerInfo.label, formatPid));
res_.push_back(processLabel);
std::shared_ptr<MetaDataIndexEvent> processIndex;
MAKE_SHARED_RETURN_VOID(processIndex, MetaDataIndexEvent, formatPid, DEFAULT_TID, META_DATA_PROCESS_INDEX,
layerInfo.sortIndex);
res_.push_back(processIndex);
for (auto &groupIt : it.second)
{
GenerateTMetaDataEvent(groupIt.second, index, formatPid);
}
}
}
void HcclAssembler::GenerateTMetaDataEvent(std::vector<HcclGroup> &groupInfo, int32_t &index, uint32_t formatPid)
{
std::string traceName;
std::string traceNameSuffix = "Communication";
for (auto &group : groupInfo)
{
auto startIndex = index;
traceName = group.groupName != NA ? ("Group " + group.groupName + " " + traceNameSuffix) : traceNameSuffix;
group.startIndex = index;
std::shared_ptr<MetaDataNameEvent> threadName;
MAKE_SHARED_RETURN_VOID(threadName, MetaDataNameEvent, formatPid, index, META_DATA_THREAD_NAME, traceName);
res_.push_back(threadName);
std::shared_ptr<MetaDataIndexEvent> threadIndex;
MAKE_SHARED_RETURN_VOID(threadIndex, MetaDataIndexEvent, formatPid, index, META_DATA_THREAD_INDEX, index);
res_.push_back(threadIndex);
for (const auto &plane : group.planes)
{
traceName = {"Plane " + std::to_string(plane)};
index = startIndex + plane + 1;
std::shared_ptr<MetaDataNameEvent> pThreadName;
MAKE_SHARED_RETURN_VOID(pThreadName, MetaDataNameEvent, formatPid, index, META_DATA_THREAD_NAME, traceName);
res_.push_back(pThreadName);
std::shared_ptr<MetaDataIndexEvent> pThreadIndex;
MAKE_SHARED_RETURN_VOID(pThreadIndex, MetaDataIndexEvent, formatPid, index, META_DATA_THREAD_INDEX, index);
res_.push_back(pThreadIndex);
}
index++;
}
}
int32_t HcclAssembler::GetTid(const std::string groupName, const uint16_t deviceId, const HcclType &type)
{
int32_t tid = -1;
auto it = groupIndex_.find(deviceId);
if (it != groupIndex_.end())
{
auto groupIt = it->second.find(groupName);
if (groupIt != it->second.end())
{
auto tmp = std::find_if(groupIt->second.begin(), groupIt->second.end(),
[&type](const HcclGroup &op) { return op.type == type; });
if (tmp != groupIt->second.end())
{
tid = tmp->startIndex;
}
}
}
return tid;
}
std::unordered_map<uint16_t, std::unordered_map<std::string, std::vector<HcclGroup>>> HcclAssembler::InitHcclGroup(
std::shared_ptr<std::vector<CommunicationTaskData>> &hcclData, std::shared_ptr<std::vector<KfcTaskData>> &kfcData)
{
std::unordered_map<uint16_t, std::unordered_map<std::string, std::vector<HcclGroup>>> groupTable;
std::unordered_map<uint16_t, std::unordered_map<std::string, std::set<int32_t>>> planesTable;
int32_t plainId;
if (hcclData != nullptr)
{
for (const auto &it : *hcclData)
{
plainId = it.planeId == INVALID_PLANE ? 0 : it.planeId;
planesTable[it.deviceId][it.groupName].emplace(plainId);
}
}
for (const auto &item : planesTable)
{
for (const auto &groupInfo : item.second)
{
groupTable[item.first][groupInfo.first].emplace_back(groupInfo.first, HcclType::HCCL, groupInfo.second);
}
}
planesTable.clear();
if (kfcData != nullptr)
{
for (const auto &it : *kfcData)
{
plainId = it.planeId == INVALID_PLANE ? 0 : it.planeId;
planesTable[it.deviceId][it.groupName].emplace(plainId);
}
}
for (const auto &item : planesTable)
{
for (const auto &groupInfo : item.second)
{
groupTable[item.first][groupInfo.first].emplace_back(groupInfo.first, HcclType::MC2, groupInfo.second);
}
}
return groupTable;
}
uint8_t HcclAssembler::AssembleData(DataInventory &dataInventory, JsonWriter &ostream, const std::string &profPath)
{
auto taskData = dataInventory.GetPtr<std::vector<CommunicationTaskData>>();
auto opData = dataInventory.GetPtr<std::vector<CommunicationOpData>>();
auto kfcTask = dataInventory.GetPtr<std::vector<KfcTaskData>>();
auto kfcOp = dataInventory.GetPtr<std::vector<KfcOpData>>();
if (taskData == nullptr && opData == nullptr && kfcTask == nullptr && kfcOp == nullptr)
{
WARN("Can't get hccl(kfc) task data and hccl(kfc) op data from dataInventory");
return DATA_NOT_EXIST;
}
std::unordered_map<uint16_t, uint32_t> devicePid;
auto layerInfo = GetLayerInfo(PROCESS_HCCL);
groupIndex_ = InitHcclGroup(taskData, kfcTask);
GenerateMetaDataEvent(devicePid, layerInfo, profPath);
if (taskData != nullptr)
{
GenerateCommTaskTrace<CommunicationTaskData>(*taskData, profPath, HcclType::HCCL, devicePid, layerInfo);
}
if (opData != nullptr)
{
GenerateCommOpTrace<CommunicationOpData>(*opData, profPath, HcclType::HCCL, devicePid, layerInfo);
}
if (kfcTask != nullptr)
{
GenerateCommTaskTrace<KfcTaskData>(*kfcTask, profPath, HcclType::MC2, devicePid, layerInfo);
}
if (kfcOp != nullptr)
{
GenerateCommOpTrace<KfcOpData>(*kfcOp, profPath, HcclType::MC2, devicePid, layerInfo);
}
if (res_.empty())
{
ERROR("Can't Generate any Ascend process data");
return ASSEMBLE_FAILED;
}
for (const auto &node : res_)
{
node->DumpJson(ostream);
}
ostream << ",";
return ASSEMBLE_SUCCESS;
}
}
}