| @@ -16,12 +16,15 @@ | |||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | - | ||
| 20 | 19 | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 21 | 24 | ||
| 22 | 25 | ||
| 23 | 26 | ||
| 24 | -#include "analysis/csrc/domain/data_process/ai_task/overlap_analysis_processor.h" | 27 | +#include "analysis/csrc/domain/data_process/data_processor.h" |
| 25 | 28 | ||
| 26 | 29 | ||
| 27 | 30 | ||
| @@ -53,7 +56,7 @@ | |||
| 53 | 56 | ||
| 54 | 57 | ||
| 55 | 58 | ||
| 56 | -#include "analysis/csrc/infrastructure/utils/thread_pool.h" | 59 | +#include "analysis/csrc/infrastructure/process/include/topo_callback_process.h" |
| 57 | 60 | ||
| 58 | namespace Analysis | 61 | namespace Analysis |
| 59 | { | 62 | { |
| @@ -161,7 +164,7 @@ bool CreateTableIndex(const std::string& tableName, const std::string& indexName | |||
| 161 | 164 | ||
| 162 | bool SaveApiData(DataInventory& dataInventory, DBInfo& msprofDB, const std::string& profPath) | 165 | bool SaveApiData(DataInventory& dataInventory, DBInfo& msprofDB, const std::string& profPath) |
| 163 | { | 166 | { |
| 164 | - uint32_t pid = Context::GetInstance().GetPidFromInfoJson(HOST_ID, profPath); | 167 | + uint32_t pid = Environment::Context::GetInstance().GetPidFromInfoJson(HOST_ID, profPath); |
| 165 | auto apiData = dataInventory.GetPtr<std::vector<ApiData>>(); | 168 | auto apiData = dataInventory.GetPtr<std::vector<ApiData>>(); |
| 166 | if (apiData == nullptr) | 169 | if (apiData == nullptr) |
| 167 | { | 170 | { |
| @@ -501,8 +504,8 @@ bool SaveHostInfoData(DataInventory& dataInventory, DBInfo& msprofDB, const std: | |||
| 501 | // hostuid, hostname | 504 | // hostuid, hostname |
| 502 | using HostInfoDataFormat = std::vector<std::tuple<std::string, std::string>>; | 505 | using HostInfoDataFormat = std::vector<std::tuple<std::string, std::string>>; |
| 503 | HostInfoDataFormat hostInfoData; | 506 | HostInfoDataFormat hostInfoData; |
| 504 | - std::string hostUid = Context::GetInstance().GetHostUid(HOST_ID, profPath); | 507 | + std::string hostUid = Environment::Context::GetInstance().GetHostUid(HOST_ID, profPath); |
| 505 | - std::string hostName = Context::GetInstance().GetHostName(HOST_ID, profPath); | 508 | + std::string hostName = Environment::Context::GetInstance().GetHostName(HOST_ID, profPath); |
| 506 | hostInfoData.emplace_back(hostUid, hostName); | 509 | hostInfoData.emplace_back(hostUid, hostName); |
| 507 | if (hostInfoData.empty()) | 510 | if (hostInfoData.empty()) |
| 508 | { | 511 | { |
| @@ -571,7 +574,7 @@ bool SaveMsprofTxData(DataInventory& dataInventory, DBInfo& msprofDB, const std: | |||
| 571 | ERROR("Reserved for MsprofTx data failed."); | 574 | ERROR("Reserved for MsprofTx data failed."); |
| 572 | return false; | 575 | return false; |
| 573 | } | 576 | } |
| 574 | - uint32_t pid = Context::GetInstance().GetPidFromInfoJson(HOST_ID, profPath); | 577 | + uint32_t pid = Environment::Context::GetInstance().GetPidFromInfoJson(HOST_ID, profPath); |
| 575 | for (const auto& item : *msprofTxData) | 578 | for (const auto& item : *msprofTxData) |
| 576 | { | 579 | { |
| 577 | uint64_t message = IdPool::GetInstance().GetUint64Id(item.message); | 580 | uint64_t message = IdPool::GetInstance().GetUint64Id(item.message); |
| @@ -588,7 +591,7 @@ void UpdateNpuData(const std::string& profPath, const std::string& deviceDir, | |||
| 588 | std::vector<std::tuple<int16_t, int16_t>>& rankDeviceMapData) | 591 | std::vector<std::tuple<int16_t, int16_t>>& rankDeviceMapData) |
| 589 | { | 592 | { |
| 590 | uint16_t deviceId = Utils::GetDeviceIdByDevicePath(deviceDir); | 593 | uint16_t deviceId = Utils::GetDeviceIdByDevicePath(deviceDir); |
| 591 | - uint16_t chip = Context::GetInstance().GetPlatformVersion(deviceId, profPath); | 594 | + uint16_t chip = Environment::Context::GetInstance().GetPlatformVersion(deviceId, profPath); |
| 592 | std::string chipName; | 595 | std::string chipName; |
| 593 | auto it = CHIP_TABLE.find(chip); | 596 | auto it = CHIP_TABLE.find(chip); |
| 594 | if (it == CHIP_TABLE.end()) | 597 | if (it == CHIP_TABLE.end()) |
| @@ -694,7 +697,7 @@ bool SaveNpuOpMemData(DataInventory& dataInventory, DBInfo& msprofDB, const std: | |||
| 694 | return false; | 697 | return false; |
| 695 | } | 698 | } |
| 696 | uint64_t stringGeId = IdPool::GetInstance().GetUint64Id("GE"); | 699 | uint64_t stringGeId = IdPool::GetInstance().GetUint64Id("GE"); |
| 697 | - uint32_t pid = Context::GetInstance().GetPidFromInfoJson(HOST_ID, profPath); | 700 | + uint32_t pid = Environment::Context::GetInstance().GetPidFromInfoJson(HOST_ID, profPath); |
| 698 | uint64_t operatorNameId; | 701 | uint64_t operatorNameId; |
| 699 | uint64_t globalTid; | 702 | uint64_t globalTid; |
| 700 | for (const auto& item : *npuOpMemData) | 703 | for (const auto& item : *npuOpMemData) |
| @@ -768,7 +771,7 @@ bool SaveSessionTimeInfoData(DataInventory& dataInventory, DBInfo& msprofDB, con | |||
| 768 | // startTime, endTime | 771 | // startTime, endTime |
| 769 | using TimeDataFormat = std::vector<std::tuple<uint64_t, uint64_t>>; | 772 | using TimeDataFormat = std::vector<std::tuple<uint64_t, uint64_t>>; |
| 770 | Utils::ProfTimeRecord tempRecord; | 773 | Utils::ProfTimeRecord tempRecord; |
| 771 | - if (!Context::GetInstance().GetProfTimeRecordInfo(tempRecord, profPath)) | 774 | + if (!Environment::Context::GetInstance().GetProfTimeRecordInfo(tempRecord, profPath)) |
| 772 | { | 775 | { |
| 773 | ERROR("GetProfTimeRecordInfo failed, profPath is %.", profPath); | 776 | ERROR("GetProfTimeRecordInfo failed, profPath is %.", profPath); |
| 774 | return false; | 777 | return false; |
| @@ -878,7 +881,7 @@ bool SaveAscendTaskData(DataInventory& dataInventory, DBInfo& msprofDB, const st | |||
| 878 | return false; | 881 | return false; |
| 879 | } | 882 | } |
| 880 | uint64_t globalTaskId; | 883 | uint64_t globalTaskId; |
| 881 | - uint32_t globalPid = Context::GetInstance().GetPidFromInfoJson(HOST_ID, profPath); | 884 | + uint32_t globalPid = Environment::Context::GetInstance().GetPidFromInfoJson(HOST_ID, profPath); |
| 882 | uint64_t taskType; | 885 | uint64_t taskType; |
| 883 | if (ascendTaskData != nullptr) | 886 | if (ascendTaskData != nullptr) |
| 884 | { | 887 | { |
| @@ -1195,16 +1198,6 @@ bool SaveOSRuntimeApiData(DataInventory& dataInventory, DBInfo& msprofDB, const | |||
| 1195 | bool SaveOverlapAnalysisData(DataInventory& dataInventory, DBInfo& msprofDB, const std::string& profPath) | 1198 | bool SaveOverlapAnalysisData(DataInventory& dataInventory, DBInfo& msprofDB, const std::string& profPath) |
| 1196 | { | 1199 | { |
| 1197 | auto overlapData = dataInventory.GetPtr<std::vector<OverlapAnalysisData>>(); | 1200 | auto overlapData = dataInventory.GetPtr<std::vector<OverlapAnalysisData>>(); |
| 1198 | - if (overlapData == nullptr) | ||
| 1199 | - { | ||
| 1200 | - OverlapAnalysisProcessor processor(profPath); | ||
| 1201 | - if (!processor.Run(dataInventory, PROCESSOR_NAME_OVERLAP_ANALYSIS)) | ||
| 1202 | - { | ||
| 1203 | - ERROR("Process overlap analysis data failed."); | ||
| 1204 | - return false; | ||
| 1205 | - } | ||
| 1206 | - overlapData = dataInventory.GetPtr<std::vector<OverlapAnalysisData>>(); | ||
| 1207 | - } | ||
| 1208 | if (overlapData == nullptr || overlapData->empty()) | 1201 | if (overlapData == nullptr || overlapData->empty()) |
| 1209 | { | 1202 | { |
| 1210 | WARN("Overlap analysis data not exist."); | 1203 | WARN("Overlap analysis data not exist."); |
| @@ -1246,7 +1239,7 @@ bool SaveQosData(DataInventory& dataInventory, DBInfo& msprofDB, const std::stri | |||
| 1246 | for (const auto& devicePath : deviceList) | 1239 | for (const auto& devicePath : deviceList) |
| 1247 | { | 1240 | { |
| 1248 | auto deviceId = GetDeviceIdByDevicePath(devicePath); | 1241 | auto deviceId = GetDeviceIdByDevicePath(devicePath); |
| 1249 | - auto qosEvents = Context::GetInstance().GetQosEvents(deviceId, profPath); | 1242 | + auto qosEvents = Environment::Context::GetInstance().GetQosEvents(deviceId, profPath); |
| 1250 | std::vector<uint64_t> qosEventsIds; | 1243 | std::vector<uint64_t> qosEventsIds; |
| 1251 | for (const auto& event : qosEvents) | 1244 | for (const auto& event : qosEvents) |
| 1252 | { | 1245 | { |
| @@ -1488,9 +1481,9 @@ bool SaveCCUData(DataInventory& dataInventory, DBInfo& msprofDB, const std::stri | |||
| 1488 | 1481 | ||
| 1489 | return SaveData(res, TABLE_NAME_CCU, msprofDB); | 1482 | return SaveData(res, TABLE_NAME_CCU, msprofDB); |
| 1490 | } | 1483 | } |
| 1491 | -// 创建 SaveData 的函数类型 | 1484 | +const std::string DB_PREFIX = "DB:"; |
| 1492 | -using SaveDataFunc = std::function<bool(DataInventory& dataInventory, DBInfo& msprofDB, const std::string& profPath)>; | 1485 | +const std::string DB_STRING_IDS = DB_PREFIX + TABLE_NAME_STRING_IDS; |
| 1493 | -const std::unordered_map<std::string, SaveDataFunc> DATA_SAVER = { | 1486 | +const std::unordered_map<std::string, DBSaveDataFunc> DATA_SAVER = { |
| 1494 | {PROCESSOR_NAME_API, SaveApiData}, | 1487 | {PROCESSOR_NAME_API, SaveApiData}, |
| 1495 | {PROCESSOR_NAME_COMMUNICATION, SaveCommunicationData}, | 1488 | {PROCESSOR_NAME_COMMUNICATION, SaveCommunicationData}, |
| 1496 | {PROCESSOR_NAME_ACC_PMU, SaveAccPmuData}, | 1489 | {PROCESSOR_NAME_ACC_PMU, SaveAccPmuData}, |
| @@ -1532,107 +1525,67 @@ const std::unordered_map<std::string, SaveDataFunc> DATA_SAVER = { | |||
| 1532 | {PROCESSOR_NAME_CCU_MISSION, SaveCCUData}, | 1525 | {PROCESSOR_NAME_CCU_MISSION, SaveCCUData}, |
| 1533 | }; | 1526 | }; |
| 1534 | 1527 | ||
| 1535 | -bool CheckMsprofDb(const std::string& outputPath) | ||
| 1536 | -{ | ||
| 1537 | - std::vector<std::string> files = File::GetOriginData(outputPath, {DB_NAME_MSPROF_DB}, {".json", ".csv"}); | ||
| 1538 | - if (files.empty()) | ||
| 1539 | - { | ||
| 1540 | - return false; | ||
| 1541 | - } | ||
| 1542 | - std::string timestampMax; | ||
| 1543 | - std::string latestFile; | ||
| 1544 | - for (const auto& file : files) | ||
| 1545 | - { | ||
| 1546 | - auto dbName = Split(file, "/").back(); | ||
| 1547 | - size_t start = dbName.find(DB_NAME_MSPROF_DB) + DB_NAME_MSPROF_DB.length() + 1; | ||
| 1548 | - size_t end = dbName.find(".db"); | ||
| 1549 | - if (start == std::string::npos || end == std::string::npos) continue; | ||
| 1550 | - | ||
| 1551 | - std::string timestampStr = dbName.substr(start, end - start); | ||
| 1552 | - if (!IsNumber(timestampStr) || timestampStr.size() != EXPECT_TIME_LEN) | ||
| 1553 | - { | ||
| 1554 | - ERROR("Invalid msprof db name %.", dbName); | ||
| 1555 | - continue; | ||
| 1556 | - } | ||
| 1557 | - if (timestampStr > timestampMax) | ||
| 1558 | - { | ||
| 1559 | - timestampMax = timestampStr; | ||
| 1560 | - latestFile = file; | ||
| 1561 | - } | ||
| 1562 | - } | ||
| 1563 | - | ||
| 1564 | - DBInfo msprofDB(latestFile, TABLE_NAME_STRING_IDS); | ||
| 1565 | - if (!msprofDB.ConstructDBRunner(latestFile)) | ||
| 1566 | - { | ||
| 1567 | - ERROR("Construct for msprof db runner failed."); | ||
| 1568 | - return false; | ||
| 1569 | - } | ||
| 1570 | - | ||
| 1571 | - if (!Utils::FileReader::Check(latestFile, MAX_DB_BYTES)) | ||
| 1572 | - { | ||
| 1573 | - ERROR("Check % failed.", latestFile); | ||
| 1574 | - return false; | ||
| 1575 | - } | ||
| 1576 | - if (msprofDB.dbRunner->CheckTableExists(msprofDB.tableName)) | ||
| 1577 | - { | ||
| 1578 | - INFO("Find completed msprof db, %.", latestFile); | ||
| 1579 | - return true; | ||
| 1580 | - } | ||
| 1581 | - | ||
| 1582 | - INFO("The % database is incomplete and will be deleted.", latestFile); | ||
| 1583 | - PRINT_INFO("The % database is incomplete and will be deleted.", latestFile); | ||
| 1584 | - if (!Utils::File::DeleteFile(latestFile)) | ||
| 1585 | - { | ||
| 1586 | - ERROR("Failed to delete file, %.", latestFile); | ||
| 1587 | - } | ||
| 1588 | - return false; | ||
| 1589 | -} | ||
| 1590 | - | ||
| 1591 | std::string GetDBPath(const std::string& outputDir) | 1528 | std::string GetDBPath(const std::string& outputDir) |
| 1592 | { | 1529 | { |
| 1593 | return Utils::File::PathJoin({outputDir, DB_NAME_MSPROF_DB + "_" + Analysis::Utils::GetFormatLocalTime() + ".db"}); | 1530 | return Utils::File::PathJoin({outputDir, DB_NAME_MSPROF_DB + "_" + Analysis::Utils::GetFormatLocalTime() + ".db"}); |
| 1594 | } | 1531 | } |
| 1595 | 1532 | ||
| 1596 | -const std::set<std::string> DB_DATA_PROCESS_LIST{ | ||
| 1597 | - PROCESSOR_NAME_API, | ||
| 1598 | - PROCESSOR_NAME_COMMUNICATION, | ||
| 1599 | - PROCESSOR_NAME_COMPUTE_TASK_INFO, | ||
| 1600 | - PROCESSOR_NAME_KFC_TASK, | ||
| 1601 | - PROCESSOR_NAME_DEVICE_TX, | ||
| 1602 | - PROCESSOR_NAME_MSTX, | ||
| 1603 | - PROCESSOR_NAME_STEP_TRACE, | ||
| 1604 | - PROCESSOR_NAME_TASK, | ||
| 1605 | - PROCESSOR_NAME_ACC_PMU, | ||
| 1606 | - PROCESSOR_NAME_AICORE_FREQ, | ||
| 1607 | - PROCESSOR_NAME_LOW_POWER, | ||
| 1608 | - PROCESSOR_NAME_DDR, | ||
| 1609 | - PROCESSOR_NAME_HBM, | ||
| 1610 | - PROCESSOR_NAME_HCCS, | ||
| 1611 | - PROCESSOR_NAME_NETDEV_STATS, | ||
| 1612 | - PROCESSOR_NAME_CPU_USAGE, | ||
| 1613 | - PROCESSOR_NAME_MEM_USAGE, | ||
| 1614 | - PROCESSOR_NAME_DISK_USAGE, | ||
| 1615 | - PROCESSOR_NAME_NETWORK_USAGE, | ||
| 1616 | - PROCESSOR_NAME_OSRT_API, | ||
| 1617 | - PROCESSOR_NAME_LLC, | ||
| 1618 | - PROCESSOR_NAME_NPU_MEM, | ||
| 1619 | - PROCESSOR_NAME_PCIE, | ||
| 1620 | - PROCESSOR_NAME_DPU, | ||
| 1621 | - PROCESSOR_NAME_SIO, | ||
| 1622 | - PROCESSOR_NAME_UB, | ||
| 1623 | - PROCESSOR_NAME_SOC, | ||
| 1624 | - PROCESSOR_NAME_NIC, | ||
| 1625 | - PROCESSOR_NAME_ROCE, | ||
| 1626 | - PROCESSOR_NAME_QOS, | ||
| 1627 | - PROCESSOR_NAME_CCU_MISSION, | ||
| 1628 | - PROCESSOR_MC2_COMM_INFO, | ||
| 1629 | - PROCESSOR_NAME_MEMCPY_INFO, | ||
| 1630 | - PROCESSOR_NAME_NPU_OP_MEM, | ||
| 1631 | - PROCESSOR_NAME_NPU_MODULE_MEM, | ||
| 1632 | - PROCESSOR_NAME_UNIFIED_PMU, | ||
| 1633 | -}; | ||
| 1634 | } // namespace | 1533 | } // namespace |
| 1635 | 1534 | ||
| 1535 | +TopoNodeCreatorFactory DBAssembler::CreateSaver(const std::string& name) | ||
Y | |||
| 1536 | +{ | ||
| 1537 | + return [name](const TopoBuildContext& context) -> Infra::ProcessCreator | ||
| 1538 | + { | ||
| 1539 | + const auto saverIter = DATA_SAVER.find(name.substr(DB_PREFIX.size())); | ||
Y 【review】 问题:name.substr(DB_PREFIX.size()) 存在越界/异常风险 CreateSaver 里直接执行 name.substr(DB_PREFIX.size()),但这段代码没有先确认 name 是否真的以 DB_PREFIX 开头,也没有确认长度是否足够。 如果传入的 name 不符合预期,substr 可能抛出 std::out_of_range,这里又没有异常保护,会直接中断流程。 建议: 在截取前先做前缀和长度校验,例如先判断 name.size() >= DB_PREFIX.size() 且 name.compare(0, DB_PREFIX.size(), DB_PREFIX) == 0。 如果不满足条件,建议直接返回空的 ProcessCreator,同时补一条错误或告警日志,方便定位非法入参。 ![]() ![]() | |||
| 1540 | + if (saverIter == DATA_SAVER.end()) | ||
| 1541 | + { | ||
| 1542 | + return Infra::ProcessCreator(); | ||
| 1543 | + } | ||
| 1544 | + const auto session = context.dbSession; | ||
Y 【review】 问题:session 的生命周期可能不安全 两个函数都从 context.dbSession 取出 session,然后被多层 lambda 捕获并延后执行。 如果 dbSession 本质上是裸指针,或者它背后的对象生命周期短于 Process 的执行周期,这里就有悬空引用/悬空指针风险,后续访问 session->msprofDB_、session->profPath_ 可能导致未定义行为。 建议: 明确 dbSession 的所有权模型。 如果它本身就是 shared_ptr,那当前“按值捕获”通常是安全的,但建议在代码里体现这一点,降低误读成本。 如果不是共享所有权对象,建议改成显式延长生命周期的方案,比如持有 shared_ptr,或者在更高层保证 session 生命周期覆盖整个异步执行过程。 ![]() ![]() | |||
| 1545 | + if (session == nullptr) | ||
| 1546 | + { | ||
| 1547 | + return Infra::ProcessCreator(); | ||
| 1548 | + } | ||
| 1549 | + const DBSaveDataFunc saver = saverIter->second; | ||
| 1550 | + return [name, saver, session]() -> std::unique_ptr<Infra::Process> | ||
| 1551 | + { | ||
| 1552 | + return std::unique_ptr<Infra::Process>(new (std::nothrow) TopoCallbackProcess( | ||
| 1553 | + [name, saver, session](DataInventory& dataInventory) -> bool | ||
| 1554 | + { | ||
| 1555 | + INFO("Begin to save % data.", name); | ||
| 1556 | + const bool result = saver(dataInventory, session->msprofDB_, session->profPath_); | ||
| 1557 | + if (!result) | ||
| 1558 | + { | ||
| 1559 | + ERROR("Save % data failed.", name); | ||
| 1560 | + } | ||
| 1561 | + return result; | ||
| 1562 | + })); | ||
| 1563 | + }; | ||
| 1564 | + }; | ||
| 1565 | +} | ||
| 1566 | + | ||
| 1567 | +TopoNodeCreatorFactory DBAssembler::CreateStringIdsSaver() | ||
Y 【review】 问题:保存失败时的日志语义不一致,CreateStringIdsSaver 甚至会误报成功结束 CreateSaver 中有开始日志,失败时也会打印错误日志;但 CreateStringIdsSaver 中无论 SaveStringIdsData(...) 成功还是失败,都会打印 End exporting db output_file... 这会让日志看起来像“已经成功结束导出”,实际却可能失败,容易误导排查。 建议: 统一日志策略: 成功时打印成功结束日志,失败时打印错误日志,不要在失败路径输出成功语义的信息。 最好让 CreateStringIdsSaver 的日志风格与 CreateSaver 保持一致,例如: 开始保存时打印开始日志 result == false 时打印失败日志 result == true 时再打印完成日志 ![]() ![]() | |||
| 1568 | +{ | ||
| 1569 | + return [](const TopoBuildContext& context) -> Infra::ProcessCreator | ||
Y 【review】 问题:关键失败分支静默返回,排障信息不足 两处代码在以下情况下都只是直接返回空的 Infra::ProcessCreator(): DATA_SAVER 中找不到对应 saver session == nullptr 从功能上看这是“失败”,但从日志上看几乎无痕。调用方如果只是拿到空 creator,很难快速判断是配置名错了、前缀不对,还是 session 没初始化。 建议: 在这些返回空对象的分支增加明确日志,至少带上 name 或分支原因。 例如: saver 未注册:打印 name 和实际查找 key session == nullptr:打印上下文缺失信息 这样后续定位问题会快很多。 ![]() ![]() | |||
| 1570 | + { | ||
| 1571 | + const auto session = context.dbSession; | ||
| 1572 | + if (session == nullptr) | ||
| 1573 | + { | ||
| 1574 | + return Infra::ProcessCreator(); | ||
| 1575 | + } | ||
| 1576 | + return [session]() -> std::unique_ptr<Infra::Process> | ||
| 1577 | + { | ||
| 1578 | + return std::unique_ptr<Infra::Process>(new (std::nothrow) TopoCallbackProcess( | ||
| 1579 | + [session](DataInventory& dataInventory) -> bool | ||
| 1580 | + { | ||
| 1581 | + const bool result = SaveStringIdsData(dataInventory, session->msprofDB_, session->profPath_); | ||
| 1582 | + PRINT_INFO("End exporting db output_file. The file is stored in the PROF file."); | ||
| 1583 | + return result; | ||
| 1584 | + })); | ||
| 1585 | + }; | ||
| 1586 | + }; | ||
| 1587 | +} | ||
| 1588 | + | ||
| 1636 | DBAssembler::DBAssembler(const std::string& profPath, const std::string& outputPath) | 1589 | DBAssembler::DBAssembler(const std::string& profPath, const std::string& outputPath) |
| 1637 | : profPath_(profPath), outputPath_(outputPath) | 1590 | : profPath_(profPath), outputPath_(outputPath) |
| 1638 | { | 1591 | { |
| @@ -1642,44 +1595,44 @@ DBAssembler::DBAssembler(const std::string& profPath, const std::string& outputP | |||
| 1642 | msprofDB_.ConstructDBRunner(msprofDBPath); | 1595 | msprofDB_.ConstructDBRunner(msprofDBPath); |
| 1643 | } | 1596 | } |
| 1644 | 1597 | ||
| 1645 | -bool DBAssembler::Run(DataInventory& dataInventory) | 1598 | +bool DBAssembler::GetTopologyRoots(std::vector<TopoNodeId>& roots) |
| 1646 | { | 1599 | { |
| 1647 | - INFO("Start exporting db!"); | 1600 | + const size_t rootsSize = roots.size(); |
| 1648 | - PRINT_INFO("Start exporting the db!"); | 1601 | + for (const auto& saver : DATA_SAVER) |
| 1649 | - if (CheckMsprofDb(outputPath_)) | ||
| 1650 | { | 1602 | { |
| 1651 | - PRINT_INFO("Find completed msprof db. End exporting db output_file."); | 1603 | + const TopoNodeId id{TopoNodeStage::DATABASE_PERSISTENCE, DB_PREFIX + saver.first}; |
| 1652 | - return true; | 1604 | + if (TopoNodeRegistry::Find(id) == nullptr) |
| 1605 | + { | ||
| 1606 | + ERROR("DB execution list node % has no static topology registration.", id.name); | ||
| 1607 | + roots.resize(rootsSize); | ||
| 1608 | + return false; | ||
| 1609 | + } | ||
| 1610 | + roots.push_back(id); | ||
| 1653 | } | 1611 | } |
| 1654 | - | 1612 | + const TopoNodeId stringIds{TopoNodeStage::FLOW_CONTROL, DB_STRING_IDS}; |
| 1655 | - std::atomic<bool> retFlag(true); | 1613 | + if (TopoNodeRegistry::Find(stringIds) == nullptr) |
| 1656 | - const uint16_t processorsLimit = 10; // 最多有10个线程 | ||
| 1657 | - Analysis::Utils::ThreadPool pool(processorsLimit); | ||
| 1658 | - pool.Start(); | ||
| 1659 | - | ||
| 1660 | - for (const auto& saveFunc : DATA_SAVER) | ||
| 1661 | { | 1614 | { |
| 1662 | - pool.AddTask( | 1615 | + ERROR("DB StringIds node has no static topology registration."); |
| 1663 | - [saveFunc, &retFlag, &dataInventory, this]() | 1616 | + roots.resize(rootsSize); |
| 1664 | - { | 1617 | + return false; |
| 1665 | - INFO("Begin to save % data.", saveFunc.first); | ||
| 1666 | - auto flag = saveFunc.second(dataInventory, msprofDB_, profPath_); | ||
| 1667 | - if (!flag) | ||
| 1668 | - { | ||
| 1669 | - ERROR("Save % data failed.", saveFunc.first); | ||
| 1670 | - } | ||
| 1671 | - retFlag = flag && retFlag; | ||
| 1672 | - }); | ||
| 1673 | } | 1618 | } |
| 1674 | - pool.WaitAllTasks(); | 1619 | + roots.push_back(stringIds); |
| 1675 | - pool.Stop(); | 1620 | + return true; |
| 1676 | - | 1621 | +} |
| 1677 | - // StringIds为id到name映射表,需要最后落盘 | 1622 | + |
| 1678 | - retFlag = SaveStringIdsData(dataInventory, msprofDB_, profPath_) && retFlag; | 1623 | +std::vector<TopoNodeId> DBAssembler::ResolveSelectedDBSavers(const TopoBuildContext&, |
| 1679 | - PRINT_INFO("End exporting db output_file. The file is stored in the PROF file."); | 1624 | + const std::vector<TopoNodeId>& roots) |
| 1680 | - return retFlag; | 1625 | +{ |
| 1626 | + std::vector<TopoNodeId> dependencies; | ||
| 1627 | + for (const auto& root : roots) | ||
| 1628 | + { | ||
| 1629 | + if (root.stage == TopoNodeStage::DATABASE_PERSISTENCE) | ||
| 1630 | + { | ||
| 1631 | + dependencies.push_back(root); | ||
| 1632 | + } | ||
| 1633 | + } | ||
| 1634 | + return dependencies; | ||
| 1681 | } | 1635 | } |
| 1682 | 1636 | ||
| 1683 | -const std::set<std::string>& DBAssembler::GetProcessList() { return DB_DATA_PROCESS_LIST; } | ||
| 1684 | } // namespace Application | 1637 | } // namespace Application |
| 1685 | } // namespace Analysis | 1638 | } // namespace Analysis |
| @@ -17,9 +17,14 @@ | |||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 20 | 24 | ||
| 21 | 25 | ||
| 22 | 26 | ||
| 27 | + | ||
| 23 | 28 | ||
| 24 | 29 | ||
| 25 | namespace Analysis | 30 | namespace Analysis |
| @@ -28,14 +33,19 @@ namespace Application | |||
| 28 | { | 33 | { |
| 29 | using namespace Analysis::Infra; | 34 | using namespace Analysis::Infra; |
| 30 | 35 | ||
| 36 | +using DBSaveDataFunc = std::function<bool(DataInventory &dataInventory, DBInfo &msprofDB, const std::string &profPath)>; | ||
| 37 | + | ||
| 31 | class DBAssembler | 38 | class DBAssembler |
| 32 | { | 39 | { |
| 33 | public: | 40 | public: |
| 34 | DBAssembler() = default; | 41 | DBAssembler() = default; |
| 35 | DBAssembler(const std::string &profPath, const std::string &outputPath); | 42 | DBAssembler(const std::string &profPath, const std::string &outputPath); |
| 36 | virtual ~DBAssembler() = default; | 43 | virtual ~DBAssembler() = default; |
| 37 | - bool Run(DataInventory &dataInventory); | 44 | + static bool GetTopologyRoots(std::vector<TopoNodeId> &roots); |
| 38 | - const static std::set<std::string> &GetProcessList(); | 45 | + static std::vector<TopoNodeId> ResolveSelectedDBSavers(const TopoBuildContext &context, |
| 46 | + const std::vector<TopoNodeId> &roots); | ||
| 47 | + static TopoNodeCreatorFactory CreateSaver(const std::string &name); | ||
| 48 | + static TopoNodeCreatorFactory CreateStringIdsSaver(); | ||
| 39 | 49 | ||
| 40 | private: | 50 | private: |
| 41 | std::string profPath_; | 51 | std::string profPath_; |
| @@ -0,0 +1,167 @@ | |||
| 1 | +/* ------------------------------------------------------------------------- | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This file is part of the MindStudio project. | ||
| 4 | + * | ||
| 5 | + * MindStudio is licensed under Mulan PSL v2. | ||
| 6 | + * You can use this software according to the terms and conditions of the Mulan PSL v2. | ||
| 7 | + * You may obtain a copy of Mulan PSL v2 at: | ||
| 8 | + * | ||
| 9 | + * http://license.coscl.org.cn/MulanPSL2 | ||
| 10 | + * | ||
| 11 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, | ||
| 12 | + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, | ||
| 13 | + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. | ||
| 14 | + * See the Mulan PSL v2 for more details. | ||
| 15 | + * -------------------------------------------------------------------------*/ | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + | ||
| 32 | + | ||
| 33 | + | ||
| 34 | + | ||
| 35 | + | ||
| 36 | + | ||
| 37 | + | ||
| 38 | + | ||
| 39 | + | ||
| 40 | + | ||
| 41 | + | ||
| 42 | + | ||
| 43 | + | ||
| 44 | + | ||
| 45 | + | ||
| 46 | + | ||
| 47 | + | ||
| 48 | + | ||
| 49 | +namespace Analysis | ||
| 50 | +{ | ||
| 51 | +namespace Application | ||
| 52 | +{ | ||
| 53 | +using namespace Analysis::Domain; | ||
| 54 | + | ||
| 55 | +namespace | ||
| 56 | +{ | ||
| 57 | +const std::string DB_PREFIX = "DB:"; | ||
| 58 | +const std::string DB_STRING_IDS = DB_PREFIX + TABLE_NAME_STRING_IDS; | ||
| 59 | + | ||
| 60 | +} // namespace | ||
| 61 | + | ||
| 62 | + | ||
| 63 | + REGISTER_TOPO_NODE_SEQUENCE(typeid(void), TOPO_NODE(DATABASE_PERSISTENCE, DB_PREFIX + Name), true, \ | ||
| 64 | + DBAssembler::CreateSaver(DB_PREFIX + Name), Dependencies, nullptr) | ||
| 65 | + | ||
| 66 | + | ||
| 67 | + REGISTER_DB_SAVER(Name, Dependencies); \ | ||
| 68 | + REGISTER_TOPO_NODE_DEPENDENT_DATA(TOPO_NODE(DATABASE_PERSISTENCE, DB_PREFIX + Name), __VA_ARGS__) | ||
| 69 | + | ||
| 70 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_API, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_API)), | ||
| 71 | + std::vector<ApiData>); | ||
| 72 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_COMMUNICATION, | ||
| 73 | + TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_COMMUNICATION)), | ||
| 74 | + std::vector<CommunicationOpData>, std::vector<KfcOpData>, | ||
| 75 | + std::vector<CommunicationTaskData>, std::vector<KfcTaskData>); | ||
| 76 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_ACC_PMU, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_ACC_PMU)), | ||
| 77 | + std::vector<AccPmuData>); | ||
| 78 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_AICORE_FREQ, | ||
| 79 | + TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_AICORE_FREQ), | ||
| 80 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_LOW_POWER)), | ||
| 81 | + std::vector<LowPowerData>); | ||
| 82 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_DDR, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_DDR)), | ||
| 83 | + std::vector<DDRData>); | ||
| 84 | +REGISTER_DB_SAVER(PROCESSOR_NAME_ENUM, TOPO_DEPS()); | ||
| 85 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_HBM, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_HBM)), | ||
| 86 | + std::vector<HbmData>); | ||
| 87 | +REGISTER_DB_SAVER(PROCESSOR_NAME_HOST_INFO, TOPO_DEPS()); | ||
| 88 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_HCCS, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_HCCS)), | ||
| 89 | + std::vector<HccsData>); | ||
| 90 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_NETDEV_STATS, | ||
| 91 | + TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_NETDEV_STATS)), | ||
| 92 | + std::vector<NetDevStatsEventData>); | ||
| 93 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_LLC, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_LLC)), | ||
| 94 | + std::vector<LLcData>); | ||
| 95 | +REGISTER_DB_SAVER(PROCESSOR_NAME_META_DATA, TOPO_DEPS()); | ||
| 96 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_MSTX, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_MSTX)), | ||
| 97 | + std::vector<MsprofTxHostData>); | ||
| 98 | +REGISTER_DB_SAVER(PROCESSOR_NAME_NPU_INFO, TOPO_DEPS()); | ||
| 99 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_NPU_MEM, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_NPU_MEM)), | ||
| 100 | + std::vector<NpuMemData>); | ||
| 101 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_NPU_OP_MEM, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_NPU_OP_MEM)), | ||
| 102 | + std::vector<NpuOpMemData>); | ||
| 103 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_NPU_MODULE_MEM, | ||
| 104 | + TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_NPU_MODULE_MEM)), | ||
| 105 | + std::vector<NpuModuleMemData>); | ||
| 106 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_PCIE, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_PCIE)), | ||
| 107 | + std::vector<PCIeData>); | ||
| 108 | +REGISTER_DB_SAVER(PROCESSOR_NAME_SESSION_TIME_INFO, TOPO_DEPS()); | ||
| 109 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_SOC, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_SOC)), | ||
| 110 | + std::vector<SocBandwidthData>); | ||
| 111 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_NIC, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_NIC)), | ||
| 112 | + std::vector<NicOriginalData>); | ||
| 113 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_ROCE, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_ROCE)), | ||
| 114 | + std::vector<RoceOriginalData>); | ||
| 115 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_DPU, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_DPU)), | ||
| 116 | + std::vector<DPUData>); | ||
| 117 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_SIO, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_SIO)), | ||
| 118 | + std::vector<SioData>); | ||
| 119 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_UB, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_UB)), | ||
| 120 | + std::vector<UbData>); | ||
| 121 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_TASK, | ||
| 122 | + TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_TASK), | ||
| 123 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_DEVICE_TX)), | ||
| 124 | + std::vector<AscendTaskData>, std::vector<MsprofTxDeviceData>); | ||
| 125 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_COMPUTE_TASK_INFO, | ||
| 126 | + TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_COMPUTE_TASK_INFO), | ||
| 127 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_MC2_COMM_INFO)), | ||
| 128 | + std::vector<TaskInfoData>, std::vector<MC2CommInfoData>); | ||
| 129 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_MEMCPY_INFO, | ||
| 130 | + TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_MEMCPY_INFO)), | ||
| 131 | + std::vector<MemcpyInfoData>); | ||
| 132 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_TASK_PMU_INFO, | ||
| 133 | + TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_UNIFIED_PMU)), | ||
| 134 | + std::vector<UnifiedTaskPmu>); | ||
| 135 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_SAMPLE_PMU_TIMELINE, | ||
| 136 | + TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_UNIFIED_PMU)), | ||
| 137 | + std::vector<UnifiedSampleTimelinePmu>); | ||
| 138 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_SAMPLE_PMU_SUMMARY, | ||
| 139 | + TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_UNIFIED_PMU)), | ||
| 140 | + std::vector<UnifiedSampleSummaryPmu>); | ||
| 141 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_CPU_USAGE, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_CPU_USAGE)), | ||
| 142 | + std::vector<CpuUsageData>); | ||
| 143 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_MEM_USAGE, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_MEM_USAGE)), | ||
| 144 | + std::vector<MemUsageData>); | ||
| 145 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_DISK_USAGE, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_DISK_USAGE)), | ||
| 146 | + std::vector<DiskUsageData>); | ||
| 147 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_NETWORK_USAGE, | ||
| 148 | + TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_NETWORK_USAGE)), | ||
| 149 | + std::vector<NetWorkUsageData>); | ||
| 150 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_OSRT_API, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_OSRT_API)), | ||
| 151 | + std::vector<OSRuntimeApiData>); | ||
| 152 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_OVERLAP_ANALYSIS, | ||
| 153 | + TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_OVERLAP_ANALYSIS)), | ||
| 154 | + std::vector<OverlapAnalysisData>); | ||
| 155 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_QOS, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_QOS)), | ||
| 156 | + std::vector<QosData>); | ||
| 157 | +REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_CCU_MISSION, | ||
| 158 | + TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_CCU_MISSION)), | ||
| 159 | + std::vector<CCUMissionTimelineData>); | ||
| 160 | + | ||
| 161 | +REGISTER_TOPO_NODE_SEQUENCE(typeid(void), TOPO_NODE(FLOW_CONTROL, DB_STRING_IDS), true, | ||
| 162 | + DBAssembler::CreateStringIdsSaver(), TOPO_DEPS(), DBAssembler::ResolveSelectedDBSavers); | ||
| 163 | + | ||
| 164 | + | ||
| 165 | + | ||
| 166 | +} // namespace Application | ||
| 167 | +} // namespace Analysis | ||
| @@ -1,4 +1,4 @@ | |||
| 1 | -/* ------------------------------------------------------------------------- | 1 | +/* ------------------------------------------------------------------------- |
| 2 | * Copyright (c) 2025 Huawei Technologies Co., Ltd. | 2 | * Copyright (c) 2025 Huawei Technologies Co., Ltd. |
| 3 | * This file is part of the MindStudio project. | 3 | * This file is part of the MindStudio project. |
| 4 | * | 4 | * |
| @@ -6,28 +6,32 @@ | |||
| 6 | * You can use this software according to the terms and conditions of the Mulan PSL v2. | 6 | * You can use this software according to the terms and conditions of the Mulan PSL v2. |
| 7 | * You may obtain a copy of Mulan PSL v2 at: | 7 | * You may obtain a copy of Mulan PSL v2 at: |
| 8 | * | 8 | * |
| 9 | - * http://license.coscl.org.cn/MulanPSL2 | 9 | + * http://license.coscl.org.cn/MulanPSL2 |
| 10 | * | 10 | * |
| 11 | * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, | 11 | * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, |
| 12 | * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, | 12 | * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, |
| 13 | - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. | 13 | + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. |
| 14 | * See the Mulan PSL v2 for more details. | 14 | * See the Mulan PSL v2 for more details. |
| 15 | * -------------------------------------------------------------------------*/ | 15 | * -------------------------------------------------------------------------*/ |
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | -#include <atomic> | 19 | +#include <algorithm> |
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 20 | 26 | ||
| 21 | 27 | ||
| 22 | 28 | ||
| 23 | 29 | ||
| 24 | 30 | ||
| 25 | 31 | ||
| 26 | - | ||
| 27 | - | ||
| 28 | 32 | ||
| 29 | 33 | ||
| 30 | -#include "analysis/csrc/infrastructure/utils/thread_pool.h" | 34 | +#include "analysis/csrc/infrastructure/process/include/process_control.h" |
| 31 | 35 | ||
| 32 | namespace Analysis | 36 | namespace Analysis |
| 33 | { | 37 | { |
| @@ -47,64 +51,21 @@ std::string CreateOutputPath(const std::string& profPath) | |||
| 47 | } | 51 | } |
| 48 | return outputPath; | 52 | return outputPath; |
| 49 | } | 53 | } |
| 50 | -} // namespace | ||
| 51 | 54 | ||
| 52 | -bool ExportManager::ProcessData(DataInventory& dataInventory, const std::set<ExportMode>& exportModeSet) | 55 | +bool HasExportedMsprofDB(const std::string& profPath) |
Y 【review】 问题:函数名 HasExportedMsprofDB 的语义可能比实现更强,容易让调用方误解 从函数名看,它像是在判断“是否已经导出了 msprof 数据库”;但实际实现只是检查 profPath 下是否存在前缀为 DB_NAME_MSPROF_DB + "_" 且后缀为 .db 的文件。 这两者并不完全等价,例如文件可能是残留文件、空文件、半生成文件,甚至只是命名碰巧匹配。 建议: 如果当前需求只是判断“是否存在符合命名规则的 db 文件”,建议把函数名改得更贴近真实行为,比如 HasMsprofDbFile 或 ExistsExportedMsprofDbFile。 如果业务上真的要判断“已成功导出”,那应补充更严格的校验,例如文件存在性、大小、可打开性,甚至必要的 schema/表检查。 ![]() ![]() | |||
| 53 | { | 56 | { |
| 54 | - // hash数据作为其他流程的依赖数据,需要优先加载 | 57 | + const std::string dbSuffix = ".db"; |
| 55 | - HashInitProcessor hashProcessor(profPath_); | 58 | + const std::vector<std::string> dbFiles = File::GetFilesWithPrefix(profPath, DB_NAME_MSPROF_DB + "_"); |
| 56 | - hashProcessor.Run(dataInventory, PROCESSOR_NAME_HASH); | 59 | + return std::any_of(dbFiles.begin(), dbFiles.end(), |
| 57 | - const uint16_t tableProcessors = 10; // 最多有10个线程 | 60 | + [&dbSuffix](const std::string& dbPath) |
| 58 | - Analysis::Utils::ThreadPool pool(tableProcessors); | 61 | + { |
| 59 | - pool.Start(); | 62 | + return dbPath.size() >= dbSuffix.size() && |
Y 【review】 问题:dbSuffix 用 std::string 局部变量有一点不必要的运行期开销 ".db" 是固定字面量,每次调用都构造一个 std::string dbSuffix,虽然开销不大,但属于可以顺手优化掉的细节,尤其是在高频调用场景下没必要重复分配/构造。 建议: 可以改成 constexpr std::string_view dbSuffix = ".db";,或者至少改成静态常量。 这样语义更明确,也更轻量。 ![]() ![]() | |||
| 60 | - std::atomic<bool> retFlag(true); | 63 | + dbPath.compare(dbPath.size() - dbSuffix.size(), dbSuffix.size(), dbSuffix) == 0; |
Y 【review】 问题:后缀匹配逻辑正确但可读性一般,维护成本略高 现在通过 dbPath.compare(dbPath.size() - dbSuffix.size(), dbSuffix.size(), dbSuffix) == 0 来判断是否以 .db 结尾,逻辑没问题,但表达稍显绕,阅读时需要停一下理解“从尾部开始比较”。 建议: 如果项目使用的 C++ 标准支持,可以考虑改成更直观的 ends-with 风格实现;如果不支持,也可以封装一个通用的 EndsWith 工具函数。 这样能让这类“后缀判断”意图更直接,减少重复样板代码。 ![]() ![]() | |||
| 61 | - static const std::unordered_map<ExportMode, const std::set<std::string>& (*)()> processListFactory = { | 64 | + }); |
| 62 | - {ExportMode::DB, &DBAssembler::GetProcessList}, | ||
| 63 | - {ExportMode::TIMELINE, &TimelineManager::GetProcessList}, | ||
| 64 | - {ExportMode::SUMMARY, &SummaryManager::GetProcessList}}; | ||
| 65 | - | ||
| 66 | - std::set<std::string> dataProcessList; | ||
| 67 | - for (auto exportMode : exportModeSet) | ||
| 68 | - { | ||
| 69 | - auto it = processListFactory.find(exportMode); | ||
| 70 | - if (it == processListFactory.end()) | ||
| 71 | - { | ||
| 72 | - ERROR("Unsupported ExportMode: %.", static_cast<int>(exportMode)); | ||
| 73 | - return false; | ||
| 74 | - } | ||
| 75 | - auto tmpSet = it->second(); | ||
| 76 | - dataProcessList.insert(tmpSet.begin(), tmpSet.end()); | ||
| 77 | - } | ||
| 78 | - | ||
| 79 | - for (const auto& name : dataProcessList) | ||
| 80 | - { | ||
| 81 | - pool.AddTask( | ||
| 82 | - [this, &name, &retFlag, &dataInventory]() | ||
| 83 | - { | ||
| 84 | - auto processor = DataProcessorFactory::GetDataProcessByName(profPath_, name); | ||
| 85 | - if (processor == nullptr) | ||
| 86 | - { | ||
| 87 | - ERROR("% is not defined", name); | ||
| 88 | - retFlag = false; | ||
| 89 | - return; | ||
| 90 | - } | ||
| 91 | - retFlag = processor->Run(dataInventory, name) && retFlag; | ||
| 92 | - }); | ||
| 93 | - } | ||
| 94 | - pool.WaitAllTasks(); | ||
| 95 | - pool.Stop(); | ||
| 96 | - if (!retFlag) | ||
| 97 | - { | ||
| 98 | - ERROR("The % for data process failed to be executed.", profPath_); | ||
| 99 | - PRINT_ERROR( | ||
| 100 | - "The % for data process failed to be executed. " | ||
| 101 | - "Please check msprof_analysis_log in outputPath for more info.", | ||
| 102 | - profPath_); | ||
| 103 | - return false; | ||
| 104 | - } | ||
| 105 | - return true; | ||
| 106 | } | 65 | } |
| 107 | 66 | ||
| 67 | +} // namespace | ||
| 68 | + | ||
| 108 | bool ExportManager::CheckProfDirsValid() | 69 | bool ExportManager::CheckProfDirsValid() |
| 109 | { | 70 | { |
| 110 | if (profPath_.find("PROF") == std::string::npos) | 71 | if (profPath_.find("PROF") == std::string::npos) |
| @@ -149,64 +110,106 @@ bool ExportManager::Run(const std::set<ExportMode>& exportModeSet) | |||
| 149 | { | 110 | { |
| 150 | return false; | 111 | return false; |
| 151 | } | 112 | } |
| 152 | - DataInventory dataInventory; | ||
| 153 | - std::atomic<bool> runFlag(true); | ||
| 154 | - runFlag = ProcessData(dataInventory, exportModeSet); | ||
| 155 | - const std::map<ExportMode, std::function<bool(DataInventory&)>> operationMap = { | ||
| 156 | - {ExportMode::DB, | ||
| 157 | - [this](DataInventory& dataInventory) -> bool | ||
| 158 | - { | ||
| 159 | - DBAssembler dbAssembler(profPath_, profPath_); | ||
| 160 | - return dbAssembler.Run(dataInventory); | ||
| 161 | - }}, | ||
| 162 | - {ExportMode::TIMELINE, | ||
| 163 | - [this](DataInventory& dataInventory) -> bool | ||
| 164 | - { | ||
| 165 | - std::string outputPath = CreateOutputPath(profPath_); | ||
| 166 | - if (outputPath.empty()) | ||
| 167 | - { | ||
| 168 | - return false; | ||
| 169 | - } | ||
| 170 | - TimelineManager timelineManager(profPath_, outputPath); | ||
| 171 | - std::vector<JsonProcess> jsonProcesses = GetProcessEnum(); | ||
| 172 | - return timelineManager.Run(dataInventory, jsonProcesses); | ||
| 173 | - }}, | ||
| 174 | - {ExportMode::SUMMARY, | ||
| 175 | - [this](DataInventory& dataInventory) -> bool | ||
| 176 | - { | ||
| 177 | - std::string outputPath = CreateOutputPath(profPath_); | ||
| 178 | - if (outputPath.empty()) | ||
| 179 | - { | ||
| 180 | - return false; | ||
| 181 | - } | ||
| 182 | - SummaryManager summaryManager(profPath_, outputPath); | ||
| 183 | - return summaryManager.Run(dataInventory); | ||
| 184 | - }}, | ||
| 185 | - }; | ||
| 186 | 113 | ||
| 187 | - const uint16_t processorsLimit = 3; // 最多有3个线程 | 114 | + ExportSelection selection; |
| 188 | - Analysis::Utils::ThreadPool pool(processorsLimit); | 115 | + if (!GetExportSelection(exportModeSet, selection)) |
| 189 | - pool.Start(); | 116 | + { |
| 117 | + return false; | ||
| 118 | + } | ||
| 119 | + | ||
| 120 | + TopoBuildContext buildContext; | ||
| 121 | + buildContext.profPath = profPath_; | ||
| 122 | + buildContext.outputPath = profPath_; | ||
| 123 | + buildContext.timelineProcesses = selection.timelineProcesses; | ||
| 124 | + std::vector<TopoNodeId> roots; | ||
| 190 | for (const auto& exportMode : exportModeSet) | 125 | for (const auto& exportMode : exportModeSet) |
| 191 | { | 126 | { |
| 192 | - auto iter = operationMap.find(exportMode); | 127 | + switch (exportMode) |
| 193 | - if (iter != operationMap.end()) | ||
| 194 | { | 128 | { |
| 195 | - pool.AddTask([iter, &runFlag, &dataInventory]() { runFlag = iter->second(dataInventory) && runFlag; }); | 129 | + case ExportMode::DB: |
W [review] 这里逻辑依然保留了原本的exportManager的流程。本质还是将timeline和summary导出分作两个大流程处理。当前pr先保持原有能力的前后一致性。后续需要考虑将导出流程归一,一次导出所有交付件,减少导出重复无意义开销,将导出能力彻底归一。 ![]() ![]() | |||
| 130 | + { | ||
| 131 | + if (HasExportedMsprofDB(profPath_)) | ||
| 132 | + { | ||
| 133 | + INFO("The exported msprof db already exists, skip DB export."); | ||
| 134 | + break; | ||
[review] 问题: 这里 检测到已有 DB 后只执行 break,没有添加任何拓扑根节点。随后 topo_graph.cpp (line 131) 会因为 roots.empty() 返回失败。 影响: 用户再次执行仅 DB 导出时,日志提示“skip DB export”,但最终命令仍然失败,与原来已有完整 DB 时返回成功的行为不一致。 修改建议: 记录“DB 已存在且成功跳过”的状态。当所有请求项都已完成、没有待执行根节点时直接返回成功。补充“仅请求 DB 且 DB 已存在”的单测。 ![]() ![]() | |||
| 135 | + } | ||
| 136 | + buildContext.dbSession = | ||
| 137 | + std::shared_ptr<DBAssembler>(new (std::nothrow) DBAssembler(profPath_, profPath_)); | ||
| 138 | + if (buildContext.dbSession == nullptr || !DBAssembler::GetTopologyRoots(roots)) | ||
| 139 | + { | ||
| 140 | + ERROR("Build DB topology roots failed."); | ||
| 141 | + return false; | ||
| 142 | + } | ||
| 143 | + break; | ||
| 144 | + } | ||
| 145 | + case ExportMode::TIMELINE: | ||
| 146 | + { | ||
| 147 | + const std::string outputPath = CreateOutputPath(profPath_); | ||
| 148 | + if (outputPath.empty()) | ||
| 149 | + { | ||
| 150 | + return false; | ||
| 151 | + } | ||
| 152 | + buildContext.outputPath = outputPath; | ||
| 153 | + buildContext.timelineSession = | ||
| 154 | + std::shared_ptr<TimelineManager>(new (std::nothrow) TimelineManager(profPath_, outputPath)); | ||
| 155 | + if (buildContext.timelineSession == nullptr || | ||
| 156 | + !TimelineManager::GetTopologyRoots(selection.timelineProcesses, roots)) | ||
| 157 | + { | ||
| 158 | + return false; | ||
| 159 | + } | ||
| 160 | + break; | ||
| 161 | + } | ||
| 162 | + case ExportMode::SUMMARY: | ||
| 163 | + if (CreateOutputPath(profPath_).empty() || | ||
严重程度: 建议 问题: 原因: 当前 怎么改: 与 TIMELINE 分支保持一致,捕获并赋值输出路径:
即使当前汇总装配器不使用 ![]() ![]() | |||
| 164 | + !SummaryManager::GetTopologyRoots(selection.summaryDeliverables, roots)) | ||
| 165 | + { | ||
| 166 | + return false; | ||
| 167 | + } | ||
| 168 | + break; | ||
| 169 | + default: | ||
| 170 | + ERROR("Unsupported ExportMode: %.", static_cast<int>(exportMode)); | ||
| 171 | + return false; | ||
| 196 | } | 172 | } |
| 197 | } | 173 | } |
| 198 | - pool.WaitAllTasks(); | 174 | + |
| 199 | - pool.Stop(); | 175 | + Infra::ProcessCollection processes; |
| 200 | - return runFlag; | 176 | + TopoGraphBuilder graphBuilder; |
| 177 | + if (!graphBuilder.Build(buildContext, roots, processes)) | ||
| 178 | + { | ||
| 179 | + ERROR("Build export topology failed."); | ||
| 180 | + return false; | ||
| 181 | + } | ||
| 182 | + | ||
| 183 | + DataInventory dataInventory; | ||
| 184 | + Infra::Context context; | ||
| 185 | + Infra::ProcessControl processControl(processes); | ||
| 186 | + if (!processControl.ExecuteProcess(dataInventory, context)) | ||
| 187 | + { | ||
| 188 | + ERROR("The % export topology failed to be executed.", profPath_); | ||
| 189 | + PRINT_ERROR( | ||
| 190 | + "The % for export failed to be executed. " | ||
| 191 | + "Please check msprof_analysis_log in outputPath for more info.", | ||
| 192 | + profPath_); | ||
| 193 | + return false; | ||
| 194 | + } | ||
| 195 | + return true; | ||
| 201 | } | 196 | } |
| 202 | 197 | ||
| 203 | -std::vector<JsonProcess> ExportManager::GetProcessEnum() | 198 | +bool ExportManager::GetExportSelection(const std::set<ExportMode>& exportModeSet, ExportSelection& selection) |
| 204 | { | 199 | { |
| 200 | + selection.timelineProcesses.clear(); | ||
| 201 | + selection.summaryDeliverables.clear(); | ||
| 202 | + const bool exportTimeline = exportModeSet.find(ExportMode::TIMELINE) != exportModeSet.end(); | ||
| 203 | + const bool exportSummary = exportModeSet.find(ExportMode::SUMMARY) != exportModeSet.end(); | ||
| 204 | + if (exportTimeline) | ||
| 205 | + { | ||
| 206 | + selection.timelineProcesses = allProcesses; | ||
| 207 | + } | ||
| 205 | if (jsonPath_.empty()) | 208 | if (jsonPath_.empty()) |
| 206 | { | 209 | { |
| 207 | INFO("The report parameter is not used."); | 210 | INFO("The report parameter is not used."); |
| 208 | PRINT_INFO("The report parameter is not used."); | 211 | PRINT_INFO("The report parameter is not used."); |
| 209 | - return allProcesses; | 212 | + return true; |
| 210 | } | 213 | } |
| 211 | FileReader fd(jsonPath_); | 214 | FileReader fd(jsonPath_); |
| 212 | nlohmann::json config; | 215 | nlohmann::json config; |
| @@ -214,41 +217,107 @@ std::vector<JsonProcess> ExportManager::GetProcessEnum() | |||
| 214 | { | 217 | { |
| 215 | ERROR("Load report config failed: '%'.", jsonPath_); | 218 | ERROR("Load report config failed: '%'.", jsonPath_); |
| 216 | PRINT_ERROR("Load report config failed: '%'.", jsonPath_); | 219 | PRINT_ERROR("Load report config failed: '%'.", jsonPath_); |
| 217 | - return allProcesses; | 220 | + return true; |
| 218 | } | 221 | } |
| 219 | - auto jsonProcessConfig = config["json_process"]; | 222 | + |
| 220 | - if (jsonProcessConfig.is_null() || !jsonProcessConfig.is_object() || jsonProcessConfig.empty()) | 223 | + if (exportTimeline) |
| 221 | { | 224 | { |
| 222 | - INFO("The json_process is not exist."); | 225 | + const auto jsonProcessConfig = config["json_process"]; |
| 223 | - PRINT_INFO("The json_process is not exist."); | 226 | + if (jsonProcessConfig.is_null() || !jsonProcessConfig.is_object() || jsonProcessConfig.empty()) |
| 224 | - return allProcesses; | ||
| 225 | - } | ||
| 226 | - std::vector<JsonProcess> jsonProcesses; | ||
| 227 | - for (nlohmann::json::iterator it = jsonProcessConfig.begin(); it != jsonProcessConfig.end(); ++it) | ||
| 228 | - { | ||
| 229 | - if (strToJsonProcess.find(it.key()) == strToJsonProcess.end()) | ||
| 230 | { | 227 | { |
| 231 | - ERROR("Json process contains invalid key."); | 228 | + INFO("The json_process is not exist."); |
| 232 | - PRINT_ERROR("Json process contains invalid key."); | 229 | + PRINT_INFO("The json_process is not exist."); |
| 233 | - return allProcesses; | ||
| 234 | } | 230 | } |
| 235 | - if (!it.value().is_boolean()) | 231 | + else |
| 236 | { | 232 | { |
| 237 | - ERROR("Json contains invalid value, only the bool type is supported."); | 233 | + std::vector<JsonProcess> jsonProcesses; |
| 238 | - PRINT_ERROR("Json contains invalid value, only the bool type is supported."); | 234 | + bool valid = true; |
| 239 | - return allProcesses; | 235 | + for (nlohmann::json::const_iterator it = jsonProcessConfig.begin(); it != jsonProcessConfig.end(); ++it) |
| 240 | - } | ||
| 241 | - if (it.value()) | ||
| 242 | - { | ||
| 243 | - auto processEnum = strToJsonProcess.at(it.key()); | ||
| 244 | - jsonProcesses.push_back(processEnum); | ||
| 245 | - if (it.key() == "freq") | ||
| 246 | { | 236 | { |
| 247 | - jsonProcesses.push_back(JsonProcess::LOW_POWER); | 237 | + if (strToJsonProcess.find(it.key()) == strToJsonProcess.end()) |
| 238 | + { | ||
| 239 | + ERROR("Json process contains invalid key."); | ||
| 240 | + PRINT_ERROR("Json process contains invalid key."); | ||
| 241 | + valid = false; | ||
| 242 | + break; | ||
| 243 | + } | ||
| 244 | + if (!it.value().is_boolean()) | ||
| 245 | + { | ||
| 246 | + ERROR("Json contains invalid value, only the bool type is supported."); | ||
| 247 | + PRINT_ERROR("Json contains invalid value, only the bool type is supported."); | ||
| 248 | + valid = false; | ||
| 249 | + break; | ||
| 250 | + } | ||
| 251 | + if (it.value()) | ||
| 252 | + { | ||
| 253 | + const auto processEnum = strToJsonProcess.at(it.key()); | ||
| 254 | + jsonProcesses.emplace_back(processEnum); | ||
| 255 | + if (it.key() == "freq") | ||
| 256 | + { | ||
| 257 | + jsonProcesses.emplace_back(JsonProcess::LOW_POWER); | ||
| 258 | + } | ||
| 259 | + } | ||
| 260 | + } | ||
| 261 | + if (valid) | ||
| 262 | + { | ||
| 263 | + if (jsonProcesses.empty()) | ||
| 264 | + { | ||
| 265 | + ERROR("Json process has no enabled timeline deliverable."); | ||
| 266 | + return false; | ||
| 267 | + } | ||
| 268 | + selection.timelineProcesses = std::move(jsonProcesses); | ||
| 248 | } | 269 | } |
| 249 | } | 270 | } |
| 250 | } | 271 | } |
| 251 | - return std::move(jsonProcesses); | 272 | + |
| 273 | + if (exportSummary) | ||
| 274 | + { | ||
| 275 | + const auto summaryProcessConfig = config["summary_process"]; | ||
| 276 | + if (summaryProcessConfig.is_null()) | ||
| 277 | + { | ||
| 278 | + return true; | ||
| 279 | + } | ||
| 280 | + if (!summaryProcessConfig.is_object()) | ||
| 281 | + { | ||
| 282 | + ERROR("Summary process must be a JSON object."); | ||
| 283 | + PRINT_ERROR("Summary process must be a JSON object."); | ||
| 284 | + return false; | ||
| 285 | + } | ||
| 286 | + if (summaryProcessConfig.empty()) | ||
| 287 | + { | ||
| 288 | + INFO("The summary_process is empty."); | ||
| 289 | + PRINT_INFO("The summary_process is empty."); | ||
| 290 | + return true; | ||
| 291 | + } | ||
| 292 | + | ||
| 293 | + std::vector<std::string> summaryDeliverables; | ||
| 294 | + for (nlohmann::json::const_iterator it = summaryProcessConfig.begin(); it != summaryProcessConfig.end(); ++it) | ||
| 295 | + { | ||
| 296 | + if (!SummaryManager::IsDeliverableSupported(it.key())) | ||
| 297 | + { | ||
| 298 | + ERROR("Summary process contains invalid key."); | ||
| 299 | + PRINT_ERROR("Summary process contains invalid key."); | ||
| 300 | + return false; | ||
| 301 | + } | ||
| 302 | + if (!it.value().is_boolean()) | ||
| 303 | + { | ||
| 304 | + ERROR("Summary process value must be bool."); | ||
| 305 | + PRINT_ERROR("Summary process value must be bool."); | ||
| 306 | + return false; | ||
| 307 | + } | ||
| 308 | + if (it.value()) | ||
| 309 | + { | ||
| 310 | + summaryDeliverables.emplace_back(it.key()); | ||
| 311 | + } | ||
| 312 | + } | ||
| 313 | + if (summaryDeliverables.empty()) | ||
| 314 | + { | ||
| 315 | + ERROR("Summary process has no enabled deliverable."); | ||
| 316 | + return false; | ||
| 317 | + } | ||
| 318 | + selection.summaryDeliverables = std::move(summaryDeliverables); | ||
| 319 | + } | ||
| 320 | + return true; | ||
| 252 | } | 321 | } |
| 253 | } // namespace Application | 322 | } // namespace Application |
| 254 | } // namespace Analysis | 323 | } // namespace Analysis |
| @@ -17,32 +17,45 @@ | |||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | + | ||
| 20 | 21 | ||
| 21 | -#include "analysis/csrc/infrastructure/data_inventory/include/data_inventory.h" | 22 | +#include <vector> |
| 22 | - | ||
| 23 | - | ||
| 24 | 23 | ||
| 25 | -namespace Analysis { | 24 | +#include "analysis/csrc/application/include/export_mode_enum.h" |
| 26 | -namespace Application { | 25 | +#include "analysis/csrc/application/timeline/json_process_enum.h" |
| 26 | + | ||
| 27 | + | ||
| 28 | +namespace Analysis | ||
| 29 | +{ | ||
| 30 | +namespace Application | ||
| 31 | +{ | ||
| 27 | using namespace Analysis::Infra; | 32 | using namespace Analysis::Infra; |
| 28 | -class ExportManager { | 33 | + |
| 29 | -public: | 34 | +struct ExportSelection |
| 30 | - explicit ExportManager(const std::string &profPath) : profPath_(profPath) {} | 35 | +{ |
| 31 | - ExportManager(const std::string& profPath, const std::string& jsonPath) : profPath_(profPath), | 36 | + std::vector<JsonProcess> timelineProcesses; |
| 32 | - jsonPath_(jsonPath) | 37 | + std::vector<std::string> summaryDeliverables; |
| 33 | - {} | 38 | +}; |
| 39 | + | ||
| 40 | +class ExportManager | ||
| 41 | +{ | ||
| 42 | + public: | ||
| 43 | + explicit ExportManager(const std::string& profPath) : profPath_(profPath) {} | ||
| 44 | + ExportManager(const std::string& profPath, const std::string& jsonPath) : profPath_(profPath), jsonPath_(jsonPath) | ||
| 45 | + { | ||
| 46 | + } | ||
| 34 | bool Run(const std::set<ExportMode>& exportModeSet); | 47 | bool Run(const std::set<ExportMode>& exportModeSet); |
| 35 | -private: | 48 | + bool GetExportSelection(const std::set<ExportMode>& exportModeSet, ExportSelection& selection); |
| 49 | + | ||
| 50 | + private: | ||
| 36 | bool Init(); | 51 | bool Init(); |
| 37 | bool CheckProfDirsValid(); | 52 | bool CheckProfDirsValid(); |
| 38 | - bool ProcessData(DataInventory &dataInventory, const std::set<ExportMode>& exportModeSet); | ||
| 39 | - std::vector<JsonProcess> GetProcessEnum(); | ||
| 40 | 53 | ||
| 41 | -private: | 54 | + private: |
| 42 | std::string profPath_; | 55 | std::string profPath_; |
| 43 | std::string jsonPath_; | 56 | std::string jsonPath_; |
| 44 | }; | 57 | }; |
| 45 | -} | 58 | +} // namespace Application |
| 46 | -} | 59 | +} // namespace Analysis |
| 47 | 60 | ||
| 48 | -#endif // ANALYSIS_APPLICATION_EXPORT_MANAGER_H | 61 | +#endif // ANALYSIS_APPLICATION_EXPORT_MANAGER_H |
| @@ -16,10 +16,13 @@ | |||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | -#include <atomic> | 19 | +#include <set> |
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 20 | 23 | ||
| 21 | 24 | ||
| 22 | -#include "analysis/csrc/infrastructure/utils/thread_pool.h" | 25 | +#include "analysis/csrc/infrastructure/process/include/topo_callback_process.h" |
| 23 | 26 | ||
| 24 | namespace Analysis | 27 | namespace Analysis |
| 25 | { | 28 | { |
| @@ -27,81 +30,101 @@ namespace Application | |||
| 27 | { | 30 | { |
| 28 | namespace | 31 | namespace |
| 29 | { | 32 | { |
| 30 | -using namespace Utils; | ||
| 31 | -const uint8_t PROCESSOR_POOL_NUM = 5; | ||
| 32 | const std::vector<std::string> DATA_ASSEMBLE_LIST{PROCESSOR_OP_SUMMARY, PROCESSOR_NAME_COMM_STATISTIC, | 33 | const std::vector<std::string> DATA_ASSEMBLE_LIST{PROCESSOR_OP_SUMMARY, PROCESSOR_NAME_COMM_STATISTIC, |
| 33 | PROCESSOR_NAME_OP_STATISTIC, PROCESSOR_NAME_NPU_MEM, | 34 | PROCESSOR_NAME_OP_STATISTIC, PROCESSOR_NAME_NPU_MEM, |
| 34 | PROCESSOR_NAME_NPU_MODULE_MEM, PROCESSOR_NAME_API, | 35 | PROCESSOR_NAME_NPU_MODULE_MEM, PROCESSOR_NAME_API, |
| 35 | PROCESSOR_NAME_FUSION_OP, PROCESSOR_TASK_TIME_SUMMARY, | 36 | PROCESSOR_NAME_FUSION_OP, PROCESSOR_TASK_TIME_SUMMARY, |
| 36 | PROCESSOR_NAME_STEP_TRACE, PROCESSOR_NAME_PAGE_FAULT}; | 37 | PROCESSOR_NAME_STEP_TRACE, PROCESSOR_NAME_PAGE_FAULT}; |
| 37 | 38 | ||
| 38 | -const std::set<std::string> SUMMARY_DATA_PROCESS_LIST{PROCESSOR_NAME_COMMUNICATION, | 39 | +const std::unordered_map<std::string, std::string> SUMMARY_DELIVERABLES{ |
| 39 | - PROCESSOR_NAME_COMPUTE_TASK_INFO, | 40 | + {"op_summary", PROCESSOR_OP_SUMMARY}, |
| 40 | - PROCESSOR_NAME_TASK, | 41 | + {"comm_statistic", PROCESSOR_NAME_COMM_STATISTIC}, |
| 41 | - PROCESSOR_PMU, | 42 | + {"op_statistic", PROCESSOR_NAME_OP_STATISTIC}, |
| 42 | - PROCESSOR_NAME_COMM_STATISTIC, | 43 | + {"npu_memory", PROCESSOR_NAME_NPU_MEM}, |
| 43 | - PROCESSOR_NAME_OP_STATISTIC, | 44 | + {"npu_module_memory", PROCESSOR_NAME_NPU_MODULE_MEM}, |
| 44 | - PROCESSOR_NAME_NPU_MEM, | 45 | + {"api_statistic", PROCESSOR_NAME_API}, |
| 45 | - PROCESSOR_NAME_NPU_MODULE_MEM, | 46 | + {"fusion_op", PROCESSOR_NAME_FUSION_OP}, |
| 46 | - PROCESSOR_NAME_API, | 47 | + {"task_time", PROCESSOR_TASK_TIME_SUMMARY}, |
| 47 | - PROCESSOR_NAME_FUSION_OP, | 48 | + {"step_trace", PROCESSOR_NAME_STEP_TRACE}, |
| 48 | - PROCESSOR_NAME_MODEL_NAME, | 49 | + {"page_fault", PROCESSOR_NAME_PAGE_FAULT}, |
| 49 | - PROCESSOR_NAME_STEP_TRACE, | 50 | +}; |
| 50 | - PROCESSOR_HOST_TASK, | 51 | + |
| 51 | - PROCESSOR_NAME_PAGE_FAULT}; | ||
| 52 | } // namespace | 52 | } // namespace |
| 53 | 53 | ||
| 54 | -bool SummaryManager::Run(DataInventory& dataInventory) | 54 | +bool SummaryManager::IsDeliverableSupported(const std::string& deliverableName) |
| 55 | { | 55 | { |
| 56 | - INFO("Start exporting summary!"); | 56 | + return SUMMARY_DELIVERABLES.find(deliverableName) != SUMMARY_DELIVERABLES.end(); |
| 57 | - PRINT_INFO("Start exporting the summary!"); | 57 | +} |
| 58 | - bool runFlag = ProcessSummary(dataInventory); | 58 | + |
| 59 | - if (!runFlag) | 59 | +bool SummaryManager::GetTopologyRoots(const std::vector<std::string>& deliverableNames, std::vector<TopoNodeId>& roots) |
| 60 | +{ | ||
| 61 | + const size_t rootsSize = roots.size(); | ||
| 62 | + std::vector<std::string> assemblerNames; | ||
| 63 | + if (!GetAssemblerList(deliverableNames, assemblerNames)) | ||
| 60 | { | 64 | { |
| 61 | - ERROR("The unified summary process failed to be executed."); | ||
| 62 | - PRINT_ERROR( | ||
| 63 | - "The unified summary process failed to be executed. " | ||
| 64 | - "Please check msprof_analysis_log in outputPath for more info."); | ||
| 65 | return false; | 65 | return false; |
| 66 | } | 66 | } |
| 67 | - PRINT_INFO("End exporting summary output_file. The file is stored in the PROF file."); | 67 | + for (const auto& name : assemblerNames) |
| 68 | + { | ||
| 69 | + const TopoNodeId id{TopoNodeStage::SUMMARY_GENERATION, name}; | ||
| 70 | + if (TopoNodeRegistry::Find(id) == nullptr) | ||
| 71 | + { | ||
| 72 | + ERROR("Summary execution list node % has no static topology registration.", name); | ||
| 73 | + roots.resize(rootsSize); | ||
| 74 | + return false; | ||
| 75 | + } | ||
| 76 | + roots.push_back(id); | ||
| 77 | + } | ||
| 68 | return true; | 78 | return true; |
| 69 | } | 79 | } |
| 70 | 80 | ||
| 71 | -bool SummaryManager::ProcessSummary(Analysis::Infra::DataInventory& dataInventory) | 81 | +bool SummaryManager::GetAssemblerList(const std::vector<std::string>& deliverableNames, |
| 82 | + std::vector<std::string>& assemblerNames) | ||
| 72 | { | 83 | { |
| 73 | - Analysis::Utils::ThreadPool pool(PROCESSOR_POOL_NUM); | 84 | + assemblerNames.clear(); |
| 74 | - pool.Start(); | 85 | + if (deliverableNames.empty()) |
| 75 | - std::atomic<bool> retFlag(true); | ||
| 76 | - for (const auto& name : DATA_ASSEMBLE_LIST) | ||
| 77 | { | 86 | { |
| 78 | - pool.AddTask( | 87 | + assemblerNames = DATA_ASSEMBLE_LIST; |
| 79 | - [this, &name, &retFlag, &dataInventory]() | 88 | + return true; |
| 80 | - { | 89 | + } |
| 81 | - auto assembler = SummaryFactory::GetAssemblerByName(name, profPath_); | 90 | + |
| 82 | - if (assembler == nullptr) | 91 | + std::set<std::string> selectedAssemblers; |
| 92 | + for (const auto& deliverableName : deliverableNames) | ||
| 93 | + { | ||
| 94 | + const auto deliverableIter = SUMMARY_DELIVERABLES.find(deliverableName); | ||
| 95 | + if (deliverableIter == SUMMARY_DELIVERABLES.end()) | ||
| 96 | + { | ||
| 97 | + ERROR("Summary deliverable % is not supported.", deliverableName); | ||
| 98 | + return false; | ||
| 99 | + } | ||
| 100 | + if (selectedAssemblers.insert(deliverableIter->second).second) | ||
| 101 | + { | ||
| 102 | + assemblerNames.emplace_back(deliverableIter->second); | ||
| 103 | + } | ||
| 104 | + } | ||
| 105 | + return true; | ||
| 106 | +} | ||
| 107 | + | ||
| 108 | +TopoNodeCreatorFactory SummaryManager::CreateSummaryAssembler(const std::string& name) | ||
| 109 | +{ | ||
| 110 | + return [name](const TopoBuildContext& context) | ||
| 111 | + { | ||
| 112 | + const std::string profPath = context.profPath; | ||
| 113 | + return [name, profPath]() -> std::unique_ptr<Infra::Process> | ||
| 114 | + { | ||
| 115 | + return std::unique_ptr<Infra::Process>(new (std::nothrow) TopoCallbackProcess( | ||
| 116 | + [name, profPath](DataInventory& dataInventory) -> bool | ||
| 83 | { | 117 | { |
| 84 | - ERROR("% is not defined", name); | 118 | + const auto assembler = SummaryFactory::GetAssemblerByName(name, profPath); |
| 85 | - retFlag = false; | 119 | + if (assembler == nullptr) |
| 86 | - return; | 120 | + { |
| 87 | - } | 121 | + ERROR("% is not defined", name); |
| 88 | - retFlag = assembler->Run(dataInventory) && retFlag; | 122 | + return false; |
| 89 | - }); | 123 | + } |
| 90 | - } | 124 | + return assembler->Run(dataInventory); |
| 91 | - pool.WaitAllTasks(); | 125 | + })); |
| 92 | - pool.Stop(); | 126 | + }; |
| 93 | - if (!retFlag) | 127 | + }; |
| 94 | - { | ||
| 95 | - ERROR("The % for summary assemble failed to be executed.", profPath_); | ||
| 96 | - PRINT_ERROR( | ||
| 97 | - "The % for summary assemble failed to be executed. " | ||
| 98 | - "Please check msprof_analysis_log in outputPath for more info.", | ||
| 99 | - profPath_); | ||
| 100 | - return false; | ||
| 101 | - } | ||
| 102 | - return true; | ||
| 103 | } | 128 | } |
| 104 | - | ||
| 105 | -const std::set<std::string>& SummaryManager::GetProcessList() { return SUMMARY_DATA_PROCESS_LIST; } | ||
| 106 | } // namespace Application | 129 | } // namespace Application |
| 107 | } // namespace Analysis | 130 | } // namespace Analysis |
| @@ -17,26 +17,35 @@ | |||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | + | ||
| 20 | 21 | ||
| 21 | 22 | ||
| 22 | -#include "analysis/csrc/infrastructure/data_inventory/include/data_inventory.h" | 23 | +#include <vector> |
| 23 | 24 | ||
| 24 | -namespace Analysis { | 25 | +#include "analysis/csrc/infrastructure/data_inventory/include/data_inventory.h" |
| 25 | -namespace Application { | 26 | +#include "analysis/csrc/infrastructure/process/include/topo_graph.h" |
| 27 | + | ||
| 28 | +namespace Analysis | ||
| 29 | +{ | ||
| 30 | +namespace Application | ||
| 31 | +{ | ||
| 26 | using namespace Analysis::Infra; | 32 | using namespace Analysis::Infra; |
| 27 | 33 | ||
| 28 | -class SummaryManager { | 34 | +class SummaryManager |
| 29 | -public: | 35 | +{ |
| 36 | + public: | ||
| 30 | explicit SummaryManager(const std::string& profPath, const std::string& outputPath) | 37 | explicit SummaryManager(const std::string& profPath, const std::string& outputPath) |
| 31 | : profPath_(profPath), outputPath_(outputPath) {}; | 38 | : profPath_(profPath), outputPath_(outputPath) {}; |
| 32 | - bool Run(DataInventory& dataInventory); | 39 | + static bool IsDeliverableSupported(const std::string& deliverableName); |
| 33 | - const static std::set<std::string>& GetProcessList(); | 40 | + static TopoNodeCreatorFactory CreateSummaryAssembler(const std::string& name); |
| 34 | -private: | 41 | + static bool GetAssemblerList(const std::vector<std::string>& deliverableNames, |
| 35 | - bool ProcessSummary(DataInventory& dataInventory); | 42 | + std::vector<std::string>& assemblerNames); |
| 36 | -private: | 43 | + static bool GetTopologyRoots(const std::vector<std::string>& deliverableNames, std::vector<TopoNodeId>& roots); |
| 44 | + | ||
| 45 | + private: | ||
| 37 | std::string profPath_; | 46 | std::string profPath_; |
| 38 | std::string outputPath_; | 47 | std::string outputPath_; |
| 39 | }; | 48 | }; |
| 40 | -} | 49 | +} // namespace Application |
| 41 | -} | 50 | +} // namespace Analysis |
| 42 | -#endif // ANALYSIS_APPLICATION_SUMMARY_MANAGER_H | 51 | +#endif // ANALYSIS_APPLICATION_SUMMARY_MANAGER_H |
| @@ -0,0 +1,94 @@ | |||
| 1 | +/* ------------------------------------------------------------------------- | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This file is part of the MindStudio project. | ||
| 4 | + * | ||
| 5 | + * MindStudio is licensed under Mulan PSL v2. | ||
| 6 | + * You can use this software according to the terms and conditions of the Mulan PSL v2. | ||
| 7 | + * You may obtain a copy of Mulan PSL v2 at: | ||
| 8 | + * | ||
| 9 | + * http://license.coscl.org.cn/MulanPSL2 | ||
| 10 | + * | ||
| 11 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, | ||
| 12 | + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, | ||
| 13 | + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. | ||
| 14 | + * See the Mulan PSL v2 for more details. | ||
| 15 | + * -------------------------------------------------------------------------*/ | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + | ||
| 32 | + | ||
| 33 | + | ||
| 34 | + | ||
| 35 | + | ||
| 36 | +namespace Analysis | ||
| 37 | +{ | ||
| 38 | +namespace Application | ||
| 39 | +{ | ||
| 40 | +namespace | ||
| 41 | +{ | ||
| 42 | +using namespace Analysis::Domain; | ||
| 43 | +using StringMap = std::unordered_map<std::string, std::string>; | ||
| 44 | + | ||
| 45 | +} // namespace | ||
| 46 | + | ||
| 47 | +REGISTER_TOPO_NODE_SEQUENCE(typeid(void), TOPO_NODE(SUMMARY_GENERATION, PROCESSOR_OP_SUMMARY), true, | ||
| 48 | + SummaryManager::CreateSummaryAssembler(PROCESSOR_OP_SUMMARY), | ||
| 49 | + TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_COMPUTE_TASK_INFO), | ||
| 50 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_TASK), | ||
| 51 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_COMMUNICATION), | ||
| 52 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_PMU)), | ||
| 53 | + nullptr); | ||
| 54 | +REGISTER_TOPO_NODE_DEPENDENT_DATA(TOPO_NODE(SUMMARY_GENERATION, PROCESSOR_OP_SUMMARY), std::vector<TaskInfoData>, | ||
| 55 | + std::vector<AscendTaskData>, std::vector<CommunicationOpData>, MetricSummary); | ||
| 56 | + | ||
| 57 | + | ||
| 58 | + REGISTER_TOPO_NODE_SEQUENCE(typeid(void), TOPO_NODE(SUMMARY_GENERATION, Name), true, \ | ||
| 59 | + SummaryManager::CreateSummaryAssembler(Name), \ | ||
| 60 | + TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, Dependency)), nullptr); \ | ||
| 61 | + REGISTER_TOPO_NODE_DEPENDENT_DATA(TOPO_NODE(SUMMARY_GENERATION, Name), DataType) | ||
| 62 | + | ||
| 63 | +REGISTER_SIMPLE_SUMMARY_NODE(PROCESSOR_NAME_COMM_STATISTIC, std::vector<HcclStatisticData>, | ||
| 64 | + PROCESSOR_NAME_COMM_STATISTIC); | ||
| 65 | +REGISTER_SIMPLE_SUMMARY_NODE(PROCESSOR_NAME_OP_STATISTIC, std::vector<OpStatisticData>, PROCESSOR_NAME_OP_STATISTIC); | ||
| 66 | +REGISTER_SIMPLE_SUMMARY_NODE(PROCESSOR_NAME_NPU_MEM, std::vector<NpuMemData>, PROCESSOR_NAME_NPU_MEM); | ||
| 67 | +REGISTER_SIMPLE_SUMMARY_NODE(PROCESSOR_NAME_NPU_MODULE_MEM, std::vector<NpuModuleMemData>, | ||
| 68 | + PROCESSOR_NAME_NPU_MODULE_MEM); | ||
| 69 | +REGISTER_SIMPLE_SUMMARY_NODE(PROCESSOR_NAME_API, std::vector<ApiData>, PROCESSOR_NAME_API); | ||
| 70 | +REGISTER_SIMPLE_SUMMARY_NODE(PROCESSOR_NAME_STEP_TRACE, std::vector<TrainTraceData>, PROCESSOR_NAME_STEP_TRACE); | ||
[review]
问题:
这里只登记了 std::vector ![]() ![]() | |||
| 71 | +REGISTER_SIMPLE_SUMMARY_NODE(PROCESSOR_NAME_PAGE_FAULT, std::vector<PageFaultData>, PROCESSOR_NAME_PAGE_FAULT); | ||
| 72 | + | ||
| 73 | +REGISTER_TOPO_NODE_SEQUENCE(typeid(void), TOPO_NODE(SUMMARY_GENERATION, PROCESSOR_NAME_FUSION_OP), true, | ||
| 74 | + SummaryManager::CreateSummaryAssembler(PROCESSOR_NAME_FUSION_OP), | ||
| 75 | + TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_FUSION_OP), | ||
| 76 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_MODEL_NAME), | ||
| 77 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_HASH)), | ||
| 78 | + nullptr); | ||
| 79 | +REGISTER_TOPO_NODE_DEPENDENT_DATA(TOPO_NODE(SUMMARY_GENERATION, PROCESSOR_NAME_FUSION_OP), std::vector<FusionOpInfo>, | ||
| 80 | + std::vector<ModelName>, StringMap); | ||
| 81 | + | ||
| 82 | +REGISTER_TOPO_NODE_SEQUENCE(typeid(void), TOPO_NODE(SUMMARY_GENERATION, PROCESSOR_TASK_TIME_SUMMARY), true, | ||
| 83 | + SummaryManager::CreateSummaryAssembler(PROCESSOR_TASK_TIME_SUMMARY), | ||
| 84 | + TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_COMPUTE_TASK_INFO), | ||
| 85 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_HOST_TASK), | ||
| 86 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_TASK)), | ||
| 87 | + nullptr); | ||
| 88 | +REGISTER_TOPO_NODE_DEPENDENT_DATA(TOPO_NODE(SUMMARY_GENERATION, PROCESSOR_TASK_TIME_SUMMARY), std::vector<TaskInfoData>, | ||
| 89 | + std::vector<HostTask>, std::vector<AscendTaskData>); | ||
| 90 | + | ||
| 91 | + | ||
| 92 | + | ||
| 93 | +} // namespace Application | ||
| 94 | +} // namespace Analysis | ||
| @@ -16,6 +16,10 @@ | |||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 19 | namespace Analysis | 23 | namespace Analysis |
| 20 | { | 24 | { |
| 21 | namespace Application | 25 | namespace Application |
| @@ -18,7 +18,6 @@ | |||
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | - | ||
| 22 | 21 | ||
| 23 | 22 | ||
| 24 | 23 | ||
| @@ -104,16 +103,6 @@ uint8_t OverlapAnalysisAssembler::AssembleData(DataInventory &dataInventory, Jso | |||
| 104 | const std::string &profPath) | 103 | const std::string &profPath) |
| 105 | { | 104 | { |
| 106 | auto overlapData = dataInventory.GetPtr<std::vector<OverlapAnalysisData>>(); | 105 | auto overlapData = dataInventory.GetPtr<std::vector<OverlapAnalysisData>>(); |
| 107 | - if (!overlapData) | ||
| 108 | - { | ||
| 109 | - OverlapAnalysisProcessor processor(profPath); | ||
| 110 | - if (!processor.Run(dataInventory, PROCESSOR_NAME_OVERLAP_ANALYSIS)) | ||
| 111 | - { | ||
| 112 | - ERROR("Process overlap analysis data failed."); | ||
| 113 | - return ASSEMBLE_FAILED; | ||
| 114 | - } | ||
| 115 | - overlapData = dataInventory.GetPtr<std::vector<OverlapAnalysisData>>(); | ||
| 116 | - } | ||
| 117 | if (!overlapData || overlapData->empty()) | 106 | if (!overlapData || overlapData->empty()) |
| 118 | { | 107 | { |
| 119 | WARN("No overlap analysis data found."); | 108 | WARN("No overlap analysis data found."); |
| @@ -16,12 +16,15 @@ | |||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | -#include <atomic> | 19 | +#include <algorithm> |
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 20 | 24 | ||
| 21 | 25 | ||
| 22 | 26 | ||
| 23 | -#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/step_trace_data.h" | 27 | +#include "analysis/csrc/infrastructure/process/include/topo_callback_process.h" |
| 24 | - | ||
| 25 | 28 | ||
| 26 | namespace Analysis | 29 | namespace Analysis |
| 27 | { | 30 | { |
| @@ -32,8 +35,9 @@ namespace | |||
| 32 | const std::string PREFIX_CONTEXT = "["; | 35 | const std::string PREFIX_CONTEXT = "["; |
| 33 | const std::string SUFFIX_CONTEXT = "]"; | 36 | const std::string SUFFIX_CONTEXT = "]"; |
| 34 | const int JSON_FILE_OFFSET = -1; | 37 | const int JSON_FILE_OFFSET = -1; |
| 35 | -// 数据中心中最少也会有hash类数据 | 38 | +const std::string TIMELINE_PREFIX = "TIMELINE:"; |
| 36 | -const size_t MIN_NUM_FOR_IOC = std::set<std::string>{PROCESSOR_NAME_HASH}.size(); | 39 | +const std::string TIMELINE_PRE_DUMP = TIMELINE_PREFIX + "PRE_DUMP"; |
| 40 | +const std::string TIMELINE_POST_DUMP = TIMELINE_PREFIX + "POST_DUMP"; | ||
| 37 | 41 | ||
| 38 | const std::unordered_map<JsonProcess, std::string> JSON_TO_ASSEMBLER_TABLE{ | 42 | const std::unordered_map<JsonProcess, std::string> JSON_TO_ASSEMBLER_TABLE{ |
| 39 | {JsonProcess::ASCEND, PROCESS_TASK}, | 43 | {JsonProcess::ASCEND, PROCESS_TASK}, |
| @@ -71,86 +75,8 @@ const std::unordered_map<JsonProcess, std::string> JSON_TO_ASSEMBLER_TABLE{ | |||
| 71 | {JsonProcess::FUSION_TASK, PROCESS_FUSION_TASK}, | 75 | {JsonProcess::FUSION_TASK, PROCESS_FUSION_TASK}, |
| 72 | }; | 76 | }; |
| 73 | 77 | ||
| 74 | -std::set<std::string> TIMELINE_DATA_PROCESS_LIST{ | ||
| 75 | - PROCESSOR_NAME_API, | ||
| 76 | - PROCESSOR_NAME_DPU, | ||
| 77 | - PROCESSOR_NAME_FUSION_TASK, | ||
| 78 | - PROCESSOR_NAME_COMMUNICATION, | ||
| 79 | - PROCESSOR_NAME_CCU_MISSION, | ||
| 80 | - PROCESSOR_NAME_COMPUTE_TASK_INFO, | ||
| 81 | - PROCESSOR_NAME_KFC_TASK, | ||
| 82 | - PROCESSOR_NAME_DEVICE_TX, | ||
| 83 | - PROCESSOR_NAME_MSTX, | ||
| 84 | - PROCESSOR_NAME_STEP_TRACE, | ||
| 85 | - PROCESSOR_NAME_TASK, | ||
| 86 | - PROCESSOR_NAME_ACC_PMU, | ||
| 87 | - PROCESSOR_NAME_AICORE_FREQ, | ||
| 88 | - PROCESSOR_NAME_CHIP_TRAINS, | ||
| 89 | - PROCESSOR_NAME_DDR, | ||
| 90 | - PROCESSOR_NAME_HBM, | ||
| 91 | - PROCESSOR_NAME_HCCS, | ||
| 92 | - PROCESSOR_NAME_CPU_USAGE, | ||
| 93 | - PROCESSOR_NAME_MEM_USAGE, | ||
| 94 | - PROCESSOR_NAME_DISK_USAGE, | ||
| 95 | - PROCESSOR_NAME_NETWORK_USAGE, | ||
| 96 | - PROCESSOR_NAME_OSRT_API, | ||
| 97 | - PROCESSOR_NAME_LLC, | ||
| 98 | - PROCESSOR_NAME_NPU_MEM, | ||
| 99 | - PROCESSOR_NAME_PCIE, | ||
| 100 | - PROCESSOR_NAME_SIO, | ||
| 101 | - PROCESSOR_NAME_SOC, | ||
| 102 | - PROCESSOR_NAME_NIC, | ||
| 103 | - PROCESSOR_NAME_ROCE, | ||
| 104 | - PROCESSOR_NAME_QOS, | ||
| 105 | - PROCESSOR_MC2_COMM_INFO, | ||
| 106 | - PROCESSOR_NAME_MEMCPY_INFO, | ||
| 107 | - PROCESSOR_NAME_NPU_OP_MEM, | ||
| 108 | - PROCESSOR_NAME_NPU_MODULE_MEM, | ||
| 109 | - PROCESSOR_NAME_NIC_TIMELINE, | ||
| 110 | - PROCESSOR_NAME_ROCE_TIMELINE, | ||
| 111 | - PROCESSOR_NAME_LOW_POWER, | ||
| 112 | - PROCESSOR_NAME_BIU_PERF, | ||
| 113 | - PROCESSOR_NAME_UB, | ||
| 114 | - PROCESSOR_NAME_BLOCK_DETAIL, | ||
| 115 | -}; | ||
| 116 | } // namespace | 78 | } // namespace |
| 117 | 79 | ||
| 118 | -bool TimelineManager::ProcessTimeLine(DataInventory& dataInventory, const std::vector<JsonProcess>& jsonProcess) | ||
| 119 | -{ | ||
| 120 | - const uint16_t tableProcessors = 10; // 最多有10个线程 | ||
| 121 | - Analysis::Utils::ThreadPool pool(tableProcessors); | ||
| 122 | - pool.Start(); | ||
| 123 | - std::atomic<bool> retFlag(true); | ||
| 124 | - std::vector<std::string> assemblerList = GetAssemblerList(jsonProcess); | ||
| 125 | - for (const auto& name : assemblerList) | ||
| 126 | - { | ||
| 127 | - pool.AddTask( | ||
| 128 | - [this, &name, &retFlag, &dataInventory]() | ||
| 129 | - { | ||
| 130 | - auto assembler = TimelineFactory::GetAssemblerByName(name); | ||
| 131 | - if (assembler == nullptr) | ||
| 132 | - { | ||
| 133 | - ERROR("% is not defined", name); | ||
| 134 | - retFlag = false; | ||
| 135 | - return; | ||
| 136 | - } | ||
| 137 | - retFlag = assembler->Run(dataInventory, profPath_) && retFlag; | ||
| 138 | - }); | ||
| 139 | - } | ||
| 140 | - pool.WaitAllTasks(); | ||
| 141 | - pool.Stop(); | ||
| 142 | - if (!retFlag) | ||
| 143 | - { | ||
| 144 | - ERROR("The % for json assemble failed to be executed.", profPath_); | ||
| 145 | - PRINT_ERROR( | ||
| 146 | - "The % for json assemble failed to be executed. " | ||
| 147 | - "Please check msprof_analysis_log in outputPath for more info.", | ||
| 148 | - profPath_); | ||
| 149 | - return false; | ||
| 150 | - } | ||
| 151 | - return true; | ||
| 152 | -} | ||
| 153 | - | ||
| 154 | void TimelineManager::WriteFile(const std::string& filePrefix, FileCategory category) | 80 | void TimelineManager::WriteFile(const std::string& filePrefix, FileCategory category) |
| 155 | { | 81 | { |
| 156 | auto tempFile = filePrefix; | 82 | auto tempFile = filePrefix; |
| @@ -160,18 +86,15 @@ void TimelineManager::WriteFile(const std::string& filePrefix, FileCategory cate | |||
| 160 | fileType_.emplace(category, filePath); | 86 | fileType_.emplace(category, filePath); |
| 161 | } | 87 | } |
| 162 | 88 | ||
| 163 | -bool TimelineManager::PreDumpJson(DataInventory& dataInventory) | 89 | +bool TimelineManager::PreDumpJson(const std::vector<JsonProcess>& jsonProcess, DataInventory& dataInventory) |
| 164 | { | 90 | { |
| 165 | - if (dataInventory.Size() <= MIN_NUM_FOR_IOC) | ||
| 166 | - { | ||
| 167 | - return false; | ||
| 168 | - } | ||
| 169 | WriteFile(MSPROF_JSON_FILE, FileCategory::MSPROF); | 91 | WriteFile(MSPROF_JSON_FILE, FileCategory::MSPROF); |
| 170 | - if (dataInventory.GetPtr<std::vector<TrainTraceData>>()) | 92 | + if (std::find(jsonProcess.begin(), jsonProcess.end(), JsonProcess::STEP_TRACE) != jsonProcess.end()) |
| 171 | { | 93 | { |
| 172 | WriteFile(STEP_TRACE_FILE, FileCategory::STEP); | 94 | WriteFile(STEP_TRACE_FILE, FileCategory::STEP); |
| 173 | } | 95 | } |
| 174 | - if (dataInventory.GetPtr<std::vector<MsprofTxHostData>>()) | 96 | + if (std::find(jsonProcess.begin(), jsonProcess.end(), JsonProcess::MSPROFTX) != jsonProcess.end() && |
| 97 | + dataInventory.GetPtr<std::vector<MsprofTxHostData>>() != nullptr) | ||
| 175 | { | 98 | { |
| 176 | WriteFile(MSPROF_TX_FILE, FileCategory::MSPROF_TX); | 99 | WriteFile(MSPROF_TX_FILE, FileCategory::MSPROF_TX); |
| 177 | } | 100 | } |
| @@ -184,44 +107,148 @@ void TimelineManager::PostDumpJson() | |||
| 184 | { | 107 | { |
| 185 | // 此处需要覆盖文件末尾的",",实测必须使用in、out、ate三种模式打开文件,才可以实现覆盖写入 | 108 | // 此处需要覆盖文件末尾的",",实测必须使用in、out、ate三种模式打开文件,才可以实现覆盖写入 |
| 186 | FileWriter writer(it.second, std::ios::in | std::ios::out | std::ios::ate); | 109 | FileWriter writer(it.second, std::ios::in | std::ios::out | std::ios::ate); |
| 187 | - writer.WriteTextBack(SUFFIX_CONTEXT, JSON_FILE_OFFSET); | 110 | + if (File::Size(it.second) == PREFIX_CONTEXT.size()) |
| 111 | + { | ||
| 112 | + writer.WriteText(SUFFIX_CONTEXT); | ||
| 113 | + } | ||
| 114 | + else | ||
| 115 | + { | ||
| 116 | + writer.WriteTextBack(SUFFIX_CONTEXT, JSON_FILE_OFFSET); | ||
| 117 | + } | ||
| 188 | } | 118 | } |
| 189 | } | 119 | } |
| 190 | 120 | ||
| 191 | -bool TimelineManager::Run(DataInventory& dataInventory, const std::vector<JsonProcess>& jsonProcess) | ||
| 192 | -{ | ||
| 193 | - INFO("Start exporting timeline!"); | ||
| 194 | - PRINT_INFO("Start exporting the timeline!"); | ||
| 195 | - if (!PreDumpJson(dataInventory)) | ||
| 196 | - { | ||
| 197 | - WARN("Can't Get data from dataInventory after data process"); | ||
| 198 | - PRINT_WARN("Can't export timeline, msprof_analysis_log in outputPath for more info"); | ||
| 199 | - return true; | ||
| 200 | - } | ||
| 201 | - bool runFlag = ProcessTimeLine(dataInventory, jsonProcess); | ||
| 202 | - PostDumpJson(); | ||
| 203 | - if (!runFlag) | ||
| 204 | - { | ||
| 205 | - ERROR("The unified timeline process failed to be executed."); | ||
| 206 | - PRINT_ERROR( | ||
| 207 | - "The unified timeline process failed to be executed. " | ||
| 208 | - "Please check msprof_analysis_log in outputPath for more info."); | ||
| 209 | - return false; | ||
| 210 | - } | ||
| 211 | - PRINT_INFO("End exporting timeline output_file. The file is stored in the PROF file."); | ||
| 212 | - return true; | ||
| 213 | -} | ||
| 214 | - | ||
| 215 | std::vector<std::string> TimelineManager::GetAssemblerList(const std::vector<JsonProcess>& jsonProcess) | 121 | std::vector<std::string> TimelineManager::GetAssemblerList(const std::vector<JsonProcess>& jsonProcess) |
| 216 | { | 122 | { |
| 217 | std::vector<std::string> assemblerList; | 123 | std::vector<std::string> assemblerList; |
| 124 | + std::set<std::string> assemblerSet; | ||
| 218 | for (const auto& jsonEnum : jsonProcess) | 125 | for (const auto& jsonEnum : jsonProcess) |
| 219 | { | 126 | { |
| 220 | - assemblerList.push_back(JSON_TO_ASSEMBLER_TABLE.at(jsonEnum)); | 127 | + const auto& assemblerName = JSON_TO_ASSEMBLER_TABLE.at(jsonEnum); |
| 128 | + if (assemblerSet.insert(assemblerName).second) | ||
| 129 | + { | ||
| 130 | + assemblerList.push_back(assemblerName); | ||
| 131 | + } | ||
| 221 | } | 132 | } |
| 222 | return assemblerList; | 133 | return assemblerList; |
| 223 | } | 134 | } |
| 224 | 135 | ||
| 225 | -const std::set<std::string>& TimelineManager::GetProcessList() { return TIMELINE_DATA_PROCESS_LIST; } | 136 | +bool TimelineManager::GetTopologyRoots(const std::vector<JsonProcess>& jsonProcesses, std::vector<TopoNodeId>& roots) |
| 137 | +{ | ||
| 138 | + const size_t rootsSize = roots.size(); | ||
| 139 | + for (const auto& name : GetAssemblerList(jsonProcesses)) | ||
| 140 | + { | ||
| 141 | + const TopoNodeId id{TopoNodeStage::TIMELINE_EXPORT, name}; | ||
| 142 | + if (TopoNodeRegistry::Find(id) == nullptr) | ||
| 143 | + { | ||
| 144 | + ERROR("Timeline execution list node % has no static topology registration.", name); | ||
| 145 | + roots.resize(rootsSize); | ||
| 146 | + return false; | ||
| 147 | + } | ||
| 148 | + roots.push_back(id); | ||
| 149 | + } | ||
| 150 | + const TopoNodeId postDump{TopoNodeStage::FLOW_CONTROL, TIMELINE_POST_DUMP}; | ||
| 151 | + if (TopoNodeRegistry::Find(postDump) == nullptr) | ||
| 152 | + { | ||
| 153 | + ERROR("Timeline post dump node has no static topology registration."); | ||
| 154 | + roots.resize(rootsSize); | ||
| 155 | + return false; | ||
| 156 | + } | ||
| 157 | + roots.push_back(postDump); | ||
| 158 | + return true; | ||
| 159 | +} | ||
| 160 | + | ||
| 161 | +TopoNodeCreatorFactory TimelineManager::CreateTimelineAssembler(const std::string& name) | ||
| 162 | +{ | ||
| 163 | + return [name](const TopoBuildContext& context) | ||
| 164 | + { | ||
| 165 | + const std::string profPath = context.profPath; | ||
| 166 | + return [name, profPath]() -> std::unique_ptr<Infra::Process> | ||
| 167 | + { | ||
| 168 | + return std::unique_ptr<Infra::Process>(new (std::nothrow) TopoCallbackProcess( | ||
| 169 | + [name, profPath](DataInventory& dataInventory) -> bool | ||
| 170 | + { | ||
| 171 | + const auto assembler = TimelineFactory::GetAssemblerByName(name); | ||
| 172 | + if (assembler == nullptr) | ||
| 173 | + { | ||
| 174 | + ERROR("% is not defined", name); | ||
| 175 | + return false; | ||
| 176 | + } | ||
| 177 | + return assembler->Run(dataInventory, profPath); | ||
| 178 | + })); | ||
| 179 | + }; | ||
| 180 | + }; | ||
| 181 | +} | ||
| 182 | + | ||
| 183 | +TopoNodeCreatorFactory TimelineManager::CreateTimelinePreDump() | ||
| 184 | +{ | ||
| 185 | + return [](const TopoBuildContext& context) -> Infra::ProcessCreator | ||
| 186 | + { | ||
| 187 | + const auto session = context.timelineSession; | ||
| 188 | + const std::vector<JsonProcess> processes = context.timelineProcesses; | ||
| 189 | + if (session == nullptr) | ||
| 190 | + { | ||
| 191 | + return Infra::ProcessCreator(); | ||
| 192 | + } | ||
| 193 | + return [session, processes]() -> std::unique_ptr<Infra::Process> | ||
| 194 | + { | ||
| 195 | + return std::unique_ptr<Infra::Process>(new (std::nothrow) TopoCallbackProcess( | ||
| 196 | + [session, processes](DataInventory& dataInventory) -> bool | ||
| 197 | + { | ||
| 198 | + INFO("Start exporting timeline!"); | ||
| 199 | + PRINT_INFO("Start exporting the timeline!"); | ||
| 200 | + return session->PreDumpJson(processes, dataInventory); | ||
| 201 | + })); | ||
| 202 | + }; | ||
| 203 | + }; | ||
| 204 | +} | ||
| 205 | + | ||
| 206 | +TopoNodeCreatorFactory TimelineManager::CreateTimelinePostDump() | ||
| 207 | +{ | ||
| 208 | + return [](const TopoBuildContext& context) -> Infra::ProcessCreator | ||
| 209 | + { | ||
| 210 | + const auto session = context.timelineSession; | ||
| 211 | + if (session == nullptr) | ||
| 212 | + { | ||
| 213 | + return Infra::ProcessCreator(); | ||
| 214 | + } | ||
| 215 | + return [session]() -> std::unique_ptr<Infra::Process> | ||
| 216 | + { | ||
| 217 | + return std::unique_ptr<Infra::Process>(new (std::nothrow) TopoCallbackProcess( | ||
| 218 | + [session](DataInventory&) -> bool | ||
| 219 | + { | ||
| 220 | + session->PostDumpJson(); | ||
| 221 | + PRINT_INFO("End exporting timeline output_file. The file is stored in the PROF file."); | ||
| 222 | + return true; | ||
| 223 | + })); | ||
| 224 | + }; | ||
| 225 | + }; | ||
| 226 | +} | ||
| 227 | + | ||
| 228 | +std::vector<TopoNodeId> TimelineManager::ResolveSelectedTimelineNodes(const TopoBuildContext&, | ||
| 229 | + const std::vector<TopoNodeId>& roots) | ||
| 230 | +{ | ||
| 231 | + std::vector<TopoNodeId> dependencies; | ||
| 232 | + for (const auto& root : roots) | ||
| 233 | + { | ||
| 234 | + if (root.stage == TopoNodeStage::TIMELINE_EXPORT) | ||
| 235 | + { | ||
| 236 | + dependencies.push_back(root); | ||
| 237 | + } | ||
| 238 | + } | ||
| 239 | + return dependencies; | ||
| 240 | +} | ||
| 241 | + | ||
| 242 | +std::vector<TopoNodeId> TimelineManager::ResolveTimelinePreDumpDependencies(const TopoBuildContext& context, | ||
| 243 | + const std::vector<TopoNodeId>&) | ||
| 244 | +{ | ||
| 245 | + std::vector<TopoNodeId> dependencies; | ||
| 246 | + if (std::find(context.timelineProcesses.begin(), context.timelineProcesses.end(), JsonProcess::MSPROFTX) != | ||
| 247 | + context.timelineProcesses.end()) | ||
| 248 | + { | ||
| 249 | + dependencies.push_back(TopoNodeId{TopoNodeStage::DATA_PROCESSING, PROCESSOR_NAME_MSTX}); | ||
| 250 | + } | ||
| 251 | + return dependencies; | ||
| 252 | +} | ||
| 226 | } // namespace Application | 253 | } // namespace Application |
| 227 | } // namespace Analysis | 254 | } // namespace Analysis |
| @@ -17,32 +17,47 @@ | |||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | + | ||
| 20 | 21 | ||
| 22 | + | ||
| 21 | 23 | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 22 | 27 | ||
| 23 | 28 | ||
| 24 | -#include "analysis/csrc/application/timeline/json_process_enum.h" | 29 | +#include "analysis/csrc/infrastructure/process/include/topo_graph.h" |
| 25 | 30 | ||
| 26 | -namespace Analysis { | 31 | +namespace Analysis |
| 27 | -namespace Application { | 32 | +{ |
| 33 | +namespace Application | ||
| 34 | +{ | ||
| 28 | using namespace Analysis::Infra; | 35 | using namespace Analysis::Infra; |
| 29 | -class TimelineManager { | 36 | +class TimelineManager |
| 30 | -public: | 37 | +{ |
| 38 | + public: | ||
| 31 | explicit TimelineManager(const std::string &profPath, const std::string &outputPath) | 39 | explicit TimelineManager(const std::string &profPath, const std::string &outputPath) |
| 32 | : profPath_(profPath), outputPath_(outputPath) {}; | 40 | : profPath_(profPath), outputPath_(outputPath) {}; |
| 33 | - bool Run(DataInventory &dataInventory, const std::vector<JsonProcess>& jsonProcess); | 41 | + static bool GetTopologyRoots(const std::vector<JsonProcess> &jsonProcesses, std::vector<TopoNodeId> &roots); |
| 34 | - const static std::set<std::string>& GetProcessList(); | 42 | + static TopoNodeCreatorFactory CreateTimelineAssembler(const std::string &name); |
| 35 | -private: | 43 | + static TopoNodeCreatorFactory CreateTimelinePreDump(); |
| 36 | - bool ProcessTimeLine(DataInventory &dataInventory, const std::vector<JsonProcess> &jsonEnum); | 44 | + static TopoNodeCreatorFactory CreateTimelinePostDump(); |
| 37 | - bool PreDumpJson(DataInventory &dataInventory); | 45 | + static std::vector<TopoNodeId> ResolveSelectedTimelineNodes(const TopoBuildContext &context, |
| 46 | + const std::vector<TopoNodeId> &roots); | ||
| 47 | + static std::vector<TopoNodeId> ResolveTimelinePreDumpDependencies(const TopoBuildContext &context, | ||
| 48 | + const std::vector<TopoNodeId> &roots); | ||
| 49 | + bool PreDumpJson(const std::vector<JsonProcess> &jsonProcess, DataInventory &dataInventory); | ||
| 38 | void PostDumpJson(); | 50 | void PostDumpJson(); |
| 51 | + | ||
| 52 | + private: | ||
| 39 | void WriteFile(const std::string &filePrefix, FileCategory category); | 53 | void WriteFile(const std::string &filePrefix, FileCategory category); |
| 40 | - std::vector<std::string> GetAssemblerList(const std::vector<JsonProcess>& jsonProcess); | 54 | + static std::vector<std::string> GetAssemblerList(const std::vector<JsonProcess> &jsonProcess); |
| 41 | -private: | 55 | + |
| 56 | + private: | ||
| 42 | std::string profPath_; | 57 | std::string profPath_; |
| 43 | std::string outputPath_; | 58 | std::string outputPath_; |
| 44 | std::unordered_map<FileCategory, std::string> fileType_; | 59 | std::unordered_map<FileCategory, std::string> fileType_; |
| 45 | }; | 60 | }; |
| 46 | -} | 61 | +} // namespace Application |
| 47 | -} | 62 | +} // namespace Analysis |
| 48 | -#endif // ANALYSIS_APPLICATION_TIMELINE_MANAGER_H | 63 | +#endif // ANALYSIS_APPLICATION_TIMELINE_MANAGER_H |
| @@ -0,0 +1,183 @@ | |||
| 1 | +/* ------------------------------------------------------------------------- | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This file is part of the MindStudio project. | ||
| 4 | + * | ||
| 5 | + * MindStudio is licensed under Mulan PSL v2. | ||
| 6 | + * You can use this software according to the terms and conditions of the Mulan PSL v2. | ||
| 7 | + * You may obtain a copy of Mulan PSL v2 at: | ||
| 8 | + * | ||
| 9 | + * http://license.coscl.org.cn/MulanPSL2 | ||
| 10 | + * | ||
| 11 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, | ||
| 12 | + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, | ||
| 13 | + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. | ||
| 14 | + * See the Mulan PSL v2 for more details. | ||
| 15 | + * -------------------------------------------------------------------------*/ | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + | ||
| 32 | + | ||
| 33 | + | ||
| 34 | + | ||
| 35 | + | ||
| 36 | + | ||
| 37 | + | ||
| 38 | + | ||
| 39 | + | ||
| 40 | + | ||
| 41 | + | ||
| 42 | + | ||
| 43 | + | ||
| 44 | + | ||
| 45 | + | ||
| 46 | + | ||
| 47 | + | ||
| 48 | + | ||
| 49 | + | ||
| 50 | + | ||
| 51 | + | ||
| 52 | + | ||
| 53 | + | ||
| 54 | + | ||
| 55 | + | ||
| 56 | + | ||
| 57 | +namespace Analysis | ||
| 58 | +{ | ||
| 59 | +namespace Application | ||
| 60 | +{ | ||
| 61 | +using namespace Analysis::Domain; | ||
| 62 | + | ||
| 63 | +namespace | ||
| 64 | +{ | ||
| 65 | +const std::string TIMELINE_PREFIX = "TIMELINE:"; | ||
| 66 | +const std::string TIMELINE_PRE_DUMP = TIMELINE_PREFIX + "PRE_DUMP"; | ||
| 67 | +const std::string TIMELINE_POST_DUMP = TIMELINE_PREFIX + "POST_DUMP"; | ||
| 68 | +} // namespace | ||
| 69 | + | ||
| 70 | + | ||
| 71 | + REGISTER_TOPO_NODE_SEQUENCE(typeid(void), TOPO_NODE(TIMELINE_EXPORT, Name), true, \ | ||
| 72 | + TimelineManager::CreateTimelineAssembler(Name), Dependencies, nullptr) | ||
| 73 | + | ||
| 74 | + | ||
| 75 | + REGISTER_TIMELINE_NODE(Name, Dependencies); \ | ||
| 76 | + REGISTER_TOPO_NODE_DEPENDENT_DATA(TOPO_NODE(TIMELINE_EXPORT, Name), __VA_ARGS__) | ||
| 77 | + | ||
| 78 | +REGISTER_TOPO_NODE_SEQUENCE(typeid(void), TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP), true, | ||
| 79 | + TimelineManager::CreateTimelinePreDump(), TOPO_DEPS(), | ||
| 80 | + TimelineManager::ResolveTimelinePreDumpDependencies); | ||
| 81 | +REGISTER_TOPO_NODE_DEPENDENT_DATA(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP), std::vector<MsprofTxHostData>); | ||
| 82 | + | ||
| 83 | +REGISTER_TIMELINE_NODE_WITH_DATA( | ||
| 84 | + PROCESS_TASK, | ||
| 85 | + TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP), TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_TASK), | ||
| 86 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_KFC_TASK), | ||
| 87 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_COMPUTE_TASK_INFO), | ||
| 88 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_API), TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_MEMCPY_INFO)), | ||
| 89 | + std::unordered_map<uint32_t, uint32_t>, std::vector<TaskInfoData>, std::vector<ApiData>, | ||
| 90 | + std::vector<MemcpyInfoData>, std::vector<AscendTaskData>, std::vector<KfcTurnData>); | ||
| 91 | +REGISTER_TIMELINE_NODE_WITH_DATA(PROCESS_ACC_PMU, | ||
| 92 | + TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP), | ||
| 93 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_ACC_PMU)), | ||
| 94 | + std::vector<AccPmuData>); | ||
| 95 | +REGISTER_TIMELINE_NODE_WITH_DATA(PROCESS_API, | ||
| 96 | + TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP), | ||
| 97 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_API), | ||
| 98 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_TASK)), | ||
| 99 | + std::vector<AscendTaskData>, std::vector<ApiData>); | ||
| 100 | +REGISTER_TIMELINE_NODE_WITH_DATA(PROCESS_DDR, | ||
| 101 | + TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP), | ||
| 102 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_DDR)), | ||
| 103 | + std::vector<DDRData>); | ||
| 104 | +REGISTER_TIMELINE_NODE_WITH_DATA(PROCESS_STARS_CHIP_TRANS, | ||
| 105 | + TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP), | ||
| 106 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_CHIP_TRAINS), | ||
| 107 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_PCIE)), | ||
| 108 | + std::vector<PaLinkInfoData>, std::vector<PcieInfoData>); | ||
| 109 | +REGISTER_TIMELINE_NODE_WITH_DATA(PROCESS_HBM, | ||
| 110 | + TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP), | ||
| 111 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_HBM)), | ||
| 112 | + std::vector<HbmData>); | ||
| 113 | +REGISTER_TIMELINE_NODE_WITH_DATA(PROCESS_HCCL, | ||
| 114 | + TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP), | ||
| 115 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_COMMUNICATION), | ||
| 116 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_KFC_TASK)), | ||
| 117 | + std::vector<CommunicationTaskData>, std::vector<CommunicationOpData>, | ||
| 118 | + std::vector<KfcTaskData>, std::vector<KfcOpData>); | ||
| 119 | +REGISTER_TIMELINE_NODE_WITH_DATA(PROCESS_CCU, | ||
| 120 | + TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP), | ||
| 121 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_CCU_MISSION)), | ||
| 122 | + std::vector<CCUMissionTimelineData>); | ||
| 123 | +REGISTER_TIMELINE_NODE_WITH_DATA(PROCESS_HCCS, | ||
| 124 | + TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP), | ||
| 125 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_HCCS)), | ||
| 126 | + std::vector<HccsData>); | ||
| 127 | + | ||
| 128 | + | ||
| 129 | + REGISTER_TIMELINE_NODE_WITH_DATA( \ | ||
| 130 | + Name, TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP), TOPO_NODE(DATA_PROCESSING, Processor)), DataType) | ||
| 131 | + | ||
| 132 | +REGISTER_SIMPLE_TIMELINE_NODE(PROCESSOR_NAME_OSRT_API, PROCESSOR_NAME_OSRT_API, std::vector<OSRuntimeApiData>); | ||
| 133 | +REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_NETWORK_USAGE, PROCESSOR_NAME_NETWORK_USAGE, std::vector<NetWorkUsageData>); | ||
| 134 | +REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_DISK_USAGE, PROCESSOR_NAME_DISK_USAGE, std::vector<DiskUsageData>); | ||
| 135 | +REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_MEMORY_USAGE, PROCESSOR_NAME_MEM_USAGE, std::vector<MemUsageData>); | ||
| 136 | +REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_CPU_USAGE, PROCESSOR_NAME_CPU_USAGE, std::vector<CpuUsageData>); | ||
| 137 | +REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_MSPROFTX, PROCESSOR_NAME_MSTX, std::vector<MsprofTxHostData>); | ||
| 138 | +REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_NPU_MEM, PROCESSOR_NAME_NPU_MEM, std::vector<NpuMemData>); | ||
| 139 | +REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_OVERLAP_ANALYSE, PROCESSOR_NAME_OVERLAP_ANALYSIS, | ||
| 140 | + std::vector<OverlapAnalysisData>); | ||
| 141 | +REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_PCIE, PROCESSOR_NAME_PCIE, std::vector<PCIeData>); | ||
| 142 | +REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_SIO, PROCESSOR_NAME_SIO, std::vector<SioData>); | ||
| 143 | +REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_STARS_SOC, PROCESSOR_NAME_SOC, std::vector<SocBandwidthData>); | ||
| 144 | +REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_LLC, PROCESSOR_NAME_LLC, std::vector<LLcData>); | ||
| 145 | +REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_NIC, PROCESSOR_NAME_NIC_TIMELINE, std::vector<NicReceiveSendData>); | ||
| 146 | +REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_ROCE, PROCESSOR_NAME_ROCE_TIMELINE, std::vector<RoceReceiveSendData>); | ||
| 147 | +REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_QOS, PROCESSOR_NAME_QOS, std::vector<QosData>); | ||
| 148 | +REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_BIU_PERF, PROCESSOR_NAME_BIU_PERF, std::vector<BiuPerfData>); | ||
| 149 | +REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_UB, PROCESSOR_NAME_UB, std::vector<UbData>); | ||
| 150 | +REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_DPU, PROCESSOR_NAME_DPU, std::vector<DPUData>); | ||
| 151 | +REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_FUSION_TASK, PROCESSOR_NAME_FUSION_TASK, std::vector<FusionTaskTimelineData>); | ||
| 152 | + | ||
| 153 | + | ||
| 154 | + | ||
| 155 | +REGISTER_TIMELINE_NODE_WITH_DATA(PROCESS_STEP_TRACE, | ||
| 156 | + TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP), | ||
| 157 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_STEP_TRACE)), | ||
| 158 | + std::vector<TrainTraceData>, std::vector<AllReduceData>, std::vector<GetNextData>); | ||
| 159 | +REGISTER_TIMELINE_NODE_WITH_DATA(PROCESS_LOW_POWER, | ||
| 160 | + TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP), | ||
| 161 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_AICORE_FREQ), | ||
| 162 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_LOW_POWER)), | ||
| 163 | + std::vector<LowPowerData>); | ||
| 164 | +REGISTER_TIMELINE_NODE_WITH_DATA(PROCESS_DEVICE_TX, | ||
| 165 | + TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP), | ||
| 166 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_DEVICE_TX), | ||
| 167 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_MSTX)), | ||
| 168 | + std::vector<MsprofTxDeviceData>, std::vector<MsprofTxHostData>); | ||
| 169 | +REGISTER_TIMELINE_NODE_WITH_DATA(PROCESS_BLOCK_DETAIL, | ||
| 170 | + TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP), | ||
| 171 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_BLOCK_DETAIL), | ||
| 172 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_COMPUTE_TASK_INFO), | ||
| 173 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_TASK)), | ||
| 174 | + std::vector<BlockDetailData>, std::vector<TaskInfoData>, std::vector<AscendTaskData>); | ||
| 175 | + | ||
| 176 | +REGISTER_TOPO_NODE_SEQUENCE(typeid(void), TOPO_NODE(FLOW_CONTROL, TIMELINE_POST_DUMP), true, | ||
| 177 | + TimelineManager::CreateTimelinePostDump(), TOPO_DEPS(), | ||
| 178 | + TimelineManager::ResolveSelectedTimelineNodes); | ||
| 179 | + | ||
| 180 | + | ||
| 181 | + | ||
| 182 | +} // namespace Application | ||
| 183 | +} // namespace Analysis | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* ------------------------------------------------------------------------- | 1 | /* ------------------------------------------------------------------------- |
| 2 | - * Copyright (c) 2025 Huawei Technologies Co., Ltd. | 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. |
| 3 | * This file is part of the MindStudio project. | 3 | * This file is part of the MindStudio project. |
| 4 | * | 4 | * |
| 5 | * MindStudio is licensed under Mulan PSL v2. | 5 | * MindStudio is licensed under Mulan PSL v2. |
| @@ -16,167 +16,20 @@ | |||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | -#include "analysis/csrc/application/database/db_constant.h" | 19 | +#include "analysis/csrc/infrastructure/dfx/error_code.h" |
| 20 | - | ||
| 21 | - | ||
| 22 | - | ||
| 23 | - | ||
| 24 | - | ||
| 25 | - | ||
| 26 | - | ||
| 27 | - | ||
| 28 | - | ||
| 29 | - | ||
| 30 | - | ||
| 31 | - | ||
| 32 | - | ||
| 33 | - | ||
| 34 | - | ||
| 35 | - | ||
| 36 | - | ||
| 37 | - | ||
| 38 | - | ||
| 39 | - | ||
| 40 | - | ||
| 41 | - | ||
| 42 | - | ||
| 43 | - | ||
| 44 | - | ||
| 45 | - | ||
| 46 | - | ||
| 47 | - | ||
| 48 | - | ||
| 49 | - | ||
| 50 | - | ||
| 51 | - | ||
| 52 | - | ||
| 53 | - | ||
| 54 | - | ||
| 55 | - | ||
| 56 | - | ||
| 57 | - | ||
| 58 | - | ||
| 59 | - | ||
| 60 | - | ||
| 61 | - | ||
| 62 | - | ||
| 63 | 20 | ||
| 64 | namespace Analysis | 21 | namespace Analysis |
| 65 | { | 22 | { |
| 66 | namespace Domain | 23 | namespace Domain |
| 67 | { | 24 | { |
| 68 | -std::unordered_map<std::string, ProcessorCreator> DataProcessorFactory::processorTable_{ | 25 | +uint32_t DataProcessorProcess::ProcessEntry(Infra::DataInventory& inventory, const Infra::Context&) |
| 69 | - {PROCESSOR_NAME_API, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 70 | - { MAKE_SHARED_RETURN_VOID(processor, ApiProcessor, profPath); }}, | ||
| 71 | - {PROCESSOR_NAME_DPU, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 72 | - { MAKE_SHARED_RETURN_VOID(processor, DPUProcessor, profPath); }}, | ||
| 73 | - {PROCESSOR_NAME_COMMUNICATION, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 74 | - { MAKE_SHARED_RETURN_VOID(processor, CommunicationInfoProcessor, profPath); }}, | ||
| 75 | - {PROCESSOR_NAME_CCU_MISSION, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 76 | - { MAKE_SHARED_RETURN_VOID(processor, CCUMissionProcessor, profPath); }}, | ||
| 77 | - {PROCESSOR_NAME_COMPUTE_TASK_INFO, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 78 | - { MAKE_SHARED_RETURN_VOID(processor, ComputeTaskInfoProcessor, profPath); }}, | ||
| 79 | - {PROCESSOR_NAME_KFC_TASK, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 80 | - { MAKE_SHARED_RETURN_VOID(processor, KfcTaskProcessor, profPath); }}, | ||
| 81 | - {PROCESSOR_NAME_DEVICE_TX, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 82 | - { MAKE_SHARED_RETURN_VOID(processor, MsprofTxDeviceProcessor, profPath); }}, | ||
| 83 | - {PROCESSOR_NAME_MSTX, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 84 | - { MAKE_SHARED_RETURN_VOID(processor, MsprofTxHostProcessor, profPath); }}, | ||
| 85 | - {PROCESSOR_NAME_STEP_TRACE, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 86 | - { MAKE_SHARED_RETURN_VOID(processor, StepTraceProcessor, profPath); }}, | ||
| 87 | - {PROCESSOR_NAME_TASK, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 88 | - { MAKE_SHARED_RETURN_VOID(processor, TaskProcessor, profPath); }}, | ||
| 89 | - {PROCESSOR_NAME_ACC_PMU, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 90 | - { MAKE_SHARED_RETURN_VOID(processor, AccPmuProcessor, profPath); }}, | ||
| 91 | - {PROCESSOR_NAME_AICORE_FREQ, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 92 | - { MAKE_SHARED_RETURN_VOID(processor, AicoreFreqProcessor, profPath); }}, | ||
| 93 | - {PROCESSOR_NAME_CHIP_TRAINS, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 94 | - { MAKE_SHARED_RETURN_VOID(processor, ChipTransProcessor, profPath); }}, | ||
| 95 | - {PROCESSOR_NAME_DDR, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 96 | - { MAKE_SHARED_RETURN_VOID(processor, DDRProcessor, profPath); }}, | ||
| 97 | - {PROCESSOR_NAME_HBM, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 98 | - { MAKE_SHARED_RETURN_VOID(processor, HBMProcessor, profPath); }}, | ||
| 99 | - {PROCESSOR_NAME_HCCS, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 100 | - { MAKE_SHARED_RETURN_VOID(processor, HCCSProcessor, profPath); }}, | ||
| 101 | - {PROCESSOR_NAME_NETDEV_STATS, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 102 | - { MAKE_SHARED_RETURN_VOID(processor, NetDevStatsProcessor, profPath); }}, | ||
| 103 | - {PROCESSOR_NAME_CPU_USAGE, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 104 | - { MAKE_SHARED_RETURN_VOID(processor, HostCpuUsageProcessor, profPath); }}, | ||
| 105 | - {PROCESSOR_NAME_MEM_USAGE, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 106 | - { MAKE_SHARED_RETURN_VOID(processor, HostMemUsageProcessor, profPath); }}, | ||
| 107 | - {PROCESSOR_NAME_DISK_USAGE, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 108 | - { MAKE_SHARED_RETURN_VOID(processor, HostDiskUsageProcessor, profPath); }}, | ||
| 109 | - {PROCESSOR_NAME_NETWORK_USAGE, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 110 | - { MAKE_SHARED_RETURN_VOID(processor, HostNetworkUsageProcessor, profPath); }}, | ||
| 111 | - {PROCESSOR_NAME_OSRT_API, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 112 | - { MAKE_SHARED_RETURN_VOID(processor, OSRuntimeApiProcessor, profPath); }}, | ||
| 113 | - {PROCESSOR_NAME_LLC, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 114 | - { MAKE_SHARED_RETURN_VOID(processor, LLcProcessor, profPath); }}, | ||
| 115 | - {PROCESSOR_NAME_NPU_MEM, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 116 | - { MAKE_SHARED_RETURN_VOID(processor, NpuMemProcessor, profPath); }}, | ||
| 117 | - {PROCESSOR_NAME_PCIE, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 118 | - { MAKE_SHARED_RETURN_VOID(processor, PCIeProcessor, profPath); }}, | ||
| 119 | - {PROCESSOR_NAME_SIO, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 120 | - { MAKE_SHARED_RETURN_VOID(processor, SioProcessor, profPath); }}, | ||
| 121 | - {PROCESSOR_NAME_SOC, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 122 | - { MAKE_SHARED_RETURN_VOID(processor, SocBandwidthProcessor, profPath); }}, | ||
| 123 | - {PROCESSOR_NAME_PAGE_FAULT, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 124 | - { MAKE_SHARED_RETURN_VOID(processor, PageFaultProcessor, profPath); }}, | ||
| 125 | - {PROCESSOR_NAME_NIC_TIMELINE, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 126 | - { MAKE_SHARED_RETURN_VOID(processor, NicTimelineProcessor, profPath); }}, | ||
| 127 | - {PROCESSOR_NAME_ROCE_TIMELINE, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 128 | - { MAKE_SHARED_RETURN_VOID(processor, RoCETimelineProcessor, profPath); }}, | ||
| 129 | - {PROCESSOR_NAME_NIC, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 130 | - { MAKE_SHARED_RETURN_VOID(processor, NicProcessor, profPath); }}, | ||
| 131 | - {PROCESSOR_NAME_ROCE, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 132 | - { MAKE_SHARED_RETURN_VOID(processor, RoCEProcessor, profPath); }}, | ||
| 133 | - {PROCESSOR_NAME_QOS, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 134 | - { MAKE_SHARED_RETURN_VOID(processor, QosProcessor, profPath); }}, | ||
| 135 | - {PROCESSOR_MC2_COMM_INFO, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 136 | - { MAKE_SHARED_RETURN_VOID(processor, Mc2CommInfoProcessor, profPath); }}, | ||
| 137 | - {PROCESSOR_PMU, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 138 | - { MAKE_SHARED_RETURN_VOID(processor, MetricProcessor, profPath); }}, | ||
| 139 | - {PROCESSOR_NAME_MEMCPY_INFO, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 140 | - { MAKE_SHARED_RETURN_VOID(processor, MemcpyInfoProcessor, profPath); }}, | ||
| 141 | - {PROCESSOR_NAME_NPU_OP_MEM, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 142 | - { MAKE_SHARED_RETURN_VOID(processor, NpuOpMemProcessor, profPath); }}, | ||
| 143 | - {PROCESSOR_NAME_NPU_MODULE_MEM, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 144 | - { MAKE_SHARED_RETURN_VOID(processor, NpuModuleMemProcessor, profPath); }}, | ||
| 145 | - {PROCESSOR_NAME_UNIFIED_PMU, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 146 | - { MAKE_SHARED_RETURN_VOID(processor, UnifiedPmuProcessor, profPath); }}, | ||
| 147 | - {PROCESSOR_NAME_FUSION_OP, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 148 | - { MAKE_SHARED_RETURN_VOID(processor, FusionOpProcessor, profPath); }}, | ||
| 149 | - {PROCESSOR_NAME_FUSION_TASK, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 150 | - { MAKE_SHARED_RETURN_VOID(processor, FusionTaskProcessor, profPath); }}, | ||
| 151 | - {PROCESSOR_NAME_MODEL_NAME, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 152 | - { MAKE_SHARED_RETURN_VOID(processor, ModelNameProcessor, profPath); }}, | ||
| 153 | - {PROCESSOR_NAME_COMM_STATISTIC, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 154 | - { MAKE_SHARED_RETURN_VOID(processor, HcclStatisticProcessor, profPath); }}, | ||
| 155 | - {PROCESSOR_NAME_OP_STATISTIC, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 156 | - { MAKE_SHARED_RETURN_VOID(processor, OpStatisticProcessor, profPath); }}, | ||
| 157 | - {PROCESSOR_HOST_TASK, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 158 | - { MAKE_SHARED_RETURN_VOID(processor, HostTaskProcessor, profPath); }}, | ||
| 159 | - {PROCESSOR_NAME_OVERLAP_ANALYSIS, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 160 | - { MAKE_SHARED_RETURN_VOID(processor, OverlapAnalysisProcessor, profPath); }}, | ||
| 161 | - {PROCESSOR_NAME_LOW_POWER, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 162 | - { MAKE_SHARED_RETURN_VOID(processor, LowPowerProcessor, profPath); }}, | ||
| 163 | - {PROCESSOR_NAME_BIU_PERF, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 164 | - { MAKE_SHARED_RETURN_VOID(processor, BiuPerfProcessor, profPath); }}, | ||
| 165 | - {PROCESSOR_NAME_UB, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 166 | - { MAKE_SHARED_RETURN_VOID(processor, UbProcessor, profPath); }}, | ||
| 167 | - {PROCESSOR_NAME_BLOCK_DETAIL, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor) | ||
| 168 | - { MAKE_SHARED_RETURN_VOID(processor, BlockDetailProcessor, profPath); }}}; | ||
| 169 | - | ||
| 170 | -std::shared_ptr<DataProcessor> DataProcessorFactory::GetDataProcessByName(const std::string &profPath, | ||
| 171 | - const std::string &processName) | ||
| 172 | { | 26 | { |
| 173 | - std::shared_ptr<DataProcessor> processor = nullptr; | 27 | + if (processor_ == nullptr) |
| 174 | - auto it = processorTable_.find(processName); | ||
| 175 | - if (it != processorTable_.end()) | ||
| 176 | { | 28 | { |
| 177 | - it->second(profPath, processor); | 29 | + ERROR("Create processor % failed.", name_); |
| 30 | + return ANALYSIS_ERROR; | ||
| 178 | } | 31 | } |
| 179 | - return processor; | 32 | + return processor_->Run(inventory, name_) ? ANALYSIS_OK : ANALYSIS_ERROR; |
| 180 | } | 33 | } |
| 181 | 34 | ||
| 182 | } // namespace Domain | 35 | } // namespace Domain |
| @@ -0,0 +1,147 @@ | |||
| 1 | +/* ------------------------------------------------------------------------- | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This file is part of the MindStudio project. | ||
| 4 | + * | ||
| 5 | + * MindStudio is licensed under Mulan PSL v2. | ||
| 6 | + * You can use this software according to the terms and conditions of the Mulan PSL v2. | ||
| 7 | + * You may obtain a copy of Mulan PSL v2 at: | ||
| 8 | + * | ||
| 9 | + * http://license.coscl.org.cn/MulanPSL2 | ||
| 10 | + * | ||
| 11 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, | ||
| 12 | + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, | ||
| 13 | + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. | ||
| 14 | + * See the Mulan PSL v2 for more details. | ||
| 15 | + * -------------------------------------------------------------------------*/ | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + | ||
| 32 | + | ||
| 33 | + | ||
| 34 | + | ||
| 35 | + | ||
| 36 | + | ||
| 37 | + | ||
| 38 | + | ||
| 39 | + | ||
| 40 | + | ||
| 41 | + | ||
| 42 | + | ||
| 43 | + | ||
| 44 | + | ||
| 45 | + | ||
| 46 | + | ||
| 47 | + | ||
| 48 | + | ||
| 49 | + | ||
| 50 | + | ||
| 51 | + | ||
| 52 | + | ||
| 53 | + | ||
| 54 | + | ||
| 55 | + | ||
| 56 | + | ||
| 57 | + | ||
| 58 | + | ||
| 59 | + | ||
| 60 | + | ||
| 61 | + | ||
| 62 | + | ||
| 63 | + | ||
| 64 | +namespace Analysis | ||
| 65 | +{ | ||
| 66 | +namespace Domain | ||
| 67 | +{ | ||
| 68 | + | ||
| 69 | + REGISTER_TOPO_NODE_SEQUENCE(typeid(Processor), TOPO_NODE(DATA_PROCESSING, Name), true, \ | ||
| 70 | + CreateDataProcessorFactory<Processor>(Name), Dependencies, nullptr) | ||
| 71 | + | ||
| 72 | + | ||
| 73 | + REGISTER_PROCESSOR(Processor, Name, Dependencies); \ | ||
| 74 | + REGISTER_TOPO_NODE_DEPENDENT_DATA(TOPO_NODE(DATA_PROCESSING, Name), __VA_ARGS__) | ||
| 75 | + | ||
| 76 | + | ||
| 77 | + REGISTER_TOPO_NODE_SEQUENCE(typeid(Processor), TOPO_NODE(DATA_PROCESSING, Name), false, \ | ||
| 78 | + CreateDataProcessorFactory<Processor>(Name), Dependencies, nullptr) | ||
| 79 | + | ||
| 80 | +REGISTER_PROCESSOR(HashInitProcessor, PROCESSOR_NAME_HASH, TOPO_DEPS()); | ||
| 81 | +REGISTER_PROCESSOR(ApiProcessor, PROCESSOR_NAME_API, TOPO_DEPS()); | ||
| 82 | +REGISTER_PROCESSOR(DPUProcessor, PROCESSOR_NAME_DPU, TOPO_DEPS()); | ||
| 83 | +REGISTER_PROCESSOR_WITH_DATA(CommunicationInfoProcessor, PROCESSOR_NAME_COMMUNICATION, | ||
| 84 | + TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_HASH)), GeHashMap); | ||
| 85 | +REGISTER_PROCESSOR(CCUMissionProcessor, PROCESSOR_NAME_CCU_MISSION, TOPO_DEPS()); | ||
| 86 | +REGISTER_PROCESSOR_WITH_DATA(ComputeTaskInfoProcessor, PROCESSOR_NAME_COMPUTE_TASK_INFO, | ||
| 87 | + TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_HASH)), GeHashMap); | ||
| 88 | +REGISTER_PROCESSOR(KfcTaskProcessor, PROCESSOR_NAME_KFC_TASK, TOPO_DEPS()); | ||
| 89 | + | ||
| 90 | +REGISTER_PROCESSOR(MsprofTxDeviceProcessor, PROCESSOR_NAME_DEVICE_TX, TOPO_DEPS()); | ||
| 91 | +REGISTER_PROCESSOR(MsprofTxHostProcessor, PROCESSOR_NAME_MSTX, TOPO_DEPS()); | ||
| 92 | +REGISTER_PROCESSOR(StepTraceProcessor, PROCESSOR_NAME_STEP_TRACE, TOPO_DEPS()); | ||
| 93 | +REGISTER_PROCESSOR(TaskProcessor, PROCESSOR_NAME_TASK, TOPO_DEPS()); | ||
| 94 | +REGISTER_PROCESSOR(AccPmuProcessor, PROCESSOR_NAME_ACC_PMU, TOPO_DEPS()); | ||
| 95 | +REGISTER_PROCESSOR(AicoreFreqProcessor, PROCESSOR_NAME_AICORE_FREQ, TOPO_DEPS()); | ||
| 96 | +REGISTER_PROCESSOR(ChipTransProcessor, PROCESSOR_NAME_CHIP_TRAINS, TOPO_DEPS()); | ||
| 97 | +REGISTER_PROCESSOR(DDRProcessor, PROCESSOR_NAME_DDR, TOPO_DEPS()); | ||
| 98 | +REGISTER_PROCESSOR(HBMProcessor, PROCESSOR_NAME_HBM, TOPO_DEPS()); | ||
| 99 | +REGISTER_PROCESSOR(HCCSProcessor, PROCESSOR_NAME_HCCS, TOPO_DEPS()); | ||
| 100 | +REGISTER_OPTIONAL_PROCESSOR(NetDevStatsProcessor, PROCESSOR_NAME_NETDEV_STATS, TOPO_DEPS()); | ||
| 101 | +REGISTER_PROCESSOR(HostCpuUsageProcessor, PROCESSOR_NAME_CPU_USAGE, TOPO_DEPS()); | ||
| 102 | +REGISTER_PROCESSOR(HostMemUsageProcessor, PROCESSOR_NAME_MEM_USAGE, TOPO_DEPS()); | ||
| 103 | +REGISTER_PROCESSOR(HostDiskUsageProcessor, PROCESSOR_NAME_DISK_USAGE, TOPO_DEPS()); | ||
| 104 | +REGISTER_PROCESSOR(HostNetworkUsageProcessor, PROCESSOR_NAME_NETWORK_USAGE, TOPO_DEPS()); | ||
| 105 | +REGISTER_PROCESSOR(OSRuntimeApiProcessor, PROCESSOR_NAME_OSRT_API, TOPO_DEPS()); | ||
| 106 | +REGISTER_PROCESSOR(LLcProcessor, PROCESSOR_NAME_LLC, TOPO_DEPS()); | ||
| 107 | +REGISTER_PROCESSOR(NpuMemProcessor, PROCESSOR_NAME_NPU_MEM, TOPO_DEPS()); | ||
| 108 | +REGISTER_PROCESSOR(PCIeProcessor, PROCESSOR_NAME_PCIE, TOPO_DEPS()); | ||
| 109 | +REGISTER_PROCESSOR(SioProcessor, PROCESSOR_NAME_SIO, TOPO_DEPS()); | ||
| 110 | +REGISTER_PROCESSOR(SocBandwidthProcessor, PROCESSOR_NAME_SOC, TOPO_DEPS()); | ||
| 111 | +REGISTER_PROCESSOR(PageFaultProcessor, PROCESSOR_NAME_PAGE_FAULT, TOPO_DEPS()); | ||
| 112 | +REGISTER_PROCESSOR(NicTimelineProcessor, PROCESSOR_NAME_NIC_TIMELINE, TOPO_DEPS()); | ||
| 113 | +REGISTER_PROCESSOR(RoCETimelineProcessor, PROCESSOR_NAME_ROCE_TIMELINE, TOPO_DEPS()); | ||
| 114 | +REGISTER_PROCESSOR(NicProcessor, PROCESSOR_NAME_NIC, TOPO_DEPS()); | ||
| 115 | +REGISTER_PROCESSOR(RoCEProcessor, PROCESSOR_NAME_ROCE, TOPO_DEPS()); | ||
| 116 | +REGISTER_PROCESSOR(QosProcessor, PROCESSOR_NAME_QOS, TOPO_DEPS()); | ||
| 117 | +REGISTER_PROCESSOR(Mc2CommInfoProcessor, PROCESSOR_MC2_COMM_INFO, TOPO_DEPS()); | ||
| 118 | +REGISTER_PROCESSOR(MetricProcessor, PROCESSOR_PMU, TOPO_DEPS()); | ||
| 119 | +REGISTER_PROCESSOR(MemcpyInfoProcessor, PROCESSOR_NAME_MEMCPY_INFO, TOPO_DEPS()); | ||
| 120 | +REGISTER_PROCESSOR_WITH_DATA(NpuOpMemProcessor, PROCESSOR_NAME_NPU_OP_MEM, | ||
| 121 | + TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_HASH)), GeHashMap); | ||
| 122 | +REGISTER_PROCESSOR(NpuModuleMemProcessor, PROCESSOR_NAME_NPU_MODULE_MEM, TOPO_DEPS()); | ||
| 123 | +REGISTER_PROCESSOR(UnifiedPmuProcessor, PROCESSOR_NAME_UNIFIED_PMU, TOPO_DEPS()); | ||
| 124 | +REGISTER_PROCESSOR(FusionOpProcessor, PROCESSOR_NAME_FUSION_OP, TOPO_DEPS()); | ||
| 125 | +REGISTER_PROCESSOR(FusionTaskProcessor, PROCESSOR_NAME_FUSION_TASK, TOPO_DEPS()); | ||
| 126 | +REGISTER_PROCESSOR(ModelNameProcessor, PROCESSOR_NAME_MODEL_NAME, TOPO_DEPS()); | ||
| 127 | +REGISTER_PROCESSOR(HcclStatisticProcessor, PROCESSOR_NAME_COMM_STATISTIC, TOPO_DEPS()); | ||
| 128 | +REGISTER_PROCESSOR(OpStatisticProcessor, PROCESSOR_NAME_OP_STATISTIC, TOPO_DEPS()); | ||
| 129 | +REGISTER_PROCESSOR(HostTaskProcessor, PROCESSOR_HOST_TASK, TOPO_DEPS()); | ||
| 130 | +REGISTER_PROCESSOR_WITH_DATA(OverlapAnalysisProcessor, PROCESSOR_NAME_OVERLAP_ANALYSIS, | ||
| 131 | + TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_TASK), | ||
| 132 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_COMPUTE_TASK_INFO), | ||
| 133 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_COMMUNICATION), | ||
| 134 | + TOPO_NODE(DATA_PROCESSING, PROCESSOR_MC2_COMM_INFO)), | ||
| 135 | + std::vector<AscendTaskData>, std::vector<TaskInfoData>, std::vector<CommunicationOpData>, | ||
| 136 | + std::vector<MC2CommInfoData>); | ||
| 137 | +REGISTER_PROCESSOR(LowPowerProcessor, PROCESSOR_NAME_LOW_POWER, TOPO_DEPS()); | ||
| 138 | +REGISTER_PROCESSOR(BiuPerfProcessor, PROCESSOR_NAME_BIU_PERF, TOPO_DEPS()); | ||
| 139 | +REGISTER_PROCESSOR(UbProcessor, PROCESSOR_NAME_UB, TOPO_DEPS()); | ||
| 140 | +REGISTER_PROCESSOR(BlockDetailProcessor, PROCESSOR_NAME_BLOCK_DETAIL, TOPO_DEPS()); | ||
| 141 | + | ||
| 142 | + | ||
| 143 | + | ||
| 144 | + | ||
| 145 | + | ||
| 146 | +} // namespace Domain | ||
| 147 | +} // namespace Analysis | ||
| @@ -17,19 +17,55 @@ | |||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | -#include <functional> | 20 | +#include <memory> |
| 21 | -#include "analysis/csrc/domain/data_process/data_processor.h" | 21 | +#include <new> |
| 22 | + | ||
| 23 | + | ||
| 22 | 24 | ||
| 23 | -namespace Analysis { | 25 | +#include "analysis/csrc/domain/data_process/data_processor.h" |
| 24 | -namespace Domain { | 26 | +#include "analysis/csrc/infrastructure/process/include/process.h" |
| 25 | -using ProcessorCreator = std::function<void(const std::string&, std::shared_ptr<DataProcessor>&)>; | 27 | +#include "analysis/csrc/infrastructure/process/include/process_struct.h" |
| 26 | -class DataProcessorFactory { | 28 | +#include "analysis/csrc/infrastructure/process/include/topo_graph.h" |
| 27 | -public: | 29 | + |
| 28 | - static std::shared_ptr<DataProcessor> GetDataProcessByName(const std::string &profPath, | 30 | +namespace Analysis |
| 29 | - const std::string &processName); | 31 | +{ |
| 30 | -private: | 32 | +namespace Domain |
| 31 | - static std::unordered_map<std::string, ProcessorCreator> processorTable_; | 33 | +{ |
| 34 | +class DataProcessorProcess final : public Infra::Process | ||
| 35 | +{ | ||
| 36 | + public: | ||
| 37 | + DataProcessorProcess(std::shared_ptr<DataProcessor> processor, std::string name) | ||
| 38 | + : processor_(std::move(processor)), name_(std::move(name)) | ||
| 39 | + { | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + const std::shared_ptr<DataProcessor>& GetProcessor() const { return processor_; } | ||
| 43 | + | ||
| 44 | + private: | ||
| 45 | + uint32_t ProcessEntry(Infra::DataInventory& inventory, const Infra::Context&) override; | ||
| 46 | + | ||
| 47 | + std::shared_ptr<DataProcessor> processor_; | ||
| 48 | + std::string name_; | ||
| 32 | }; | 49 | }; |
| 50 | + | ||
| 51 | +template <typename Processor> | ||
| 52 | +Application::TopoNodeCreatorFactory CreateDataProcessorFactory(const std::string& processName) | ||
| 53 | +{ | ||
| 54 | + return [processName](const Application::TopoBuildContext& context) | ||
| 55 | + { | ||
| 56 | + const std::string profPath = context.profPath; | ||
| 57 | + return [processName, profPath]() -> std::unique_ptr<Infra::Process> | ||
| 58 | + { | ||
| 59 | + std::shared_ptr<DataProcessor> processor(new (std::nothrow) Processor(profPath)); | ||
| 60 | + if (processor == nullptr) | ||
| 61 | + { | ||
| 62 | + return nullptr; | ||
| 63 | + } | ||
| 64 | + return std::unique_ptr<Infra::Process>(new (std::nothrow) DataProcessorProcess(processor, processName)); | ||
| 65 | + }; | ||
| 66 | + }; | ||
| 33 | } | 67 | } |
| 34 | -} | 68 | + |
| 35 | -#endif // ANALYSIS_DOMAIN_DATA_PROCESSOR_FACTORY_H | 69 | +} // namespace Domain |
| 70 | +} // namespace Analysis | ||
| 71 | + | ||
| @@ -17,17 +17,20 @@ | |||
| 17 | 17 | ||
| 18 | using namespace Analysis; | 18 | using namespace Analysis; |
| 19 | 19 | ||
| 20 | -namespace Analysis { | 20 | +namespace Analysis |
| 21 | +{ | ||
| 21 | 22 | ||
| 22 | -namespace Infra { | 23 | +namespace Infra |
| 24 | +{ | ||
| 23 | 25 | ||
| 24 | bool DataInventory::InputToData(std::type_index idx, BaseTypePtr ptr) | 26 | bool DataInventory::InputToData(std::type_index idx, BaseTypePtr ptr) |
| 25 | { | 27 | { |
| 26 | - if (ptr == nullptr) { | 28 | + if (ptr == nullptr) |
| 29 | + { | ||
| 27 | ERROR("invalid ptr, type name: %", idx.name()); | 30 | ERROR("invalid ptr, type name: %", idx.name()); |
| 28 | return false; | 31 | return false; |
| 29 | } | 32 | } |
| 30 | - | 33 | + |
| 31 | std::lock_guard<std::mutex> lg(mutex_); | 34 | std::lock_guard<std::mutex> lg(mutex_); |
| 32 | auto ret = data_.emplace(idx, ptr); | 35 | auto ret = data_.emplace(idx, ptr); |
| 33 | return ret.second; | 36 | return ret.second; |
| @@ -37,9 +40,10 @@ std::set<std::type_index> DataInventory::RemoveRestData(const std::set<std::type | |||
| 37 | { | 40 | { |
| 38 | std::set<std::type_index> removedTypes; | 41 | std::set<std::type_index> removedTypes; |
| 39 | std::lock_guard<std::mutex> lg(mutex_); | 42 | std::lock_guard<std::mutex> lg(mutex_); |
| 40 | - for (auto it = data_.begin(); it != data_.end();) { | 43 | + for (auto it = data_.begin(); it != data_.end();) |
| 41 | - if (std::find(keepingDataType.begin(), keepingDataType.end(), it->first) == | 44 | + { |
| 42 | - std::end(keepingDataType)) { | 45 | + if (std::find(keepingDataType.begin(), keepingDataType.end(), it->first) == std::end(keepingDataType)) |
| 46 | + { | ||
| 43 | removedTypes.insert(it->first); | 47 | removedTypes.insert(it->first); |
| 44 | it = data_.erase(it); | 48 | it = data_.erase(it); |
| 45 | continue; | 49 | continue; |
| @@ -53,13 +57,14 @@ BaseTypePtr DataInventory::GetPtr(std::type_index idx) const | |||
| 53 | { | 57 | { |
| 54 | std::lock_guard<std::mutex> lg(mutex_); | 58 | std::lock_guard<std::mutex> lg(mutex_); |
| 55 | auto it = data_.find(idx); | 59 | auto it = data_.find(idx); |
| 56 | - if (it == data_.end()) { | 60 | + if (it == data_.end()) |
| 61 | + { | ||
| 57 | return {}; | 62 | return {}; |
| 58 | } | 63 | } |
| 59 | 64 | ||
| 60 | return it->second; | 65 | return it->second; |
| 61 | } | 66 | } |
| 62 | 67 | ||
| 63 | -} | 68 | +} // namespace Infra |
| 64 | 69 | ||
| 65 | -} | 70 | +} // namespace Analysis |
| @@ -20,35 +20,42 @@ | |||
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | 22 | ||
| 23 | - | ||
| 24 | - | ||
| 25 | - | ||
| 26 | 23 | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 27 | 28 | ||
| 28 | 29 | ||
| 29 | -using Analysis::Log; | ||
| 30 | using Analysis::Format; | 30 | using Analysis::Format; |
| 31 | +using Analysis::Log; | ||
| 31 | 32 | ||
| 32 | -namespace Analysis { | 33 | +namespace Analysis |
| 33 | -namespace Infra { | 34 | +{ |
| 35 | +namespace Infra | ||
| 36 | +{ | ||
| 34 | 37 | ||
| 35 | -struct BaseType { | 38 | +struct BaseType |
| 39 | +{ | ||
| 36 | virtual ~BaseType() = default; | 40 | virtual ~BaseType() = default; |
| 37 | }; | 41 | }; |
| 38 | using BaseTypePtr = std::shared_ptr<BaseType>; | 42 | using BaseTypePtr = std::shared_ptr<BaseType>; |
| 39 | 43 | ||
| 40 | template <typename T> | 44 | template <typename T> |
| 41 | -struct CustomType : public BaseType { | 45 | +struct CustomType : public BaseType |
| 46 | +{ | ||
| 42 | std::shared_ptr<T> data; | 47 | std::shared_ptr<T> data; |
| 43 | }; | 48 | }; |
| 44 | 49 | ||
| 45 | -template<typename T> | 50 | +template <typename T> |
| 46 | -struct SharedPtrType { | 51 | +struct SharedPtrType |
| 52 | +{ | ||
| 47 | using Type = std::shared_ptr<T>; | 53 | using Type = std::shared_ptr<T>; |
| 48 | }; | 54 | }; |
| 49 | 55 | ||
| 50 | -class DataInventory { | 56 | +class DataInventory |
| 51 | -public: | 57 | +{ |
| 58 | + public: | ||
| 52 | /** | 59 | /** |
| 53 | * @brief 将数据存放入DataInventory | 60 | * @brief 将数据存放入DataInventory |
| 54 | * | 61 | * |
| @@ -57,14 +64,16 @@ public: | |||
| 57 | * @return 成功或失败 | 64 | * @return 成功或失败 |
| 58 | * @note 非常重要:使用本接口缓存的数据,如果没有用REGISTER_PROCESS_DEPENDENT_DATA注册,会立即被释放 | 65 | * @note 非常重要:使用本接口缓存的数据,如果没有用REGISTER_PROCESS_DEPENDENT_DATA注册,会立即被释放 |
| 59 | */ | 66 | */ |
| 60 | - template<typename T> | 67 | + template <typename T> |
| 61 | bool Inject(std::shared_ptr<T> ptr) | 68 | bool Inject(std::shared_ptr<T> ptr) |
| 62 | { | 69 | { |
| 63 | - if (ptr == nullptr) { | 70 | + if (ptr == nullptr) |
| 71 | + { | ||
| 64 | return false; | 72 | return false; |
| 65 | } | 73 | } |
| 66 | 74 | ||
| 67 | - if (GetPtr<T>() != nullptr) { // 不支持注入相同类型数据 | 75 | + if (GetPtr<T>() != nullptr) |
| 76 | + { // 不支持注入相同类型数据 | ||
| 68 | return false; | 77 | return false; |
| 69 | } | 78 | } |
| 70 | 79 | ||
| @@ -73,7 +82,7 @@ public: | |||
| 73 | container->data = ptr; | 82 | container->data = ptr; |
| 74 | return InputToData(typeid(T), container); | 83 | return InputToData(typeid(T), container); |
| 75 | } | 84 | } |
| 76 | - template<typename T> | 85 | + template <typename T> |
| 77 | std::shared_ptr<T> GetPtr() const | 86 | std::shared_ptr<T> GetPtr() const |
| 78 | { | 87 | { |
| 79 | return Cast<T>(GetPtr(typeid(T))); | 88 | return Cast<T>(GetPtr(typeid(T))); |
| @@ -87,32 +96,30 @@ public: | |||
| 87 | */ | 96 | */ |
| 88 | std::set<std::type_index> RemoveRestData(const std::set<std::type_index>& keepingDataType); | 97 | std::set<std::type_index> RemoveRestData(const std::set<std::type_index>& keepingDataType); |
| 89 | 98 | ||
| 90 | - std::size_t Size() | 99 | + std::size_t Size() { return data_.size(); } |
| 91 | - { | ||
| 92 | - return data_.size(); | ||
| 93 | - } | ||
| 94 | 100 | ||
| 95 | DataInventory() = default; | 101 | DataInventory() = default; |
| 96 | ~DataInventory() = default; | 102 | ~DataInventory() = default; |
| 97 | DataInventory(const DataInventory&) = delete; | 103 | DataInventory(const DataInventory&) = delete; |
| 98 | DataInventory& operator=(const DataInventory&) = delete; | 104 | DataInventory& operator=(const DataInventory&) = delete; |
| 99 | - DataInventory(DataInventory&& dataInventory) : data_(std::move(dataInventory.data_)) | 105 | + DataInventory(DataInventory&& dataInventory) : data_(std::move(dataInventory.data_)) {} |
| 100 | - { | ||
| 101 | - } | ||
| 102 | DataInventory& operator=(DataInventory&& dataInventory) | 106 | DataInventory& operator=(DataInventory&& dataInventory) |
| 103 | { | 107 | { |
| 104 | - if (&dataInventory == this) { | 108 | + if (&dataInventory == this) |
| 109 | + { | ||
| 105 | return *this; | 110 | return *this; |
| 106 | } | 111 | } |
| 107 | data_.swap(dataInventory.data_); | 112 | data_.swap(dataInventory.data_); |
| 108 | dataInventory.data_.clear(); | 113 | dataInventory.data_.clear(); |
| 109 | return *this; | 114 | return *this; |
| 110 | } | 115 | } |
| 111 | -private: | 116 | + |
| 112 | - template<typename T> | 117 | + private: |
| 118 | + template <typename T> | ||
| 113 | std::shared_ptr<T> Cast(const BaseTypePtr& ptr) const | 119 | std::shared_ptr<T> Cast(const BaseTypePtr& ptr) const |
| 114 | { | 120 | { |
| 115 | - if (ptr == nullptr) { | 121 | + if (ptr == nullptr) |
| 122 | + { | ||
| 116 | return {}; | 123 | return {}; |
| 117 | } | 124 | } |
| 118 | auto customPtr = std::static_pointer_cast<CustomType<T>>(ptr); | 125 | auto customPtr = std::static_pointer_cast<CustomType<T>>(ptr); |
| @@ -121,13 +128,13 @@ private: | |||
| 121 | bool InputToData(std::type_index idx, BaseTypePtr ptr); | 128 | bool InputToData(std::type_index idx, BaseTypePtr ptr); |
| 122 | BaseTypePtr GetPtr(std::type_index idx) const; | 129 | BaseTypePtr GetPtr(std::type_index idx) const; |
| 123 | 130 | ||
| 124 | -private: | 131 | + private: |
| 125 | std::unordered_map<std::type_index, BaseTypePtr> data_; | 132 | std::unordered_map<std::type_index, BaseTypePtr> data_; |
| 126 | mutable std::mutex mutex_; | 133 | mutable std::mutex mutex_; |
| 127 | }; | 134 | }; |
| 128 | 135 | ||
| 129 | -} | 136 | +} // namespace Infra |
| 130 | 137 | ||
| 131 | -} | 138 | +} // namespace Analysis |
| 132 | 139 | ||
| 133 | -#endif | 140 | +#endif |
| @@ -16,19 +16,22 @@ | |||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | - | ||
| 20 | - | ||
| 21 | 19 | ||
| 20 | + | ||
| 22 | 21 | ||
| 22 | + | ||
| 23 | 23 | ||
| 24 | 24 | ||
| 25 | 25 | ||
| 26 | 26 | ||
| 27 | -namespace Analysis { | 27 | +namespace Analysis |
| 28 | +{ | ||
| 28 | 29 | ||
| 29 | -namespace Infra { | 30 | +namespace Infra |
| 31 | +{ | ||
| 30 | 32 | ||
| 31 | -struct ProcessStatistics { | 33 | +struct ProcessStatistics |
| 34 | +{ | ||
| 32 | std::string processName; // 以后升级到C++17或更高版本,可以使用std::string_view代替std::string | 35 | std::string processName; // 以后升级到C++17或更高版本,可以使用std::string_view代替std::string |
| 33 | std::vector<std::string> dependProcessNames; | 36 | std::vector<std::string> dependProcessNames; |
| 34 | uint32_t returnCode; | 37 | uint32_t returnCode; |
| @@ -38,27 +41,35 @@ struct ProcessStatistics { | |||
| 38 | bool dfxStop; // DFX需求:可以指定执行完哪个Process停止 | 41 | bool dfxStop; // DFX需求:可以指定执行完哪个Process停止 |
| 39 | }; | 42 | }; |
| 40 | 43 | ||
| 41 | -struct OneLevelStat { | 44 | +struct OneLevelStat |
| 45 | +{ | ||
| 42 | bool generalResult; | 46 | bool generalResult; |
| 43 | std::vector<ProcessStatistics> processStatistics; | 47 | std::vector<ProcessStatistics> processStatistics; |
| 44 | }; | 48 | }; |
| 45 | 49 | ||
| 46 | -struct ExecuteProcessStat { | 50 | +struct ExecuteProcessStat |
| 51 | +{ | ||
| 47 | uint32_t chipId; | 52 | uint32_t chipId; |
| 48 | std::vector<OneLevelStat> allLevelStat; | 53 | std::vector<OneLevelStat> allLevelStat; |
| 49 | }; | 54 | }; |
| 50 | 55 | ||
| 56 | +struct ProcessControlOptions | ||
| 57 | +{ | ||
| 58 | + bool releaseUnusedData = true; | ||
| 59 | + // 0 selects min(10, hardware_concurrency()). | ||
| 60 | + uint32_t maxWorkerThreads = 0; | ||
| 61 | +}; | ||
| 51 | 62 | ||
| 52 | void RecordProcessStat(const ExecuteProcessStat& stat, const std::string& subDir, std::string& log); | 63 | void RecordProcessStat(const ExecuteProcessStat& stat, const std::string& subDir, std::string& log); |
| 53 | 64 | ||
| 54 | - | ||
| 55 | /** | 65 | /** |
| 56 | * @brief 流程控制类 | 66 | * @brief 流程控制类 |
| 57 | * 本类用于控制用户通过Register注册的所有流程。支持同一个level并发运行,并提供一些DFX功能 | 67 | * 本类用于控制用户通过Register注册的所有流程。支持同一个level并发运行,并提供一些DFX功能 |
| 58 | */ | 68 | */ |
| 59 | -class ProcessControl final { | 69 | +class ProcessControl final |
| 60 | -public: | 70 | +{ |
| 61 | - explicit ProcessControl(ProcessCollection& processes); | 71 | + public: |
| 72 | + explicit ProcessControl(ProcessCollection& processes, ProcessControlOptions options = {}); | ||
| 62 | ~ProcessControl(); | 73 | ~ProcessControl(); |
| 63 | 74 | ||
| 64 | bool ExecuteProcess(DataInventory& dataInventory, const Context& context); | 75 | bool ExecuteProcess(DataInventory& dataInventory, const Context& context); |
| @@ -68,13 +79,13 @@ public: | |||
| 68 | 79 | ||
| 69 | bool VerifyProcess(const ProcessCollection& chipRelatedProcess) const; | 80 | bool VerifyProcess(const ProcessCollection& chipRelatedProcess) const; |
| 70 | 81 | ||
| 71 | -private: | 82 | + private: |
| 72 | class Impl; | 83 | class Impl; |
| 73 | std::unique_ptr<Impl> impl_; | 84 | std::unique_ptr<Impl> impl_; |
| 74 | }; | 85 | }; |
| 75 | 86 | ||
| 76 | -} | 87 | +} // namespace Infra |
| 77 | 88 | ||
| 78 | -} | 89 | +} // namespace Analysis |
| 79 | 90 | ||
| 80 | -#endif | 91 | +#endif |
| @@ -0,0 +1,38 @@ | |||
| 1 | +/* ------------------------------------------------------------------------- | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This file is part of the MindStudio project. | ||
| 4 | + * -------------------------------------------------------------------------*/ | ||
| 5 | + | ||
| 6 | + | ||
| 7 | + | ||
| 8 | + | ||
| 9 | + | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | +namespace Analysis | ||
| 17 | +{ | ||
| 18 | +namespace Application | ||
| 19 | +{ | ||
| 20 | +using TopoProcessCallback = std::function<bool(Infra::DataInventory&)>; | ||
| 21 | + | ||
| 22 | +class TopoCallbackProcess final : public Infra::Process | ||
| 23 | +{ | ||
| 24 | + public: | ||
| 25 | + explicit TopoCallbackProcess(TopoProcessCallback callback) : callback_(std::move(callback)) {} | ||
| 26 | + | ||
| 27 | + private: | ||
| 28 | + uint32_t ProcessEntry(Infra::DataInventory& dataInventory, const Infra::Context&) override | ||
| 29 | + { | ||
| 30 | + return callback_ != nullptr && callback_(dataInventory) ? ANALYSIS_OK : ANALYSIS_ERROR; | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + TopoProcessCallback callback_; | ||
| 34 | +}; | ||
| 35 | +} // namespace Application | ||
| 36 | +} // namespace Analysis | ||
| 37 | + | ||
| 38 | + | ||
| @@ -0,0 +1,212 @@ | |||
| 1 | +/* ------------------------------------------------------------------------- | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This file is part of the MindStudio project. | ||
| 4 | + * -------------------------------------------------------------------------*/ | ||
| 5 | + | ||
| 6 | + | ||
| 7 | + | ||
| 8 | + | ||
| 9 | + | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | +namespace Analysis | ||
| 25 | +{ | ||
| 26 | +namespace Application | ||
| 27 | +{ | ||
| 28 | +class DBAssembler; | ||
| 29 | +class TimelineManager; | ||
| 30 | +constexpr size_t MAX_TOPO_NODE_COUNT = 64; | ||
| 31 | + | ||
| 32 | +enum class TopoNodeStage : uint8_t | ||
| 33 | +{ | ||
| 34 | + DATA_PROCESSING, // Domain data processing. | ||
| 35 | + SUMMARY_GENERATION, // Application summary generation. | ||
| 36 | + DATABASE_PERSISTENCE, // Application database persistence. | ||
| 37 | + TIMELINE_EXPORT, // Application timeline export. | ||
| 38 | + FLOW_CONTROL, // Topology lifecycle control. | ||
| 39 | +}; | ||
| 40 | + | ||
| 41 | +struct TopoNodeId | ||
| 42 | +{ | ||
| 43 | + TopoNodeStage stage; | ||
| 44 | + std::string name; | ||
| 45 | + | ||
| 46 | + bool operator==(const TopoNodeId& other) const { return stage == other.stage && name == other.name; } | ||
| 47 | +}; | ||
| 48 | + | ||
| 49 | +struct TopoNodeIdHash | ||
| 50 | +{ | ||
| 51 | + size_t operator()(const TopoNodeId& id) const | ||
| 52 | + { | ||
| 53 | + return std::hash<uint8_t>()(static_cast<uint8_t>(id.stage)) ^ (std::hash<std::string>()(id.name) << 1U); | ||
| 54 | + } | ||
| 55 | +}; | ||
| 56 | + | ||
| 57 | +struct TopoBuildContext | ||
| 58 | +{ | ||
| 59 | + std::string profPath; | ||
| 60 | + std::string outputPath; | ||
| 61 | + std::vector<JsonProcess> timelineProcesses; | ||
| 62 | + std::shared_ptr<TimelineManager> timelineSession; | ||
| 63 | + std::shared_ptr<DBAssembler> dbSession; | ||
| 64 | +}; | ||
| 65 | + | ||
| 66 | +using TopoNodeCreatorFactory = std::function<Infra::ProcessCreator(const TopoBuildContext&)>; | ||
| 67 | +using TopoDependencyResolver = | ||
| 68 | + std::function<std::vector<TopoNodeId>(const TopoBuildContext&, const std::vector<TopoNodeId>&)>; | ||
| 69 | + | ||
| 70 | +struct TopoNodeDefinition | ||
| 71 | +{ | ||
| 72 | + TopoNodeId id; | ||
| 73 | + std::vector<TopoNodeId> processDependencies; | ||
| 74 | + std::vector<std::type_index> inputDataTypes; | ||
| 75 | + bool mandatory{false}; | ||
| 76 | + std::vector<uint32_t> chipIds; | ||
| 77 | + TopoNodeCreatorFactory creatorFactory; | ||
| 78 | + TopoDependencyResolver dependencyResolver; | ||
| 79 | + std::type_index runtimeType{typeid(void)}; | ||
| 80 | +}; | ||
| 81 | + | ||
| 82 | +using TopoNodeCollection = std::unordered_map<TopoNodeId, TopoNodeDefinition, TopoNodeIdHash>; | ||
| 83 | + | ||
| 84 | +class TopoNodeRegistry | ||
| 85 | +{ | ||
| 86 | + public: | ||
| 87 | + static bool Register(TopoNodeDefinition definition); | ||
| 88 | + static const TopoNodeCollection& GetDefinitions(); | ||
| 89 | + static const TopoNodeDefinition* Find(const TopoNodeId& id); | ||
| 90 | + static const TopoNodeDefinition* FindProcessorByName(const std::string& name); | ||
| 91 | + static const TopoNodeDefinition* FindProcessorByRuntimeType(std::type_index runtimeType); | ||
| 92 | + static TopoNodeCollection& MutableDefinitions(); | ||
| 93 | +}; | ||
| 94 | + | ||
| 95 | +class TopoNodeSequenceRegister | ||
| 96 | +{ | ||
| 97 | + public: | ||
| 98 | + TopoNodeSequenceRegister(TopoNodeId id, std::type_index runtimeType, bool mandatory, | ||
| 99 | + std::vector<TopoNodeId> dependencies, TopoNodeCreatorFactory creatorFactory, | ||
| 100 | + TopoDependencyResolver dependencyResolver = nullptr); | ||
| 101 | +}; | ||
| 102 | + | ||
| 103 | +class TopoNodeDataRegister | ||
| 104 | +{ | ||
| 105 | + public: | ||
| 106 | + TopoNodeDataRegister(TopoNodeId id, std::vector<std::type_index> inputDataTypes); | ||
| 107 | +}; | ||
| 108 | + | ||
| 109 | +template <typename... T> | ||
| 110 | +struct TopoNodeTypeIndexList | ||
| 111 | +{ | ||
| 112 | + TopoNodeTypeIndexList() : types{typeid(T)...} {} | ||
| 113 | + std::vector<std::type_index> types; | ||
| 114 | +}; | ||
| 115 | + | ||
| 116 | +class TopoGraphBuilder | ||
| 117 | +{ | ||
| 118 | + public: | ||
| 119 | + bool Build(const TopoBuildContext& context, const std::vector<TopoNodeId>& roots, | ||
| 120 | + Infra::ProcessCollection& processes); | ||
| 121 | + | ||
| 122 | + private: | ||
| 123 | + bool AddNode(const TopoNodeId& id, std::type_index& key); | ||
| 124 | + bool ResolveDependencies(const TopoNodeDefinition& definition, std::vector<std::type_index>& dependencies); | ||
| 125 | + std::type_index AllocateSyntheticKey(TopoNodeStage stage); | ||
| 126 | + | ||
| 127 | + private: | ||
| 128 | + const TopoBuildContext* context_{}; | ||
| 129 | + const std::vector<TopoNodeId>* roots_{}; | ||
| 130 | + Infra::ProcessCollection* processes_{}; | ||
| 131 | + std::unordered_map<TopoNodeId, std::type_index, TopoNodeIdHash> nodeKeys_; | ||
| 132 | + std::unordered_map<TopoNodeStage, size_t> nextSyntheticIndex_; | ||
| 133 | + std::unordered_map<TopoNodeId, bool, TopoNodeIdHash> visiting_; | ||
| 134 | +}; | ||
| 135 | +} // namespace Application | ||
| 136 | +} // namespace Analysis | ||
| 137 | + | ||
| 138 | +/** | ||
| 139 | + * | ||
| 140 | + * TOPO_NODE(stage, name) | ||
| 141 | + * @param stage 节点所属业务阶段,取值为 TopoNodeStage 枚举值。 | ||
| 142 | + * 例如 DATA_PROCESSING、SUMMARY_GENERATION、 | ||
| 143 | + * DATABASE_PERSISTENCE、TIMELINE_EXPORT、FLOW_CONTROL。 | ||
| 144 | + * @param name 阶段内稳定且唯一的业务节点名称。相同 stage 与 name | ||
| 145 | + * 共同组成 TopoNodeId,必须与依赖节点及数据注册中的节点标识保持一致。 | ||
| 146 | + * | ||
| 147 | + * TOPO_DEPS(...) | ||
| 148 | + * @param ... 零个或多个由 TOPO_NODE(...) 构造的前置依赖节点。 | ||
| 149 | + * 调度器会先执行全部依赖节点,再执行当前节点;依赖节点必须已注册, | ||
| 150 | + * 且依赖关系不能形成环。无依赖时使用 TOPO_DEPS()。 | ||
| 151 | + * | ||
| 152 | + * REGISTER_TOPO_NODE_SEQUENCE(RuntimeType, NodeId, Mandatory, CreatorFactory, | ||
| 153 | + * Dependencies, Resolver) | ||
| 154 | + * @param RuntimeType DATA_PROCESSING 阶段节点对应具体处理器类型, | ||
| 155 | + * 使用 typeid(ProcessorType);其余阶段节点使用 typeid(void), | ||
| 156 | + * 由拓扑构建器生成 synthetic key。 | ||
| 157 | + * @param NodeId 当前节点标识,使用 TOPO_NODE(stage, name) 构造。 | ||
| 158 | + * @param Mandatory 是否为必需节点。true 表示节点执行失败会导致本次流程失败; | ||
| 159 | + * false 表示该节点失败后流程可继续执行。 | ||
| 160 | + * @param CreatorFactory 节点创建工厂,接收 TopoBuildContext 并返回 ProcessCreator。 | ||
| 161 | + * 工厂或其创建的 Process 为空时,节点构建失败。 | ||
| 162 | + * @param Dependencies 静态依赖列表,使用 TOPO_DEPS(...) 构造。 | ||
| 163 | + * @param Resolver 可选动态依赖解析器;根据 TopoBuildContext 和根节点列表 | ||
| 164 | + * 补充依赖。没有动态依赖时传入 nullptr。 | ||
| 165 | + * | ||
| 166 | + * REGISTER_TOPO_NODE_DEPENDENT_DATA(NodeId, ...) | ||
| 167 | + * @param NodeId 当前节点标识,必须与 REGISTER_TOPO_NODE_SEQUENCE 的 NodeId 完全一致。 | ||
| 168 | + * @param ... 节点从 DataInventory 读取的输入数据类型,例如 | ||
| 169 | + * std::vector<TaskInfoData>。类型必须与生产节点写入的类型一致。 | ||
| 170 | + * 该宏必须定义在同一节点的 REGISTER_TOPO_NODE_SEQUENCE 之后。 | ||
| 171 | + * | ||
| 172 | + * 示例:注册一个时间线导出节点。它依赖时间线预处理和任务数据处理, | ||
| 173 | + * 并声明运行时从 DataInventory 读取的输入类型。 | ||
| 174 | + * | ||
| 175 | + * REGISTER_TOPO_NODE_SEQUENCE( | ||
| 176 | + * typeid(void), | ||
| 177 | + * TOPO_NODE(TIMELINE_EXPORT, PROCESS_TASK), | ||
| 178 | + * true, | ||
| 179 | + * TimelineManager::CreateTimelineAssembler(PROCESS_TASK), | ||
| 180 | + * TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP), | ||
| 181 | + * TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_TASK)), | ||
| 182 | + * nullptr); | ||
| 183 | + * | ||
| 184 | + * REGISTER_TOPO_NODE_DEPENDENT_DATA( | ||
| 185 | + * TOPO_NODE(TIMELINE_EXPORT, PROCESS_TASK), | ||
| 186 | + * std::vector<TaskInfoData>, | ||
| 187 | + * std::vector<AscendTaskData>); | ||
| 188 | + */ | ||
| 189 | + | ||
| 190 | + | ||
W [review] 这里新增了较多的宏定义内容,对于宏定义方法来说,本身的可理解性相比一般业务代码会差。这里建议增加相关宏定义的介绍和示例说明。方便后续维护整体业务。避免相关宏在演进过程中逐渐丢失。 ![]() ![]() | |||
| 191 | + | ||
| 192 | + | ||
| 193 | + | ||
| 194 | + | ||
| 195 | + | ||
| 196 | + | ||
| 197 | + REGISTER_TOPO_NODE_SEQUENCE_IMPL(RuntimeType, NodeId, Mandatory, CreatorFactory, Dependencies, Resolver, __LINE__) | ||
| 198 | + | ||
| 199 | + | ||
| 200 | + static Analysis::Application::TopoNodeSequenceRegister TOPO_NODE_REGISTER_CONCAT(topoNodeSequenceRegister, line)( \ | ||
| 201 | + NodeId, RuntimeType, Mandatory, Dependencies, CreatorFactory, Resolver) | ||
| 202 | + | ||
| 203 | + | ||
| 204 | + REGISTER_TOPO_NODE_DEPENDENT_DATA_IMPL(NodeId, __LINE__, __VA_ARGS__) | ||
| 205 | + | ||
| 206 | + | ||
| 207 | + static Analysis::Application::TopoNodeTypeIndexList<__VA_ARGS__> TOPO_NODE_REGISTER_CONCAT(topoNodeDataHelper, \ | ||
| 208 | + line); \ | ||
| 209 | + static Analysis::Application::TopoNodeDataRegister TOPO_NODE_REGISTER_CONCAT(topoNodeDataRegister, line)( \ | ||
| 210 | + NodeId, std::move(TOPO_NODE_REGISTER_CONCAT(topoNodeDataHelper, line).types)) | ||
| 211 | + | ||
| 212 | + | ||
| @@ -14,24 +14,38 @@ | |||
| 14 | * See the Mulan PSL v2 for more details. | 14 | * See the Mulan PSL v2 for more details. |
| 15 | * -------------------------------------------------------------------------*/ | 15 | * -------------------------------------------------------------------------*/ |
| 16 | 16 | ||
| 17 | + | ||
| 17 | 18 | ||
| 18 | - | ||
| 19 | 19 | ||
| 20 | -#include <sstream> | 20 | +#include <condition_variable> |
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 21 | 24 | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | + | ||
| 22 | 31 | ||
| 23 | 32 | ||
| 24 | -namespace Analysis { | 33 | +namespace Analysis |
| 34 | +{ | ||
| 25 | 35 | ||
| 26 | -namespace Infra { | 36 | +namespace Infra |
| 27 | -namespace { | 37 | +{ |
| 38 | +namespace | ||
| 39 | +{ | ||
| 28 | 40 | ||
| 29 | void GetDepProcessNames(const RegProcessInfo& procInfo, const ProcessCollection& allRegProcess, | 41 | void GetDepProcessNames(const RegProcessInfo& procInfo, const ProcessCollection& allRegProcess, |
| 30 | std::vector<std::string>& depProcNames) | 42 | std::vector<std::string>& depProcNames) |
| 31 | { | 43 | { |
| 32 | - for (const auto& typeIndex : procInfo.processDependence) { | 44 | + for (const auto& typeIndex : procInfo.processDependence) |
| 45 | + { | ||
| 33 | auto it = allRegProcess.find(typeIndex); | 46 | auto it = allRegProcess.find(typeIndex); |
| 34 | - if (it == allRegProcess.end()) { | 47 | + if (it == allRegProcess.end()) |
| 48 | + { | ||
| 35 | continue; | 49 | continue; |
| 36 | } | 50 | } |
| 37 | depProcNames.emplace_back(it->second.processName); | 51 | depProcNames.emplace_back(it->second.processName); |
| @@ -40,28 +54,36 @@ void GetDepProcessNames(const RegProcessInfo& procInfo, const ProcessCollection& | |||
| 40 | 54 | ||
| 41 | void FillStatisticianDependence(const ProcessCollection& regProcess, std::vector<ProcessStatistics>& stat) | 55 | void FillStatisticianDependence(const ProcessCollection& regProcess, std::vector<ProcessStatistics>& stat) |
| 42 | { | 56 | { |
| 43 | - for (auto& node : stat) { | 57 | + for (auto& node : stat) |
| 44 | - for (const auto& regPair : regProcess) { | 58 | + { |
| 45 | - if (node.processName == regPair.second.processName) { | 59 | + for (const auto& regPair : regProcess) |
| 60 | + { | ||
| 61 | + if (node.processName == regPair.second.processName) | ||
| 62 | + { | ||
| 46 | GetDepProcessNames(regPair.second, regProcess, node.dependProcessNames); | 63 | GetDepProcessNames(regPair.second, regProcess, node.dependProcessNames); |
| 47 | } | 64 | } |
| 48 | } | 65 | } |
| 49 | } | 66 | } |
| 50 | } | 67 | } |
| 51 | 68 | ||
| 52 | -} | 69 | +} // namespace |
| 53 | 70 | ||
| 54 | -class ProcessControl::Impl final { | 71 | +class ProcessControl::Impl final |
| 55 | -public: | 72 | +{ |
| 56 | - explicit Impl(ProcessCollection& processes) | 73 | + public: |
| 57 | - : allProcess_(std::move(processes)) { stat_.chipId = 0; } | 74 | + explicit Impl(ProcessCollection& processes, ProcessControlOptions options) |
| 75 | + : allProcess_(std::move(processes)), options_(options) | ||
| 76 | + { | ||
| 77 | + stat_.chipId = 0; | ||
| 78 | + } | ||
| 58 | ~Impl() = default; | 79 | ~Impl() = default; |
| 59 | 80 | ||
| 60 | bool VerifyProcess(const ProcessCollection& chipRelatedProcess) const | 81 | bool VerifyProcess(const ProcessCollection& chipRelatedProcess) const |
| 61 | { | 82 | { |
| 62 | auto verifyProcess = chipRelatedProcess; | 83 | auto verifyProcess = chipRelatedProcess; |
| 63 | auto preparedProcess = TakeAwayPreparedProcess(verifyProcess); | 84 | auto preparedProcess = TakeAwayPreparedProcess(verifyProcess); |
| 64 | - while (!preparedProcess.empty()) { | 85 | + while (!preparedProcess.empty()) |
| 86 | + { | ||
| 65 | preparedProcess = TakeAwayPreparedProcess(verifyProcess); | 87 | preparedProcess = TakeAwayPreparedProcess(verifyProcess); |
| 66 | } | 88 | } |
| 67 | return verifyProcess.empty(); | 89 | return verifyProcess.empty(); |
| @@ -74,7 +96,8 @@ public: | |||
| 74 | 96 | ||
| 75 | ProcessTopo processTopoBuilder(allProcess_); | 97 | ProcessTopo processTopoBuilder(allProcess_); |
| 76 | auto chipRelatedProcess = processTopoBuilder.BuildProcessControlTopoByChip(chipId_); | 98 | auto chipRelatedProcess = processTopoBuilder.BuildProcessControlTopoByChip(chipId_); |
| 77 | - if (!VerifyProcess(chipRelatedProcess)) { | 99 | + if (!VerifyProcess(chipRelatedProcess)) |
| 100 | + { | ||
| 78 | ERROR("Topo Verify failed!"); | 101 | ERROR("Topo Verify failed!"); |
| 79 | return false; | 102 | return false; |
| 80 | } | 103 | } |
| @@ -82,111 +105,226 @@ public: | |||
| 82 | return RunProcesses(chipRelatedProcess, dataInventory, context); | 105 | return RunProcesses(chipRelatedProcess, dataInventory, context); |
| 83 | } | 106 | } |
| 84 | 107 | ||
| 85 | - ExecuteProcessStat GetExecuteStat() const | 108 | + ExecuteProcessStat GetExecuteStat() const { return stat_; } |
| 86 | - { | ||
| 87 | - return stat_; | ||
| 88 | - } | ||
| 89 | 109 | ||
| 90 | -private: | 110 | + private: |
| 91 | /** | 111 | /** |
| 92 | * @brief 拓扑排序算法执行所有Process 使用的算法为卡恩算法 | 112 | * @brief 拓扑排序算法执行所有Process 使用的算法为卡恩算法 |
| 93 | * @param chipRelatedProcess 相应Chip的Process集合 | 113 | * @param chipRelatedProcess 相应Chip的Process集合 |
| 94 | */ | 114 | */ |
| 95 | - bool RunProcesses(ProcessCollection& chipRelatedProcess, DataInventory& dataInventory, | 115 | + bool RunProcesses(ProcessCollection& chipRelatedProcess, DataInventory& dataInventory, const Context& context) |
| 96 | - const Context& context) | ||
| 97 | { | 116 | { |
| 98 | - auto regProcessCopy = chipRelatedProcess; // 这里COPY一份是为了DFX中填dependProcess字段 | 117 | + const ProcessCollection regProcessCopy = chipRelatedProcess; |
| 118 | + if (chipRelatedProcess.empty()) | ||
| 119 | + { | ||
| 120 | + return true; | ||
| 121 | + } | ||
| 99 | 122 | ||
| 100 | - size_t levelIndex = 0; | 123 | + using ProcessKey = std::type_index; |
| 101 | - auto preparedProcess = TakeAwayPreparedProcess(chipRelatedProcess); | 124 | + struct CompletedProcess |
| 102 | - while (!preparedProcess.empty()) { | 125 | + { |
| 103 | - std::vector<ProcessStatistics> stat(preparedProcess.size()); | 126 | + ProcessKey key; |
| 104 | - Analysis::Utils::ThreadPool pool(preparedProcess.size()); | 127 | + size_t level; |
| 105 | - pool.Start(); | 128 | + ProcessStatistics statistics; |
| 106 | - RunPreparedProcess(preparedProcess, stat, pool, dataInventory, context); | 129 | + }; |
| 107 | - pool.WaitAllTasks(); | ||
| 108 | - pool.Stop(); | ||
| 109 | 130 | ||
| 110 | - // DFX | 131 | + std::unordered_map<ProcessKey, size_t> unresolvedDependencies; |
| 111 | - FillStatisticianDependence(regProcessCopy, stat); | 132 | + std::unordered_map<ProcessKey, std::vector<ProcessKey>> dependents; |
| 133 | + std::unordered_map<ProcessKey, size_t> levels; | ||
| 134 | + std::vector<ProcessKey> readyProcesses; | ||
| 135 | + for (const auto& processPair : chipRelatedProcess) | ||
| 136 | + { | ||
| 137 | + const ProcessKey& key = processPair.first; | ||
| 138 | + unresolvedDependencies.emplace(key, processPair.second.processDependence.size()); | ||
| 139 | + levels.emplace(key, 0UL); | ||
| 140 | + if (processPair.second.processDependence.empty()) | ||
| 141 | + { | ||
| 142 | + readyProcesses.emplace_back(key); | ||
| 143 | + } | ||
| 144 | + for (const auto& dependency : processPair.second.processDependence) | ||
| 145 | + { | ||
| 146 | + dependents[dependency].emplace_back(key); | ||
| 147 | + } | ||
| 148 | + } | ||
| 149 | + | ||
| 150 | + const uint32_t hardwareWorkerCount = std::thread::hardware_concurrency(); | ||
| 151 | + const uint32_t defaultWorkerCount = hardwareWorkerCount == 0 ? 10U : std::min(10U, hardwareWorkerCount); | ||
| 152 | + const uint32_t configuredWorkerCount = | ||
| 153 | + options_.maxWorkerThreads == 0 ? defaultWorkerCount : options_.maxWorkerThreads; | ||
| 154 | + const uint32_t workerCount = | ||
| 155 | + std::max(1U, std::min(configuredWorkerCount, static_cast<uint32_t>(chipRelatedProcess.size()))); | ||
| 156 | + Analysis::Utils::ThreadPool pool(workerCount); | ||
| 157 | + if (!pool.Start()) | ||
| 158 | + { | ||
| 159 | + ERROR("Start process worker pool failed."); | ||
| 160 | + return false; | ||
| 161 | + } | ||
| 162 | + | ||
| 163 | + std::mutex schedulerMutex; | ||
| 164 | + std::condition_variable schedulerDone; | ||
| 165 | + ProcessCollection remainingProcesses = chipRelatedProcess; | ||
| 166 | + std::vector<CompletedProcess> completedProcesses; | ||
| 167 | + size_t activeTaskCount = 0; | ||
| 168 | + size_t completedTaskCount = 0; | ||
| 169 | + size_t releaseIndex = 0; | ||
| 170 | + bool stopScheduling = false; | ||
| 171 | + | ||
| 172 | + std::function<void(const ProcessKey&)> schedule; | ||
| 173 | + schedule = [&](const ProcessKey& key) | ||
| 174 | + { | ||
| 175 | + const auto processIter = chipRelatedProcess.find(key); | ||
| 176 | + if (processIter == chipRelatedProcess.end()) | ||
| 177 | + { | ||
| 178 | + ERROR("Scheduled process is not registered."); | ||
| 179 | + stopScheduling = true; | ||
| 180 | + return; | ||
| 181 | + } | ||
| 182 | + ++activeTaskCount; | ||
| 183 | + const RegProcessInfo processInfo = processIter->second; | ||
| 184 | + const size_t level = levels.at(key); | ||
| 185 | + pool.AddTask( | ||
| 186 | + [&, key, level, processInfo]() | ||
| 187 | + { | ||
| 188 | + ProcessStatistics statistics{}; | ||
| 189 | + const auto startTime = std::chrono::steady_clock::now(); | ||
| 190 | + if (!processInfo.creator) | ||
| 191 | + { | ||
| 192 | + ERROR("creator==nullptr, process name: %", processInfo.processName); | ||
| 193 | + } | ||
| 194 | + else | ||
| 195 | + { | ||
| 196 | + try | ||
| 197 | + { | ||
| 198 | + auto proc = processInfo.creator(); | ||
| 199 | + if (proc != nullptr) | ||
| 200 | + { | ||
| 201 | + statistics.returnCode = proc->Run(dataInventory, context); | ||
| 202 | + statistics.mandatory = processInfo.mandatory; | ||
| 203 | + } | ||
| 204 | + } | ||
| 205 | + catch (const std::exception& exception) | ||
| 206 | + { | ||
| 207 | + ERROR("Process % threw an exception: %", processInfo.processName, exception.what()); | ||
| 208 | + statistics.returnCode = ANALYSIS_ERROR; | ||
| 209 | + statistics.mandatory = processInfo.mandatory; | ||
| 210 | + } | ||
| 211 | + catch (...) | ||
| 212 | + { | ||
| 213 | + ERROR("Process % threw an unknown exception.", processInfo.processName); | ||
| 214 | + statistics.returnCode = ANALYSIS_ERROR; | ||
| 215 | + statistics.mandatory = processInfo.mandatory; | ||
| 216 | + } | ||
| 217 | + } | ||
| 218 | + const auto endTime = std::chrono::steady_clock::now(); | ||
| 219 | + statistics.startTime = | ||
| 220 | + std::chrono::duration_cast<std::chrono::microseconds>(startTime.time_since_epoch()).count(); | ||
| 221 | + statistics.duration = | ||
| 222 | + std::chrono::duration_cast<std::chrono::microseconds>(endTime - startTime).count(); | ||
| 223 | + statistics.processName = processInfo.processName; | ||
| 224 | + const std::string& stopProcessName = context.GetDfxStopAtName(); | ||
| 225 | + statistics.dfxStop = !stopProcessName.empty() && stopProcessName == processInfo.processName; | ||
| 226 | + | ||
| 227 | + std::unique_lock<std::mutex> lock(schedulerMutex); | ||
| 228 | + --activeTaskCount; | ||
| 229 | + ++completedTaskCount; | ||
| 230 | + completedProcesses.push_back({key, level, std::move(statistics)}); | ||
| 231 | + const ProcessStatistics& completedStat = completedProcesses.back().statistics; | ||
| 232 | + remainingProcesses.erase(key); | ||
| 233 | + if (options_.releaseUnusedData) | ||
| 234 | + { | ||
| 235 | + ReleaseNoLongerUsedData(remainingProcesses, dataInventory, releaseIndex++); | ||
| 236 | + } | ||
| 237 | + | ||
| 238 | + if ((completedStat.returnCode != ANALYSIS_OK && completedStat.mandatory) || completedStat.dfxStop) | ||
| 239 | + { | ||
| 240 | + stopScheduling = true; | ||
| 241 | + } | ||
| 242 | + if (!stopScheduling) | ||
| 243 | + { | ||
| 244 | + const auto dependentIter = dependents.find(key); | ||
| 245 | + if (dependentIter != dependents.end()) | ||
| 246 | + { | ||
| 247 | + for (const auto& dependent : dependentIter->second) | ||
| 248 | + { | ||
| 249 | + size_t& pendingCount = unresolvedDependencies.at(dependent); | ||
| 250 | + levels.at(dependent) = std::max(levels.at(dependent), level + 1); | ||
| 251 | + if (--pendingCount == 0) | ||
| 252 | + { | ||
| 253 | + schedule(dependent); | ||
| 254 | + } | ||
| 255 | + } | ||
| 256 | + } | ||
| 257 | + } | ||
| 258 | + schedulerDone.notify_all(); | ||
| 259 | + }); | ||
| 260 | + }; | ||
| 261 | + | ||
| 262 | + { | ||
| 263 | + std::unique_lock<std::mutex> lock(schedulerMutex); | ||
| 264 | + for (const auto& readyProcess : readyProcesses) | ||
| 265 | + { | ||
| 266 | + schedule(readyProcess); | ||
| 267 | + } | ||
| 268 | + } | ||
| 269 | + { | ||
| 270 | + std::unique_lock<std::mutex> lock(schedulerMutex); | ||
| 271 | + schedulerDone.wait(lock, | ||
| 272 | + [&]() { | ||
| 273 | + return activeTaskCount == 0 && | ||
| 274 | + (stopScheduling || completedTaskCount == chipRelatedProcess.size()); | ||
| 275 | + }); | ||
| 276 | + } | ||
| 277 | + pool.Stop(); | ||
| 278 | + | ||
| 279 | + std::map<size_t, std::vector<ProcessStatistics>> statisticsByLevel; | ||
| 280 | + for (auto& completed : completedProcesses) | ||
| 281 | + { | ||
| 282 | + statisticsByLevel[completed.level].emplace_back(std::move(completed.statistics)); | ||
| 283 | + } | ||
| 284 | + bool overallResult = !stopScheduling; | ||
| 285 | + for (auto& levelStatistics : statisticsByLevel) | ||
| 286 | + { | ||
| 287 | + FillStatisticianDependence(regProcessCopy, levelStatistics.second); | ||
| 112 | bool dfxStop = false; | 288 | bool dfxStop = false; |
| 113 | - auto ret = GetStatistician(std::move(stat), dfxStop); | 289 | + const bool levelResult = GetStatistician(std::move(levelStatistics.second), dfxStop); |
| 114 | - if (!ret) { | 290 | + overallResult = overallResult && levelResult && !dfxStop; |
| 115 | - WARN("mandatory process failed!"); | ||
| 116 | - return false; | ||
| 117 | - } | ||
| 118 | - if (dfxStop) { | ||
| 119 | - PRINT_INFO("!!!!!!! DFX Stops !!!!!!!!"); | ||
| 120 | - return false; | ||
| 121 | - } | ||
| 122 | - ReleaseNoLongerUsedData(chipRelatedProcess, dataInventory, levelIndex++); | ||
| 123 | - preparedProcess = TakeAwayPreparedProcess(chipRelatedProcess); | ||
| 124 | } | 291 | } |
| 125 | - return true; | 292 | + if (stopScheduling) |
| 126 | - } | 293 | + { |
| 127 | - | 294 | + PRINT_INFO("!!!!!!! DFX Stops or a mandatory process failed !!!!!!!!"); |
| 128 | - void RunPreparedProcess(ProcessCollection &preparedProcess, std::vector<ProcessStatistics> &stat, | ||
| 129 | - Analysis::Utils::ThreadPool &pool, DataInventory& dataInventory, | ||
| 130 | - const Context& context) const | ||
| 131 | - { | ||
| 132 | - size_t concurrentIndex{}; | ||
| 133 | - for (const auto& processNode : preparedProcess) { | ||
| 134 | - pool.AddTask([&processNode, &stat, &dataInventory, &context, concurrentIndex]() { | ||
| 135 | - auto startTime = std::chrono::steady_clock::now(); | ||
| 136 | - if (!processNode.second.creator) { | ||
| 137 | - ERROR("creator==nullptr, process name: %", processNode.second.processName); | ||
| 138 | - return; | ||
| 139 | - } | ||
| 140 | - auto proc = processNode.second.creator(); | ||
| 141 | - if (proc != nullptr) { | ||
| 142 | - stat[concurrentIndex].returnCode = proc->Run(dataInventory, context); | ||
| 143 | - stat[concurrentIndex].mandatory = processNode.second.mandatory; | ||
| 144 | - } | ||
| 145 | - auto endTime = std::chrono::steady_clock::now(); | ||
| 146 | - | ||
| 147 | - stat[concurrentIndex].startTime = std::chrono::duration_cast<std::chrono::microseconds>( | ||
| 148 | - startTime.time_since_epoch()).count(); | ||
| 149 | - stat[concurrentIndex].duration = std::chrono::duration_cast<std::chrono::microseconds>( | ||
| 150 | - endTime - startTime).count(); | ||
| 151 | - stat[concurrentIndex].processName = processNode.second.processName; | ||
| 152 | - stat[concurrentIndex].dfxStop = false; | ||
| 153 | - const std::string& stopProcessName = context.GetDfxStopAtName(); | ||
| 154 | - if (!stopProcessName.empty() && stopProcessName == processNode.second.processName) { | ||
| 155 | - stat[concurrentIndex].dfxStop = true; | ||
| 156 | - } | ||
| 157 | - }); | ||
| 158 | - ++concurrentIndex; | ||
| 159 | } | 295 | } |
| 296 | + return overallResult && completedTaskCount == chipRelatedProcess.size(); | ||
| 160 | } | 297 | } |
| 161 | 298 | ||
| 162 | bool GetStatistician(std::vector<ProcessStatistics>&& statistics, bool& dfxStop) | 299 | bool GetStatistician(std::vector<ProcessStatistics>&& statistics, bool& dfxStop) |
| 163 | { | 300 | { |
| 164 | - auto generalResult = std::all_of(statistics.begin(), statistics.end(), [](ProcessStatistics& node) { | 301 | + auto generalResult = std::all_of(statistics.begin(), statistics.end(), [](ProcessStatistics& node) |
| 165 | - return (node.returnCode == 0 || !node.mandatory); | 302 | + { return (node.returnCode == 0 || !node.mandatory); }); |
| 166 | - }); | 303 | + dfxStop = |
| 167 | - dfxStop = std::any_of(statistics.begin(), statistics.end(), [](ProcessStatistics& node) { | 304 | + std::any_of(statistics.begin(), statistics.end(), [](ProcessStatistics& node) { return node.dfxStop; }); |
| 168 | - return node.dfxStop; | ||
| 169 | - }); | ||
| 170 | stat_.allLevelStat.emplace_back(); | 305 | stat_.allLevelStat.emplace_back(); |
| 171 | auto& oneLevelStat = stat_.allLevelStat.back(); | 306 | auto& oneLevelStat = stat_.allLevelStat.back(); |
| 172 | oneLevelStat.generalResult = generalResult; | 307 | oneLevelStat.generalResult = generalResult; |
| 173 | oneLevelStat.processStatistics = std::move(statistics); | 308 | oneLevelStat.processStatistics = std::move(statistics); |
| 174 | - return generalResult; // Stop on error 这里是否停止还与Process类注册时,注册宏中mandatory字段确定 | 309 | + return generalResult; // Stop on error 这里是否停止还与Process类注册时,注册宏中mandatory字段确定 |
| 175 | } | 310 | } |
| 176 | 311 | ||
| 177 | void ReleaseNoLongerUsedData(const ProcessCollection& chipRelatedProcess, DataInventory& dataInventory, | 312 | void ReleaseNoLongerUsedData(const ProcessCollection& chipRelatedProcess, DataInventory& dataInventory, |
| 178 | size_t levelIndex) | 313 | size_t levelIndex) |
| 179 | { | 314 | { |
| 180 | std::set<std::type_index> dataTobeUsing; | 315 | std::set<std::type_index> dataTobeUsing; |
| 181 | - for (const auto& processInfo : chipRelatedProcess) { | 316 | + for (const auto& processInfo : chipRelatedProcess) |
| 182 | - for (const auto& dataType : processInfo.second.paramTypes) { | 317 | + { |
| 318 | + for (const auto& dataType : processInfo.second.paramTypes) | ||
| 319 | + { | ||
| 183 | dataTobeUsing.insert(dataType); | 320 | dataTobeUsing.insert(dataType); |
| 184 | } | 321 | } |
| 185 | } | 322 | } |
| 186 | auto removedTypes = dataInventory.RemoveRestData(dataTobeUsing); | 323 | auto removedTypes = dataInventory.RemoveRestData(dataTobeUsing); |
| 187 | 324 | ||
| 188 | std::string typeStr; | 325 | std::string typeStr; |
| 189 | - for (const auto& typeInfo : removedTypes) { | 326 | + for (const auto& typeInfo : removedTypes) |
| 327 | + { | ||
| 190 | typeStr += typeInfo.name(); | 328 | typeStr += typeInfo.name(); |
| 191 | typeStr += " "; | 329 | typeStr += " "; |
| 192 | } | 330 | } |
| @@ -197,8 +335,10 @@ private: | |||
| 197 | { | 335 | { |
| 198 | ProcessCollection preparedProcess; | 336 | ProcessCollection preparedProcess; |
| 199 | // 先拿走已经没有前向依赖的,即入度为0的节点 | 337 | // 先拿走已经没有前向依赖的,即入度为0的节点 |
| 200 | - for (auto it = chipRelatedProcess.begin(); it != chipRelatedProcess.end();) { | 338 | + for (auto it = chipRelatedProcess.begin(); it != chipRelatedProcess.end();) |
| 201 | - if (it->second.processDependence.empty()) { | 339 | + { |
| 340 | + if (it->second.processDependence.empty()) | ||
| 341 | + { | ||
| 202 | preparedProcess.insert({it->first, it->second}); | 342 | preparedProcess.insert({it->first, it->second}); |
| 203 | it = chipRelatedProcess.erase(it); | 343 | it = chipRelatedProcess.erase(it); |
| 204 | continue; | 344 | continue; |
| @@ -207,9 +347,11 @@ private: | |||
| 207 | } | 347 | } |
| 208 | 348 | ||
| 209 | // 再将其它节点中的前向依赖删除,即修正其它节点的入度 | 349 | // 再将其它节点中的前向依赖删除,即修正其它节点的入度 |
| 210 | - for (auto& process : chipRelatedProcess) { | 350 | + for (auto& process : chipRelatedProcess) |
| 351 | + { | ||
| 211 | auto& processDep = process.second.processDependence; | 352 | auto& processDep = process.second.processDependence; |
| 212 | - for (const auto& preparedNode : preparedProcess) { | 353 | + for (const auto& preparedNode : preparedProcess) |
| 354 | + { | ||
| 213 | processDep.erase(std::remove(processDep.begin(), processDep.end(), preparedNode.first), | 355 | processDep.erase(std::remove(processDep.begin(), processDep.end(), preparedNode.first), |
| 214 | processDep.end()); | 356 | processDep.end()); |
| 215 | } | 357 | } |
| @@ -217,10 +359,11 @@ private: | |||
| 217 | return preparedProcess; | 359 | return preparedProcess; |
| 218 | } | 360 | } |
| 219 | 361 | ||
| 220 | -private: | 362 | + private: |
| 221 | ProcessCollection allProcess_; | 363 | ProcessCollection allProcess_; |
| 364 | + ProcessControlOptions options_; | ||
| 222 | ExecuteProcessStat stat_; // dfx: 统计运行结果 | 365 | ExecuteProcessStat stat_; // dfx: 统计运行结果 |
| 223 | - uint32_t chipId_{}; // dfx: 记录运行什么芯片ID | 366 | + uint32_t chipId_{}; // dfx: 记录运行什么芯片ID |
| 224 | }; | 367 | }; |
| 225 | 368 | ||
| 226 | void RecordProcessStat(const ExecuteProcessStat& stat, const std::string& subDir, std::string& log) | 369 | void RecordProcessStat(const ExecuteProcessStat& stat, const std::string& subDir, std::string& log) |
| @@ -232,36 +375,41 @@ void RecordProcessStat(const ExecuteProcessStat& stat, const std::string& subDir | |||
| 232 | 375 | ||
| 233 | auto levelCount = stat.allLevelStat.size(); | 376 | auto levelCount = stat.allLevelStat.size(); |
| 234 | ss << "chip id: " << stat.chipId << ", process levels:" << levelCount << std::endl; | 377 | ss << "chip id: " << stat.chipId << ", process levels:" << levelCount << std::endl; |
| 235 | - for (size_t i = 0; i < levelCount; ++i) { | 378 | + for (size_t i = 0; i < levelCount; ++i) |
| 379 | + { | ||
| 236 | const auto& node = stat.allLevelStat[i]; | 380 | const auto& node = stat.allLevelStat[i]; |
| 237 | ss << "-------------------------------------------------------------------------------" << std::endl; | 381 | ss << "-------------------------------------------------------------------------------" << std::endl; |
| 238 | ss << "level[" << i << "] generalResult:" << std::boolalpha << node.generalResult << std::noboolalpha | 382 | ss << "level[" << i << "] generalResult:" << std::boolalpha << node.generalResult << std::noboolalpha |
| 239 | - << ", process num:" << node.processStatistics.size() << std::endl; | 383 | + << ", process num:" << node.processStatistics.size() << std::endl; |
| 240 | size_t j = 0; | 384 | size_t j = 0; |
| 241 | - for (const auto& proc : node.processStatistics) { | 385 | + for (const auto& proc : node.processStatistics) |
| 242 | - ss << "\tprocess" << j++ << "[" << proc.processName << "]:" << "return: 0x" | 386 | + { |
| 243 | - << std::hex << proc.returnCode << std::dec << ", mandatory:" | 387 | + ss << "\tprocess" << j++ << "[" << proc.processName << "]:" << "return: 0x" << std::hex << proc.returnCode |
| 244 | - << std::boolalpha << proc.mandatory << std::noboolalpha << std::endl; | 388 | + << std::dec << ", mandatory:" << std::boolalpha << proc.mandatory << std::noboolalpha << std::endl; |
| 245 | ss << "\t\tdependProcessNames: "; | 389 | ss << "\t\tdependProcessNames: "; |
| 246 | - for (const auto& depName : proc.dependProcessNames) { | 390 | + for (const auto& depName : proc.dependProcessNames) |
| 391 | + { | ||
| 247 | ss << depName << ", "; | 392 | ss << depName << ", "; |
| 248 | } | 393 | } |
| 249 | - ss << std::endl << "\t\tstartTime:" << proc.startTime << " us, duration: " | 394 | + ss << std::endl |
| 250 | - << proc.duration << " us" << std::endl; | 395 | + << "\t\tstartTime:" << proc.startTime << " us, duration: " << proc.duration << " us" << std::endl; |
| 251 | } | 396 | } |
| 252 | } | 397 | } |
| 253 | ss << std::endl; | 398 | ss << std::endl; |
| 254 | log += ss.str(); | 399 | log += ss.str(); |
| 255 | } | 400 | } |
| 256 | 401 | ||
| 257 | -ProcessControl::ProcessControl(ProcessCollection& processes) | 402 | +ProcessControl::ProcessControl(ProcessCollection& processes, ProcessControlOptions options) |
| 258 | - : impl_(new(std::nothrow) Impl(processes)) {} | 403 | + : impl_(new(std::nothrow) Impl(processes, options)) |
| 404 | +{ | ||
| 405 | +} | ||
| 259 | 406 | ||
| 260 | ProcessControl::~ProcessControl() = default; | 407 | ProcessControl::~ProcessControl() = default; |
| 261 | 408 | ||
| 262 | bool ProcessControl::ExecuteProcess(DataInventory& dataInventory, const Context& context) | 409 | bool ProcessControl::ExecuteProcess(DataInventory& dataInventory, const Context& context) |
| 263 | { | 410 | { |
| 264 | - if (!impl_) { | 411 | + if (!impl_) |
| 412 | + { | ||
| 265 | ERROR("ProcessControl Impl create failed!"); | 413 | ERROR("ProcessControl Impl create failed!"); |
| 266 | return false; | 414 | return false; |
| 267 | }; | 415 | }; |
| @@ -271,7 +419,8 @@ bool ProcessControl::ExecuteProcess(DataInventory& dataInventory, const Context& | |||
| 271 | // 获取运行结果 key为level, value为统计结构 | 419 | // 获取运行结果 key为level, value为统计结构 |
| 272 | ExecuteProcessStat ProcessControl::GetExecuteStat() const | 420 | ExecuteProcessStat ProcessControl::GetExecuteStat() const |
| 273 | { | 421 | { |
| 274 | - if (!impl_) { | 422 | + if (!impl_) |
| 423 | + { | ||
| 275 | ERROR("ProcessControl Impl create failed!"); | 424 | ERROR("ProcessControl Impl create failed!"); |
| 276 | return {}; | 425 | return {}; |
| 277 | }; | 426 | }; |
| @@ -280,13 +429,14 @@ ExecuteProcessStat ProcessControl::GetExecuteStat() const | |||
| 280 | 429 | ||
| 281 | bool ProcessControl::VerifyProcess(const ProcessCollection& chipRelatedProcess) const | 430 | bool ProcessControl::VerifyProcess(const ProcessCollection& chipRelatedProcess) const |
| 282 | { | 431 | { |
| 283 | - if (!impl_) { | 432 | + if (!impl_) |
| 433 | + { | ||
| 284 | ERROR("ProcessControl Impl create failed!"); | 434 | ERROR("ProcessControl Impl create failed!"); |
| 285 | return false; | 435 | return false; |
| 286 | }; | 436 | }; |
| 287 | return impl_->VerifyProcess(chipRelatedProcess); | 437 | return impl_->VerifyProcess(chipRelatedProcess); |
| 288 | } | 438 | } |
| 289 | 439 | ||
| 290 | -} | 440 | +} // namespace Infra |
| 291 | 441 | ||
| 292 | -} | 442 | +} // namespace Analysis |
| @@ -0,0 +1,243 @@ | |||
| 1 | +/* ------------------------------------------------------------------------- | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This file is part of the MindStudio project. | ||
| 4 | + * -------------------------------------------------------------------------*/ | ||
| 5 | + | ||
| 6 | + | ||
| 7 | + | ||
| 8 | + | ||
| 9 | + | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | +namespace Analysis | ||
| 17 | +{ | ||
| 18 | +namespace Application | ||
| 19 | +{ | ||
| 20 | +namespace | ||
| 21 | +{ | ||
| 22 | +template <TopoNodeStage Stage, size_t Index> | ||
| 23 | +struct TopoNodeTag | ||
| 24 | +{ | ||
| 25 | +}; | ||
| 26 | + | ||
| 27 | +template <TopoNodeStage Stage, size_t Index> | ||
| 28 | +struct TopoNodeTypeGetter | ||
| 29 | +{ | ||
| 30 | + static std::type_index Get(size_t index) | ||
| 31 | + { | ||
| 32 | + return index == Index ? std::type_index(typeid(TopoNodeTag<Stage, Index>)) | ||
| 33 | + : TopoNodeTypeGetter<Stage, Index - 1>::Get(index); | ||
| 34 | + } | ||
| 35 | +}; | ||
| 36 | + | ||
| 37 | +template <TopoNodeStage Stage> | ||
| 38 | +struct TopoNodeTypeGetter<Stage, 0> | ||
| 39 | +{ | ||
| 40 | + static std::type_index Get(size_t) { return std::type_index(typeid(TopoNodeTag<Stage, 0>)); } | ||
| 41 | +}; | ||
| 42 | + | ||
| 43 | +TopoNodeCollection& Definitions() | ||
| 44 | +{ | ||
| 45 | + static TopoNodeCollection definitions; | ||
| 46 | + return definitions; | ||
| 47 | +} | ||
| 48 | +} // namespace | ||
| 49 | + | ||
| 50 | +bool TopoNodeRegistry::Register(TopoNodeDefinition definition) | ||
| 51 | +{ | ||
| 52 | + if (definition.id.name.empty() || definition.creatorFactory == nullptr) | ||
| 53 | + { | ||
| 54 | + ERROR("Invalid topology node registration."); | ||
| 55 | + return false; | ||
| 56 | + } | ||
| 57 | + if (definition.chipIds.empty()) | ||
| 58 | + { | ||
| 59 | + definition.chipIds = {CHIP_ID_ALL}; | ||
| 60 | + } | ||
| 61 | + return Definitions().emplace(definition.id, std::move(definition)).second; | ||
| 62 | +} | ||
| 63 | + | ||
| 64 | +const TopoNodeCollection& TopoNodeRegistry::GetDefinitions() { return Definitions(); } | ||
| 65 | + | ||
| 66 | +TopoNodeCollection& TopoNodeRegistry::MutableDefinitions() { return Definitions(); } | ||
| 67 | + | ||
| 68 | +TopoNodeSequenceRegister::TopoNodeSequenceRegister(TopoNodeId id, std::type_index runtimeType, bool mandatory, | ||
| 69 | + std::vector<TopoNodeId> dependencies, | ||
| 70 | + TopoNodeCreatorFactory creatorFactory, | ||
| 71 | + TopoDependencyResolver dependencyResolver) | ||
| 72 | +{ | ||
| 73 | + TopoNodeDefinition definition; | ||
| 74 | + definition.id = std::move(id); | ||
| 75 | + definition.runtimeType = runtimeType; | ||
| 76 | + definition.mandatory = mandatory; | ||
| 77 | + definition.processDependencies = std::move(dependencies); | ||
| 78 | + definition.creatorFactory = std::move(creatorFactory); | ||
| 79 | + definition.dependencyResolver = std::move(dependencyResolver); | ||
| 80 | + if (!TopoNodeRegistry::Register(std::move(definition))) | ||
| 81 | + { | ||
| 82 | + ERROR("Register topology sequence failed."); | ||
| 83 | + } | ||
| 84 | +} | ||
| 85 | + | ||
| 86 | +TopoNodeDataRegister::TopoNodeDataRegister(TopoNodeId id, std::vector<std::type_index> inputDataTypes) | ||
| 87 | +{ | ||
| 88 | + const auto* definition = TopoNodeRegistry::Find(id); | ||
| 89 | + if (definition == nullptr) | ||
| 90 | + { | ||
| 91 | + ERROR("Register topology data before topology sequence."); | ||
| 92 | + return; | ||
| 93 | + } | ||
| 94 | + TopoNodeRegistry::MutableDefinitions().at(definition->id).inputDataTypes = std::move(inputDataTypes); | ||
| 95 | +} | ||
| 96 | + | ||
| 97 | +const TopoNodeDefinition* TopoNodeRegistry::Find(const TopoNodeId& id) | ||
| 98 | +{ | ||
| 99 | + const auto iter = Definitions().find(id); | ||
| 100 | + return iter == Definitions().end() ? nullptr : &iter->second; | ||
| 101 | +} | ||
| 102 | + | ||
| 103 | +const TopoNodeDefinition* TopoNodeRegistry::FindProcessorByName(const std::string& name) | ||
| 104 | +{ | ||
| 105 | + return Find({TopoNodeStage::DATA_PROCESSING, name}); | ||
| 106 | +} | ||
| 107 | + | ||
| 108 | +const TopoNodeDefinition* TopoNodeRegistry::FindProcessorByRuntimeType(std::type_index runtimeType) | ||
| 109 | +{ | ||
| 110 | + for (const auto& item : Definitions()) | ||
| 111 | + { | ||
| 112 | + if (item.second.id.stage == TopoNodeStage::DATA_PROCESSING && item.second.runtimeType == runtimeType) | ||
| 113 | + { | ||
| 114 | + return &item.second; | ||
| 115 | + } | ||
| 116 | + } | ||
| 117 | + return nullptr; | ||
| 118 | +} | ||
| 119 | + | ||
| 120 | +bool TopoGraphBuilder::Build(const TopoBuildContext& context, const std::vector<TopoNodeId>& roots, | ||
| 121 | + Infra::ProcessCollection& processes) | ||
| 122 | +{ | ||
| 123 | + if (roots.empty()) | ||
| 124 | + { | ||
| 125 | + ERROR("Topology roots are empty."); | ||
| 126 | + return false; | ||
| 127 | + } | ||
| 128 | + context_ = &context; | ||
| 129 | + roots_ = &roots; | ||
| 130 | + processes_ = &processes; | ||
| 131 | + nodeKeys_.clear(); | ||
| 132 | + nextSyntheticIndex_.clear(); | ||
| 133 | + visiting_.clear(); | ||
| 134 | + processes.clear(); | ||
| 135 | + for (const auto& root : roots) | ||
| 136 | + { | ||
| 137 | + std::type_index key(typeid(void)); | ||
| 138 | + if (!AddNode(root, key)) | ||
| 139 | + { | ||
| 140 | + processes.clear(); | ||
| 141 | + return false; | ||
| 142 | + } | ||
| 143 | + } | ||
| 144 | + return true; | ||
| 145 | +} | ||
| 146 | + | ||
| 147 | +bool TopoGraphBuilder::ResolveDependencies(const TopoNodeDefinition& definition, | ||
| 148 | + std::vector<std::type_index>& dependencies) | ||
| 149 | +{ | ||
| 150 | + std::vector<TopoNodeId> ids = definition.processDependencies; | ||
| 151 | + if (definition.dependencyResolver != nullptr) | ||
| 152 | + { | ||
| 153 | + const auto dynamicDependencies = definition.dependencyResolver(*context_, *roots_); | ||
| 154 | + ids.insert(ids.end(), dynamicDependencies.begin(), dynamicDependencies.end()); | ||
| 155 | + } | ||
| 156 | + for (const auto& id : ids) | ||
| 157 | + { | ||
| 158 | + std::type_index key(typeid(void)); | ||
| 159 | + if (!AddNode(id, key)) | ||
| 160 | + { | ||
| 161 | + return false; | ||
| 162 | + } | ||
| 163 | + if (std::find(dependencies.begin(), dependencies.end(), key) == dependencies.end()) | ||
| 164 | + { | ||
| 165 | + dependencies.emplace_back(key); | ||
| 166 | + } | ||
| 167 | + } | ||
| 168 | + return true; | ||
| 169 | +} | ||
| 170 | + | ||
| 171 | +bool TopoGraphBuilder::AddNode(const TopoNodeId& id, std::type_index& key) | ||
| 172 | +{ | ||
| 173 | + const auto keyIter = nodeKeys_.find(id); | ||
| 174 | + if (keyIter != nodeKeys_.end()) | ||
| 175 | + { | ||
| 176 | + key = keyIter->second; | ||
| 177 | + return true; | ||
| 178 | + } | ||
| 179 | + if (visiting_[id]) | ||
| 180 | + { | ||
| 181 | + ERROR("Topology contains a cycle at %.", id.name); | ||
| 182 | + return false; | ||
| 183 | + } | ||
| 184 | + const auto* definition = TopoNodeRegistry::Find(id); | ||
| 185 | + if (definition == nullptr) | ||
| 186 | + { | ||
| 187 | + ERROR("Topology contains an unregistered node %.", id.name); | ||
| 188 | + return false; | ||
| 189 | + } | ||
| 190 | + visiting_[id] = true; | ||
严重程度: 提示 问题: 原因: 当前 怎么改:
用 RAII 守卫或确保所有 early-return 前清理
或者用 scope guard 统一管理 ![]() ![]() | |||
| 191 | + std::vector<std::type_index> dependencies; | ||
| 192 | + if (!ResolveDependencies(*definition, dependencies)) | ||
| 193 | + { | ||
| 194 | + return false; | ||
| 195 | + } | ||
| 196 | + key = definition->id.stage == TopoNodeStage::DATA_PROCESSING ? definition->runtimeType | ||
| 197 | + : AllocateSyntheticKey(definition->id.stage); | ||
| 198 | + if (key == std::type_index(typeid(void))) | ||
| 199 | + { | ||
| 200 | + ERROR("Failed to allocate topology key for %.", definition->id.name); | ||
| 201 | + return false; | ||
| 202 | + } | ||
| 203 | + Infra::RegProcessInfo processInfo; | ||
| 204 | + processInfo.creator = definition->creatorFactory(*context_); | ||
| 205 | + processInfo.processDependence = std::move(dependencies); | ||
| 206 | + processInfo.paramTypes = definition->inputDataTypes; | ||
| 207 | + processInfo.chipIds = definition->chipIds; | ||
| 208 | + processInfo.processName = definition->id.name; | ||
| 209 | + processInfo.mandatory = definition->mandatory; | ||
| 210 | + if (processInfo.creator == nullptr || !processes_->emplace(key, std::move(processInfo)).second) | ||
| 211 | + { | ||
| 212 | + ERROR("Failed to append topology node %.", definition->id.name); | ||
| 213 | + return false; | ||
| 214 | + } | ||
| 215 | + nodeKeys_.emplace(id, key); | ||
| 216 | + visiting_.erase(id); | ||
| 217 | + return true; | ||
| 218 | +} | ||
| 219 | + | ||
| 220 | +std::type_index TopoGraphBuilder::AllocateSyntheticKey(TopoNodeStage stage) | ||
| 221 | +{ | ||
| 222 | + const size_t index = nextSyntheticIndex_[stage]++; | ||
| 223 | + if (index >= MAX_TOPO_NODE_COUNT) | ||
| 224 | + { | ||
| 225 | + ERROR("Too many topology nodes in stage %.", static_cast<uint8_t>(stage)); | ||
| 226 | + return std::type_index(typeid(void)); | ||
| 227 | + } | ||
| 228 | + switch (stage) | ||
| 229 | + { | ||
| 230 | + case TopoNodeStage::SUMMARY_GENERATION: | ||
| 231 | + return TopoNodeTypeGetter<TopoNodeStage::SUMMARY_GENERATION, MAX_TOPO_NODE_COUNT - 1>::Get(index); | ||
| 232 | + case TopoNodeStage::DATABASE_PERSISTENCE: | ||
| 233 | + return TopoNodeTypeGetter<TopoNodeStage::DATABASE_PERSISTENCE, MAX_TOPO_NODE_COUNT - 1>::Get(index); | ||
| 234 | + case TopoNodeStage::TIMELINE_EXPORT: | ||
| 235 | + return TopoNodeTypeGetter<TopoNodeStage::TIMELINE_EXPORT, MAX_TOPO_NODE_COUNT - 1>::Get(index); | ||
| 236 | + case TopoNodeStage::FLOW_CONTROL: | ||
| 237 | + return TopoNodeTypeGetter<TopoNodeStage::FLOW_CONTROL, MAX_TOPO_NODE_COUNT - 1>::Get(index); | ||
| 238 | + default: | ||
| 239 | + return std::type_index(typeid(void)); | ||
| 240 | + } | ||
| 241 | +} | ||
| 242 | +} // namespace Application | ||
| 243 | +} // namespace Analysis | ||
| @@ -4,6 +4,7 @@ aux_source_directory(${TOP_DIR}/analysis/csrc/infrastructure/dump_tools/csv_tool | |||
| 4 | aux_source_directory(${TOP_DIR}/analysis/csrc/infrastructure/dump_tools/json_tool SOURCES) | 4 | aux_source_directory(${TOP_DIR}/analysis/csrc/infrastructure/dump_tools/json_tool SOURCES) |
| 5 | aux_source_directory(${TOP_DIR}/analysis/csrc/infrastructure/utils SOURCES) | 5 | aux_source_directory(${TOP_DIR}/analysis/csrc/infrastructure/utils SOURCES) |
| 6 | aux_source_directory(${TOP_DIR}/analysis/csrc/infrastructure/dfx SOURCES) | 6 | aux_source_directory(${TOP_DIR}/analysis/csrc/infrastructure/dfx SOURCES) |
| 7 | +aux_source_directory(${TOP_DIR}/analysis/csrc/infrastructure/process SOURCES) | ||
| 7 | aux_source_directory(${TOP_DIR}/analysis/csrc/domain/services/environment SOURCES) | 8 | aux_source_directory(${TOP_DIR}/analysis/csrc/domain/services/environment SOURCES) |
| 8 | aux_source_directory(${TOP_DIR}/analysis/csrc/domain/entities/json_trace SOURCES) | 9 | aux_source_directory(${TOP_DIR}/analysis/csrc/domain/entities/json_trace SOURCES) |
| 9 | aux_source_directory(${TOP_DIR}/analysis/csrc/domain/data_process SOURCES) | 10 | aux_source_directory(${TOP_DIR}/analysis/csrc/domain/data_process SOURCES) |
| @@ -29,4 +30,4 @@ target_link_libraries(export_assemble_utest PRIVATE | |||
| 29 | -lsqlite3 | 30 | -lsqlite3 |
| 30 | ) | 31 | ) |
| 31 | 32 | ||
| 32 | -run_test(export_assemble_utest) | 33 | +run_test(export_assemble_utest) |


【review】 问题:两个函数在模式上高度重复,后续维护容易出现行为漂移 CreateSaver 和 CreateStringIdsSaver 本质都是: 取 session 判空 构造 ProcessCreator 在 TopoAssemblerProcess 中执行保存逻辑 但现在它们的日志、错误处理、输出语义已经不一致了,这通常就是重复代码带来的维护偏差。 建议: 抽一个统一的辅助构造函数,把“取 session、判空、创建 TopoAssemblerProcess、日志包装”这些共性逻辑收敛起来。 这样可以统一错误处理和日志规范,也能减少未来继续出现一个函数修了、另一个没修的问题。