已合并
bugfix:统一db问题修正 #487
wangzixuan创建于 22 天前
bugfix:统一db问题修正 #487
已合并
共 28 个文件变更+480-199
| @@ -84,11 +84,11 @@ using CommunicationOpDataFormat = | |||
| 84 | std::vector<std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, int64_t, int32_t, int32_t, uint64_t, | 84 | std::vector<std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, int64_t, int32_t, int32_t, uint64_t, |
| 85 | uint64_t, uint64_t, uint64_t, uint16_t, int64_t>>; | 85 | uint64_t, uint64_t, uint64_t, uint16_t, int64_t>>; |
| 86 | // 小算子数据 | 86 | // 小算子数据 |
| 87 | -// name, globalTaskId, taskType, planeId, groupName, notifyId, rdmaType, srcRank, dstRank, transportType, | 87 | +// timestampNs, name, globalTaskId, taskType, planeId, groupName, notifyId, rdmaType, srcRank, dstRank, transportType, |
| 88 | // size, dataType, linkType, opId, isMaster, bandwidth | 88 | // size, dataType, linkType, opId, isMaster, bandwidth |
| 89 | using CommunicationTaskDataFormat = | 89 | using CommunicationTaskDataFormat = |
| 90 | - std::vector<std::tuple<uint64_t, uint64_t, uint64_t, uint32_t, uint64_t, uint64_t, uint64_t, int64_t, int64_t, | 90 | + std::vector<std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, uint32_t, uint64_t, uint64_t, uint64_t, int64_t, |
| 91 | - uint64_t, uint64_t, uint64_t, uint64_t, int64_t, uint16_t, double>>; | 91 | + int64_t, uint64_t, uint64_t, uint64_t, uint64_t, int64_t, uint16_t, double>>; |
| 92 | 92 | ||
| 93 | enum class DevType | 93 | enum class DevType |
| 94 | { | 94 | { |
| @@ -273,9 +273,9 @@ void ConvertTaskData(CommunicationTaskDataFormat& processedTaskData, const std:: | |||
| 273 | DataProcessor::GetEnumTypeValue(item.linkType, NAME_STR(HCCL_LINK_TYPE_TABLE), HCCL_LINK_TYPE_TABLE); | 273 | DataProcessor::GetEnumTypeValue(item.linkType, NAME_STR(HCCL_LINK_TYPE_TABLE), HCCL_LINK_TYPE_TABLE); |
| 274 | uint32_t assocId = | 274 | uint32_t assocId = |
| 275 | IdPool::GetInstance().GetUint32Id(std::to_string(item.opId) + "_" + std::to_string(item.iterId)); | 275 | IdPool::GetInstance().GetUint32Id(std::to_string(item.opId) + "_" + std::to_string(item.iterId)); |
| 276 | - processedTaskData.emplace_back(opName, globalTaskId, taskType, item.planeId, groupName, notifyId, rdmaType, | 276 | + processedTaskData.emplace_back(item.timestamp, opName, globalTaskId, taskType, item.planeId, groupName, |
| 277 | - item.srcRank, item.dstRank, transportType, item.size, dataType, linkType, | 277 | + notifyId, rdmaType, item.srcRank, item.dstRank, transportType, item.size, |
| 278 | - assocId, item.isMaster, | 278 | + dataType, linkType, assocId, item.isMaster, |
| 279 | item.bandwidth * Common::BYTES_PER_GB); // GB/s -> B/s,字节按1024换算 | 279 | item.bandwidth * Common::BYTES_PER_GB); // GB/s -> B/s,字节按1024换算 |
| 280 | } | 280 | } |
| 281 | } | 281 | } |
| @@ -985,9 +985,9 @@ bool SaveRoCEData(DataInventory& dataInventory, DBInfo& msprofDB, const std::str | |||
| 985 | 985 | ||
| 986 | bool SaveTaskPmuData(DataInventory& dataInventory, DBInfo& msprofDB, const std::string& profPath) | 986 | bool SaveTaskPmuData(DataInventory& dataInventory, DBInfo& msprofDB, const std::string& profPath) |
| 987 | { | 987 | { |
| 988 | - // UnifiedTaskPMU deviceId, streamId, taskId, subtaskId, batchId, header, value | 988 | + // UnifiedTaskPMU deviceId, streamId, taskId, subtaskId, batchId, header, value, timestamp |
| 989 | - // ProcessedTaskFormat globalTaskId, header(uint64id), value | 989 | + // ProcessedTaskFormat timestampNs, globalTaskId, header(uint64id), value |
| 990 | - using PTFormat = std::vector<std::tuple<uint64_t, uint64_t, double>>; | 990 | + using PTFormat = std::vector<std::tuple<uint64_t, uint64_t, uint64_t, double>>; |
| 991 | PTFormat res; | 991 | PTFormat res; |
| 992 | auto unifiedTaskPmuData = dataInventory.GetPtr<std::vector<UnifiedTaskPmu>>(); | 992 | auto unifiedTaskPmuData = dataInventory.GetPtr<std::vector<UnifiedTaskPmu>>(); |
| 993 | if (unifiedTaskPmuData == nullptr) | 993 | if (unifiedTaskPmuData == nullptr) |
| @@ -1006,7 +1006,7 @@ bool SaveTaskPmuData(DataInventory& dataInventory, DBInfo& msprofDB, const std:: | |||
| 1006 | uint64_t globalTaskId = IdPool::GetInstance().GetId( | 1006 | uint64_t globalTaskId = IdPool::GetInstance().GetId( |
| 1007 | std::make_tuple(static_cast<uint16_t>(item.deviceId), item.streamId, item.taskId, item.subtaskId, | 1007 | std::make_tuple(static_cast<uint16_t>(item.deviceId), item.streamId, item.taskId, item.subtaskId, |
| 1008 | item.batchId, static_cast<uint32_t>(DevType::NPU))); | 1008 | item.batchId, static_cast<uint32_t>(DevType::NPU))); |
| 1009 | - res.emplace_back(globalTaskId, IdPool::GetInstance().GetUint64Id(item.header), item.value); | 1009 | + res.emplace_back(item.timestamp, globalTaskId, IdPool::GetInstance().GetUint64Id(item.header), item.value); |
| 1010 | } | 1010 | } |
| 1011 | return SaveData(res, TABLE_NAME_TASK_PMU_INFO, msprofDB); | 1011 | return SaveData(res, TABLE_NAME_TASK_PMU_INFO, msprofDB); |
| 1012 | } | 1012 | } |
| @@ -1304,7 +1304,7 @@ bool SaveDPUData(DataInventory& dataInventory, DBInfo& msprofDB, const std::stri | |||
| 1304 | } | 1304 | } |
| 1305 | 1305 | ||
| 1306 | using DPUTaskFormat = std::vector< | 1306 | using DPUTaskFormat = std::vector< |
| 1307 | - std::tuple<uint16_t, uint32_t, uint64_t, uint64_t, uint64_t, uint32_t, uint32_t, uint64_t, uint64_t>>; | 1307 | + std::tuple<uint16_t, uint64_t, uint64_t, uint64_t, uint64_t, uint32_t, uint32_t, uint64_t, uint64_t>>; |
| 1308 | 1308 | ||
| 1309 | DPUTaskFormat res; | 1309 | DPUTaskFormat res; |
| 1310 | if (!Reserve(res, dpuData->size())) | 1310 | if (!Reserve(res, dpuData->size())) |
| @@ -1313,6 +1313,7 @@ bool SaveDPUData(DataInventory& dataInventory, DBInfo& msprofDB, const std::stri | |||
| 1313 | return false; | 1313 | return false; |
| 1314 | } | 1314 | } |
| 1315 | 1315 | ||
| 1316 | + uint32_t pid = Environment::Context::GetInstance().GetPidFromInfoJson(HOST_ID, profPath); | ||
| 1316 | for (const auto& data : *dpuData) | 1317 | for (const auto& data : *dpuData) |
| 1317 | { | 1318 | { |
| 1318 | uint64_t globalTaskId = IdPool::GetInstance().GetId(std::make_tuple( | 1319 | uint64_t globalTaskId = IdPool::GetInstance().GetId(std::make_tuple( |
| @@ -1361,8 +1362,8 @@ bool SaveDPUData(DataInventory& dataInventory, DBInfo& msprofDB, const std::stri | |||
| 1361 | jsonWriter.EndArray(); | 1362 | jsonWriter.EndArray(); |
| 1362 | std::string args = jsonWriter.GetString(); | 1363 | std::string args = jsonWriter.GetString(); |
| 1363 | uint64_t argsId = IdPool::GetInstance().GetUint64Id(args); | 1364 | uint64_t argsId = IdPool::GetInstance().GetUint64Id(args); |
| 1364 | - res.emplace_back(data.dpuDeviceId, data.threadId, data.timestamp, data.endTime, globalTaskId, data.streamId, | 1365 | + res.emplace_back(data.dpuDeviceId, Utils::Contact(pid, data.threadId), data.timestamp, data.endTime, |
| 1365 | - data.taskId, opNameId, argsId); | 1366 | + globalTaskId, data.streamId, data.taskId, opNameId, argsId); |
| 1366 | } | 1367 | } |
| 1367 | 1368 | ||
| 1368 | return SaveData(res, TABLE_NAME_DPU_TASK, msprofDB); | 1369 | return SaveData(res, TABLE_NAME_DPU_TASK, msprofDB); |
| @@ -69,12 +69,12 @@ const TableColumns COMMUNICATION_SCHEDULE_TASK_INFO = {{"name", SQL_INTEGER_TYPE | |||
| 69 | {"opType", SQL_INTEGER_TYPE}}; | 69 | {"opType", SQL_INTEGER_TYPE}}; |
| 70 | 70 | ||
| 71 | const TableColumns COMMUNICATION_TASK_INFO = { | 71 | const TableColumns COMMUNICATION_TASK_INFO = { |
| 72 | - {"name", SQL_INTEGER_TYPE}, {"globalTaskId", SQL_INTEGER_TYPE}, {"taskType", SQL_INTEGER_TYPE}, | 72 | + {"timestampNs", SQL_INTEGER_TYPE}, {"name", SQL_INTEGER_TYPE}, {"globalTaskId", SQL_INTEGER_TYPE}, |
| 73 | - {"planeId", SQL_INTEGER_TYPE}, {"groupName", SQL_INTEGER_TYPE}, {"notifyId", SQL_INTEGER_TYPE}, | 73 | + {"taskType", SQL_INTEGER_TYPE}, {"planeId", SQL_INTEGER_TYPE}, {"groupName", SQL_INTEGER_TYPE}, |
| 74 | - {"rdmaType", SQL_INTEGER_TYPE}, {"srcRank", SQL_INTEGER_TYPE}, {"dstRank", SQL_INTEGER_TYPE}, | 74 | + {"notifyId", SQL_INTEGER_TYPE}, {"rdmaType", SQL_INTEGER_TYPE}, {"srcRank", SQL_INTEGER_TYPE}, |
| 75 | - {"transportType", SQL_INTEGER_TYPE}, {"size", SQL_INTEGER_TYPE}, {"dataType", SQL_INTEGER_TYPE}, | 75 | + {"dstRank", SQL_INTEGER_TYPE}, {"transportType", SQL_INTEGER_TYPE}, {"size", SQL_INTEGER_TYPE}, |
| 76 | - {"linkType", SQL_INTEGER_TYPE}, {"opId", SQL_INTEGER_TYPE}, {"isMaster", SQL_INTEGER_TYPE}, | 76 | + {"dataType", SQL_INTEGER_TYPE}, {"linkType", SQL_INTEGER_TYPE}, {"opId", SQL_INTEGER_TYPE}, |
| 77 | - {"bandwidth", SQL_NUMERIC_TYPE}, | 77 | + {"isMaster", SQL_INTEGER_TYPE}, {"bandwidth", SQL_NUMERIC_TYPE}, |
| 78 | }; | 78 | }; |
| 79 | 79 | ||
| 80 | const TableColumns COMMUNICATION_OP = { | 80 | const TableColumns COMMUNICATION_OP = { |
| @@ -132,8 +132,10 @@ const TableColumns LLC = { | |||
| 132 | {"hitRate", SQL_REAL_TYPE}, {"throughput", SQL_INTEGER_TYPE}, {"mode", SQL_INTEGER_TYPE}, | 132 | {"hitRate", SQL_REAL_TYPE}, {"throughput", SQL_INTEGER_TYPE}, {"mode", SQL_INTEGER_TYPE}, |
| 133 | }; | 133 | }; |
| 134 | 134 | ||
| 135 | -const TableColumns TASK_PMU_INFO = { | 135 | +const TableColumns TASK_PMU_INFO = {{"timestampNs", SQL_INTEGER_TYPE}, |
| 136 | - {"globalTaskId", SQL_INTEGER_TYPE}, {"name", SQL_INTEGER_TYPE}, {"value", SQL_NUMERIC_TYPE}}; | 136 | + {"globalTaskId", SQL_INTEGER_TYPE}, |
| 137 | + {"name", SQL_INTEGER_TYPE}, | ||
| 138 | + {"value", SQL_NUMERIC_TYPE}}; | ||
| 137 | 139 | ||
| 138 | const TableColumns SAMPLE_PMU_TIMELINE = { | 140 | const TableColumns SAMPLE_PMU_TIMELINE = { |
| 139 | {"deviceId", SQL_INTEGER_TYPE}, {"timestampNs", SQL_INTEGER_TYPE}, {"totalCycle", SQL_INTEGER_TYPE}, | 141 | {"deviceId", SQL_INTEGER_TYPE}, {"timestampNs", SQL_INTEGER_TYPE}, {"totalCycle", SQL_INTEGER_TYPE}, |
| @@ -15,6 +15,7 @@ | |||
| 15 | * -------------------------------------------------------------------------*/ | 15 | * -------------------------------------------------------------------------*/ |
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | + | ||
| 18 | 19 | ||
| 19 | 20 | ||
| 20 | 21 | ||
| @@ -39,6 +40,10 @@ const std::set<std::string> SAMPLE_BASED_DB_NAMES = {AI_VECTOR_CORE_DB, AI_CORE_ | |||
| 39 | const std::set<std::string> INVALID_COLUMN_NAMES = {"task_id", "stream_id", "subtask_id", "batch_id", "task_type", | 40 | const std::set<std::string> INVALID_COLUMN_NAMES = {"task_id", "stream_id", "subtask_id", "batch_id", "task_type", |
| 40 | "start_time", "end_time", "ffts_type", "core_type"}; | 41 | "start_time", "end_time", "ffts_type", "core_type"}; |
| 41 | const std::string TASK_BASED = "task-based"; | 42 | const std::string TASK_BASED = "task-based"; |
| 43 | +// metric_summary 中每算子一行的时间列,不作为 metric 行落盘,仅用于携带到每行 metric 的 timestampNs | ||
| 44 | +// 列值由写侧(GetTimeFromSyscnt/time_from_syscnt)换算到 host 开机 monotonic ns,读侧再经 GetLocalTime 转世界时; | ||
| 45 | +// C++侧metric_summary_persistence(chipV4)与python侧stars(ffts/chip6)落库的时间列名统一为 end_time | ||
| 46 | +const std::string END_TIME_COLUMN_NAME = "end_time"; | ||
| 42 | const double DOUBLE_ZERO = 0.0; | 47 | const double DOUBLE_ZERO = 0.0; |
| 43 | 48 | ||
| 44 | struct TaskPmuData | 49 | struct TaskPmuData |
| @@ -175,12 +180,23 @@ bool UnifiedPmuProcessor::ProcessTaskBasedData(const std::unordered_map<std::str | |||
| 175 | DataInventory &dataInventory) | 180 | DataInventory &dataInventory) |
| 176 | { | 181 | { |
| 177 | bool flag = true; | 182 | bool flag = true; |
| 183 | + // task-based 场景的 metric_summary 统一带时间列 end_time(C++ chipV4落库与python侧stars落库一致), | ||
| 184 | + // 每个算子一行。GetTaskBasedData 在查 metric 值的同时把该行 end_time 一并查出,FormatTaskBasedData 内 | ||
| 185 | + // 按 device 的 ProfTimeRecord 经 GetLocalTime 平移到世界时轴,使每条 metric 行携带所属算子自身的时间, | ||
| 186 | + // 不按算子四元组单独建表 join。若某张表确实缺 end_time 列,查询会直接失败并报错(符合预期)。 | ||
| 178 | std::vector<UnifiedTaskPmu> processedData; | 187 | std::vector<UnifiedTaskPmu> processedData; |
| 179 | for (const auto &dbPathAndDeviceId : dbPathAndDeviceIds) | 188 | for (const auto &dbPathAndDeviceId : dbPathAndDeviceIds) |
| 180 | { | 189 | { |
| 190 | + Utils::ProfTimeRecord record; | ||
| 191 | + if (!Context::GetInstance().GetProfTimeRecordInfo(record, profPath_, dbPathAndDeviceId.second)) | ||
| 192 | + { | ||
| 193 | + ERROR("GetProfTimeRecordInfo failed, profPath is %, device id is %.", profPath_, dbPathAndDeviceId.second); | ||
| 194 | + flag = false; | ||
| 195 | + continue; | ||
| 196 | + } | ||
| 181 | for (const auto &header : headers) | 197 | for (const auto &header : headers) |
| 182 | { | 198 | { |
| 183 | - if (!ProcessTaskBasedDataByHeader(dbPathAndDeviceId, metricDB, header, processedData)) | 199 | + if (!ProcessTaskBasedDataByHeader(dbPathAndDeviceId, metricDB, record, header, processedData)) |
| 184 | { | 200 | { |
| 185 | flag = false; | 201 | flag = false; |
| 186 | ERROR("Process task_based data failed, failed device is %", dbPathAndDeviceId.second); | 202 | ERROR("Process task_based data failed, failed device is %", dbPathAndDeviceId.second); |
| @@ -196,7 +212,8 @@ bool UnifiedPmuProcessor::ProcessTaskBasedData(const std::unordered_map<std::str | |||
| 196 | } | 212 | } |
| 197 | 213 | ||
| 198 | bool UnifiedPmuProcessor::ProcessTaskBasedDataByHeader(const std::pair<std::string, uint16_t> &dbPathAndDeviceId, | 214 | bool UnifiedPmuProcessor::ProcessTaskBasedDataByHeader(const std::pair<std::string, uint16_t> &dbPathAndDeviceId, |
| 199 | - Analysis::Infra::DBInfo &metricDB, const std::string &header, | 215 | + Analysis::Infra::DBInfo &metricDB, |
| 216 | + const Utils::ProfTimeRecord &record, const std::string &header, | ||
| 200 | std::vector<UnifiedTaskPmu> &processedData) | 217 | std::vector<UnifiedTaskPmu> &processedData) |
| 201 | { | 218 | { |
| 202 | if (INVALID_COLUMN_NAMES.find(header) != INVALID_COLUMN_NAMES.end()) | 219 | if (INVALID_COLUMN_NAMES.find(header) != INVALID_COLUMN_NAMES.end()) |
| @@ -205,7 +222,7 @@ bool UnifiedPmuProcessor::ProcessTaskBasedDataByHeader(const std::pair<std::stri | |||
| 205 | return true; | 222 | return true; |
| 206 | } | 223 | } |
| 207 | OTFormat pmuData = GetTaskBasedData(dbPathAndDeviceId.first, header, metricDB); | 224 | OTFormat pmuData = GetTaskBasedData(dbPathAndDeviceId.first, header, metricDB); |
| 208 | - if (!FormatTaskBasedData(pmuData, processedData, header, dbPathAndDeviceId.second)) | 225 | + if (!FormatTaskBasedData(pmuData, processedData, header, dbPathAndDeviceId.second, record)) |
| 209 | { | 226 | { |
| 210 | ERROR("FormatData failed, dbPath is %.", dbPathAndDeviceId.first); | 227 | ERROR("FormatData failed, dbPath is %.", dbPathAndDeviceId.first); |
| 211 | return false; | 228 | return false; |
| @@ -235,7 +252,13 @@ UnifiedPmuProcessor::OTFormat UnifiedPmuProcessor::GetTaskBasedData(const std::s | |||
| 235 | subtaskIdSql = "subtask_id, "; | 252 | subtaskIdSql = "subtask_id, "; |
| 236 | } | 253 | } |
| 237 | std::string sql = "SELECT stream_id, task_id, "; | 254 | std::string sql = "SELECT stream_id, task_id, "; |
| 238 | - sql.append(subtaskIdSql).append(" batch_id, ").append(columnName).append(" FROM ").append(metricDB.tableName); | 255 | + sql.append(subtaskIdSql) |
| 256 | + .append(" batch_id, ") | ||
| 257 | + .append(columnName) | ||
| 258 | + .append(", ") | ||
| 259 | + .append(END_TIME_COLUMN_NAME) | ||
| 260 | + .append(" FROM ") | ||
| 261 | + .append(metricDB.tableName); | ||
| 239 | if (!metricDB.dbRunner->QueryData(sql, oriData)) | 262 | if (!metricDB.dbRunner->QueryData(sql, oriData)) |
| 240 | { | 263 | { |
| 241 | ERROR("Query task-based % data failed, db path is %.", columnName, dbPath); | 264 | ERROR("Query task-based % data failed, db path is %.", columnName, dbPath); |
| @@ -272,7 +295,8 @@ uint64_t UnifiedPmuProcessor::UpdateColumnName(std::string &columnName) | |||
| 272 | } | 295 | } |
| 273 | 296 | ||
| 274 | bool UnifiedPmuProcessor::FormatTaskBasedData(const OTFormat &oriData, std::vector<UnifiedTaskPmu> &processedData, | 297 | bool UnifiedPmuProcessor::FormatTaskBasedData(const OTFormat &oriData, std::vector<UnifiedTaskPmu> &processedData, |
| 275 | - std::string columnName, const uint16_t &deviceId) | 298 | + std::string columnName, const uint16_t &deviceId, |
| 299 | + const Utils::ProfTimeRecord &record) | ||
| 276 | { | 300 | { |
| 277 | INFO("FormatTaskBasedData."); | 301 | INFO("FormatTaskBasedData."); |
| 278 | if (oriData.empty()) | 302 | if (oriData.empty()) |
| @@ -289,11 +313,20 @@ bool UnifiedPmuProcessor::FormatTaskBasedData(const OTFormat &oriData, std::vect | |||
| 289 | // 1、没有考虑memory_bound或是cube utilization的计算 | 313 | // 1、没有考虑memory_bound或是cube utilization的计算 |
| 290 | auto valueScale = UpdateColumnName(columnName); | 314 | auto valueScale = UpdateColumnName(columnName); |
| 291 | TaskPmuData tempData; | 315 | TaskPmuData tempData; |
| 316 | + uint64_t endTime = 0; | ||
| 292 | for (const auto &row : oriData) | 317 | for (const auto &row : oriData) |
| 293 | { | 318 | { |
| 294 | - std::tie(tempData.streamId, tempData.taskId, tempData.subtaskId, tempData.batchId, tempData.value) = row; | 319 | + // OTFormat: stream_id, task_id, subtask_id, batch_id, value, end_time |
| 320 | + std::tie(tempData.streamId, tempData.taskId, tempData.subtaskId, tempData.batchId, tempData.value, endTime) = | ||
| 321 | + row; | ||
| 322 | + // end_time 列值在写侧(GetTimeFromSyscnt/time_from_syscnt)仅换算到 host 开机 monotonic ns,尚未叠加 | ||
| 323 | + // 采集起始的“世界时”偏移。其它上 timeline 的 task/事件行写盘前都经 GetLocalTime 平移(见 | ||
| 324 | + // fusion_task_processor 同款注释),此处对每行自身 end_time 补 GetLocalTime 后才与 task 时间对齐; | ||
| 325 | + // 直接从 uint64 构造 HPFloat,避免经 double 丢低位精度 | ||
| 326 | + Utils::HPFloat endTimeHP(endTime); | ||
| 327 | + uint64_t timestamp = Utils::GetLocalTime(endTimeHP, record).Uint64(); | ||
| 295 | processedData.emplace_back(deviceId, tempData.streamId, tempData.taskId, tempData.subtaskId, tempData.batchId, | 328 | processedData.emplace_back(deviceId, tempData.streamId, tempData.taskId, tempData.subtaskId, tempData.batchId, |
| 296 | - columnName, tempData.value * valueScale); | 329 | + columnName, tempData.value * valueScale, timestamp); |
| 297 | } | 330 | } |
| 298 | if (processedData.empty()) | 331 | if (processedData.empty()) |
| 299 | { | 332 | { |
| @@ -16,52 +16,55 @@ | |||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | + | ||
| 19 | 20 | ||
| 20 | - | ||
| 21 | 21 | ||
| 22 | - | ||
| 23 | 22 | ||
| 23 | + | ||
| 24 | 24 | ||
| 25 | 25 | ||
| 26 | -namespace Analysis { | 26 | +namespace Analysis |
| 27 | -namespace Domain { | 27 | +{ |
| 28 | +namespace Domain | ||
| 29 | +{ | ||
| 28 | 30 | ||
| 29 | -class UnifiedPmuProcessor : public DataProcessor { | 31 | +class UnifiedPmuProcessor : public DataProcessor |
| 30 | -// Original Sample Timeline Format:aicore/ai_vector_core中的AICoreOriginalData | 32 | +{ |
| 31 | -// timestamp, task_cyc, coreid | 33 | + // Original Sample Timeline Format:aicore/ai_vector_core中的AICoreOriginalData |
| 32 | -using OSTFormat = std::vector<std::tuple<uint64_t, std::string, uint32_t>>; | 34 | + // timestamp, task_cyc, coreid |
| 33 | -// Original Sample Summary Format:aicore/ai_vector_core中的MetricSummary | 35 | + using OSTFormat = std::vector<std::tuple<uint64_t, std::string, uint32_t>>; |
| 34 | -// metric, value, coreid | 36 | + // Original Sample Summary Format:aicore/ai_vector_core中的MetricSummary |
| 35 | -using OSSFormat = std::vector<std::tuple<std::string, double, uint32_t>>; | 37 | + // metric, value, coreid |
| 36 | -// Original Task Format: 只取id + 对应字段的value | 38 | + using OSSFormat = std::vector<std::tuple<std::string, double, uint32_t>>; |
| 37 | -// stream_id, task_id, subtask_id, batch_id, value | 39 | + // Original Task Format: 只取id + 对应字段的value + 该行的算子时间列end_time |
| 38 | -using OTFormat = std::vector<std::tuple<uint32_t, uint32_t, uint32_t, uint32_t, double>>; | 40 | + // stream_id, task_id, subtask_id, batch_id, value, end_time(host开机monotonic ns,Format时再GetLocalTime) |
| 41 | + using OTFormat = std::vector<std::tuple<uint32_t, uint32_t, uint32_t, uint32_t, double, uint64_t>>; | ||
| 39 | 42 | ||
| 40 | -public: | 43 | + public: |
| 41 | UnifiedPmuProcessor() = default; | 44 | UnifiedPmuProcessor() = default; |
| 42 | explicit UnifiedPmuProcessor(const std::string &profPath); | 45 | explicit UnifiedPmuProcessor(const std::string &profPath); |
| 43 | -private: | 46 | + |
| 47 | + private: | ||
| 44 | bool Process(DataInventory &dataInventory) override; | 48 | bool Process(DataInventory &dataInventory) override; |
| 45 | bool TaskBasedProcess(DataInventory &data_inventory); | 49 | bool TaskBasedProcess(DataInventory &data_inventory); |
| 46 | bool SampleBasedProcess(DataInventory &data_inventory); | 50 | bool SampleBasedProcess(DataInventory &data_inventory); |
| 47 | static std::vector<std::string> GetAndCheckTableColumns( | 51 | static std::vector<std::string> GetAndCheckTableColumns( |
| 48 | - const std::unordered_map<std::string, uint16_t> &dbPathAndDeviceID, Analysis::Infra::DBInfo &metricDB); | 52 | + const std::unordered_map<std::string, uint16_t> &dbPathAndDeviceID, Analysis::Infra::DBInfo &metricDB); |
| 49 | bool TaskBasedProcess(const std::string &fileDir); | 53 | bool TaskBasedProcess(const std::string &fileDir); |
| 50 | bool ProcessTaskBasedData(const std::unordered_map<std::string, uint16_t> &dbPathAndDeviceId, | 54 | bool ProcessTaskBasedData(const std::unordered_map<std::string, uint16_t> &dbPathAndDeviceId, |
| 51 | - Analysis::Infra::DBInfo &metricDB, std::vector<std::string> &headers, | 55 | + Analysis::Infra::DBInfo &metricDB, std::vector<std::string> &headers, |
| 52 | - DataInventory &dataInventory); | 56 | + DataInventory &dataInventory); |
| 53 | bool ProcessTaskBasedDataByHeader(const std::pair<std::string, uint16_t> &dbPathAndDeviceId, | 57 | bool ProcessTaskBasedDataByHeader(const std::pair<std::string, uint16_t> &dbPathAndDeviceId, |
| 54 | - Analysis::Infra::DBInfo &metricDB, const std::string &header, | 58 | + Analysis::Infra::DBInfo &metricDB, const Utils::ProfTimeRecord &record, |
| 55 | - std::vector<UnifiedTaskPmu> &processedData); | 59 | + const std::string &header, std::vector<UnifiedTaskPmu> &processedData); |
| 56 | UnifiedPmuProcessor::OTFormat GetTaskBasedData(const std::string &dbPath, const std::string &columnName, | 60 | UnifiedPmuProcessor::OTFormat GetTaskBasedData(const std::string &dbPath, const std::string &columnName, |
| 57 | - DBInfo &metricDB); | 61 | + DBInfo &metricDB); |
| 58 | static uint64_t UpdateColumnName(std::string &columnName); | 62 | static uint64_t UpdateColumnName(std::string &columnName); |
| 59 | bool FormatTaskBasedData(const OTFormat &oriData, std::vector<UnifiedTaskPmu> &processedData, | 63 | bool FormatTaskBasedData(const OTFormat &oriData, std::vector<UnifiedTaskPmu> &processedData, |
| 60 | - std::string columnName, const uint16_t &deviceId); | 64 | + std::string columnName, const uint16_t &deviceId, const Utils::ProfTimeRecord &record); |
| 61 | bool SampleBasedProcess(const std::string &fileDir); | 65 | bool SampleBasedProcess(const std::string &fileDir); |
| 62 | - bool SampleBasedTimelineProcess( | 66 | + bool SampleBasedTimelineProcess(const std::unordered_map<std::string, std::tuple<uint16_t, uint64_t>> &dbPathTable, |
| 63 | - const std::unordered_map<std::string, std::tuple<uint16_t, uint64_t>> &dbPathTable, | 67 | + DataInventory &dataInventory); |
| 64 | - DataInventory &dataInventory); | ||
| 65 | UnifiedPmuProcessor::OSTFormat GetSampleBasedTimelineData(const std::string &dbPath); | 68 | UnifiedPmuProcessor::OSTFormat GetSampleBasedTimelineData(const std::string &dbPath); |
| 66 | bool FormatSampleBasedTimelineData(const OSTFormat &oriData, std::vector<UnifiedSampleTimelinePmu> &processedData, | 69 | bool FormatSampleBasedTimelineData(const OSTFormat &oriData, std::vector<UnifiedSampleTimelinePmu> &processedData, |
| 67 | const Utils::LocaltimeContext &localtimeContext, const double freq, | 70 | const Utils::LocaltimeContext &localtimeContext, const double freq, |
| @@ -73,7 +76,7 @@ private: | |||
| 73 | const uint16_t deviceId, const uint64_t coreType); | 76 | const uint16_t deviceId, const uint64_t coreType); |
| 74 | }; | 77 | }; |
| 75 | 78 | ||
| 76 | -} // Domain | 79 | +} // namespace Domain |
| 77 | -} // Analysis | 80 | +} // namespace Analysis |
| 78 | 81 | ||
| 79 | -#endif // ANALYSIS_DOMAIN_UNIFIED_PMU_PROCESSOR_H | 82 | +#endif // ANALYSIS_DOMAIN_UNIFIED_PMU_PROCESSOR_H |
| @@ -19,24 +19,32 @@ | |||
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | + | ||
| 22 | 23 | ||
| 23 | 24 | ||
| 24 | 25 | ||
| 25 | -namespace Analysis { | 26 | +namespace Analysis |
| 26 | -namespace Domain { | 27 | +{ |
| 28 | +namespace Domain | ||
| 29 | +{ | ||
| 27 | 30 | ||
| 28 | -struct PmuBaseInfo { | 31 | +struct PmuBaseInfo |
| 32 | +{ | ||
| 29 | AcceleratorType type = INVALID; | 33 | AcceleratorType type = INVALID; |
| 34 | + // 关联的 context PMU 时间,由 context 侧 syscnt 换算后的 wall-clock 时间(ns) | ||
| 35 | + uint64_t timestamp = 0; | ||
| 30 | virtual ~PmuBaseInfo() = default; | 36 | virtual ~PmuBaseInfo() = default; |
| 31 | }; | 37 | }; |
| 32 | 38 | ||
| 33 | -struct PmuInfoSingleAccelerator : public PmuBaseInfo { | 39 | +struct PmuInfoSingleAccelerator : public PmuBaseInfo |
| 40 | +{ | ||
| 34 | double totalTime = 0; | 41 | double totalTime = 0; |
| 35 | uint64_t totalCycles = 0; | 42 | uint64_t totalCycles = 0; |
| 36 | std::vector<double> pmuResult; | 43 | std::vector<double> pmuResult; |
| 37 | }; | 44 | }; |
| 38 | 45 | ||
| 39 | -struct PmuInfoMixAccelerator : public PmuBaseInfo { | 46 | +struct PmuInfoMixAccelerator : public PmuBaseInfo |
| 47 | +{ | ||
| 40 | uint32_t totalBlockCount = 0; | 48 | uint32_t totalBlockCount = 0; |
| 41 | uint64_t mainTimestamp = 0; | 49 | uint64_t mainTimestamp = 0; |
| 42 | double aiCoreTime = 0; | 50 | double aiCoreTime = 0; |
| @@ -46,6 +54,6 @@ struct PmuInfoMixAccelerator : public PmuBaseInfo { | |||
| 46 | std::vector<double> aicPmuResult; | 54 | std::vector<double> aicPmuResult; |
| 47 | std::vector<double> aivPmuResult; | 55 | std::vector<double> aivPmuResult; |
| 48 | }; | 56 | }; |
| 49 | -} | 57 | +} // namespace Domain |
| 50 | -} | 58 | +} // namespace Analysis |
| 51 | -#endif // MSPROF_ANALYSIS_PMU_INFO_H | 59 | +#endif // MSPROF_ANALYSIS_PMU_INFO_H |
| @@ -21,12 +21,16 @@ | |||
| 21 | 21 | ||
| 22 | 22 | ||
| 23 | 23 | ||
| 24 | - | ||
| 25 | - | ||
| 26 | 24 | ||
| 27 | -namespace Analysis { | 25 | +#include "analysis/csrc/domain/entities/viewer_data/basic_data.h" |
| 28 | -namespace Domain { | 26 | +#include "analysis/csrc/domain/valueobject/include/task_id.h" |
| 29 | -struct UnifiedTaskPmu { | 27 | + |
| 28 | +namespace Analysis | ||
| 29 | +{ | ||
| 30 | +namespace Domain | ||
| 31 | +{ | ||
| 32 | +struct UnifiedTaskPmu | ||
| 33 | +{ | ||
| 30 | uint16_t deviceId = UINT16_MAX; | 34 | uint16_t deviceId = UINT16_MAX; |
| 31 | uint32_t streamId = UINT32_MAX; | 35 | uint32_t streamId = UINT32_MAX; |
| 32 | uint32_t taskId = UINT32_MAX; | 36 | uint32_t taskId = UINT32_MAX; |
| @@ -34,15 +38,24 @@ struct UnifiedTaskPmu { | |||
| 34 | uint32_t batchId = UINT32_MAX; | 38 | uint32_t batchId = UINT32_MAX; |
| 35 | double value = 0.0; | 39 | double value = 0.0; |
| 36 | std::string header; | 40 | std::string header; |
| 41 | + // 算子 context PMU 时间,换算后的 wall-clock ns,随每行 metric 重复落盘到 TASK_PMU_INFO.timestampNs | ||
| 42 | + uint64_t timestamp = 0; | ||
| 37 | 43 | ||
| 38 | UnifiedTaskPmu() = default; | 44 | UnifiedTaskPmu() = default; |
| 39 | UnifiedTaskPmu(uint16_t deviceId_, uint32_t streamId_, uint32_t taskId_, uint32_t subtaskId_, uint32_t batchId_, | 45 | UnifiedTaskPmu(uint16_t deviceId_, uint32_t streamId_, uint32_t taskId_, uint32_t subtaskId_, uint32_t batchId_, |
| 40 | - std::string header_, double value_) : deviceId(deviceId_), streamId(streamId_), | 46 | + std::string header_, double value_, uint64_t timestamp_ = 0) |
| 41 | - taskId(taskId_), subtaskId(subtaskId_), batchId(batchId_), | 47 | + : deviceId(deviceId_), |
| 42 | - header(std::move(header_)), value(value_) {}; | 48 | + streamId(streamId_), |
| 49 | + taskId(taskId_), | ||
| 50 | + subtaskId(subtaskId_), | ||
| 51 | + batchId(batchId_), | ||
| 52 | + header(std::move(header_)), | ||
| 53 | + value(value_), | ||
| 54 | + timestamp(timestamp_) {}; | ||
| 43 | }; | 55 | }; |
| 44 | 56 | ||
| 45 | -struct UnifiedSampleTimelinePmu : public BasicData { | 57 | +struct UnifiedSampleTimelinePmu : public BasicData |
| 58 | +{ | ||
| 46 | uint16_t deviceId = UINT16_MAX; | 59 | uint16_t deviceId = UINT16_MAX; |
| 47 | uint16_t coreId = UINT16_MAX; | 60 | uint16_t coreId = UINT16_MAX; |
| 48 | double usage = 0.0; | 61 | double usage = 0.0; |
| @@ -51,13 +64,19 @@ struct UnifiedSampleTimelinePmu : public BasicData { | |||
| 51 | uint64_t coreType = UINT64_MAX; | 64 | uint64_t coreType = UINT64_MAX; |
| 52 | 65 | ||
| 53 | UnifiedSampleTimelinePmu() = default; | 66 | UnifiedSampleTimelinePmu() = default; |
| 54 | - UnifiedSampleTimelinePmu(uint16_t deviceId_, uint64_t timestamp_, uint64_t totalCycle_, double usage_, | 67 | + UnifiedSampleTimelinePmu(uint16_t deviceId_, uint64_t timestamp_, uint64_t totalCycle_, double usage_, double freq_, |
| 55 | - double freq_, uint16_t coreId_, uint64_t coreType_) | 68 | + uint16_t coreId_, uint64_t coreType_) |
| 56 | - : BasicData(timestamp_), deviceId(deviceId_), totalCycle(totalCycle_), usage(usage_), | 69 | + : BasicData(timestamp_), |
| 57 | - freq(freq_), coreId(coreId_), coreType(coreType_) {}; | 70 | + deviceId(deviceId_), |
| 71 | + totalCycle(totalCycle_), | ||
| 72 | + usage(usage_), | ||
| 73 | + freq(freq_), | ||
| 74 | + coreId(coreId_), | ||
| 75 | + coreType(coreType_) {}; | ||
| 58 | }; | 76 | }; |
| 59 | 77 | ||
| 60 | -struct UnifiedSampleSummaryPmu { | 78 | +struct UnifiedSampleSummaryPmu |
| 79 | +{ | ||
| 61 | uint16_t deviceId = UINT16_MAX; | 80 | uint16_t deviceId = UINT16_MAX; |
| 62 | uint16_t coreId = UINT16_MAX; | 81 | uint16_t coreId = UINT16_MAX; |
| 63 | double value = 0.0; | 82 | double value = 0.0; |
| @@ -66,9 +85,9 @@ struct UnifiedSampleSummaryPmu { | |||
| 66 | 85 | ||
| 67 | UnifiedSampleSummaryPmu() = default; | 86 | UnifiedSampleSummaryPmu() = default; |
| 68 | UnifiedSampleSummaryPmu(uint16_t deviceId_, std::string metric_, double value_, uint16_t coreId_, | 87 | UnifiedSampleSummaryPmu(uint16_t deviceId_, std::string metric_, double value_, uint16_t coreId_, |
| 69 | - uint64_t coreType_) : deviceId(deviceId_), metric(std::move(metric_)), | 88 | + uint64_t coreType_) |
| 70 | - value(value_), coreId(coreId_), coreType(coreType_) {}; | 89 | + : deviceId(deviceId_), metric(std::move(metric_)), value(value_), coreId(coreId_), coreType(coreType_) {}; |
| 71 | }; | 90 | }; |
| 72 | -} | 91 | +} // namespace Domain |
| 73 | -} | 92 | +} // namespace Analysis |
| 74 | -#endif // MSPROF_ANALYSIS_UNIFIED_PMU_DATA_H | 93 | +#endif // MSPROF_ANALYSIS_UNIFIED_PMU_DATA_H |
| @@ -42,7 +42,6 @@ namespace | |||
| 42 | const uint64_t DEFAULT_MODEL_ID = UINT32_MAX; | 42 | const uint64_t DEFAULT_MODEL_ID = UINT32_MAX; |
| 43 | const int32_t DEFAULT_INDEX_ID = -1; | 43 | const int32_t DEFAULT_INDEX_ID = -1; |
| 44 | const int64_t DEFAULT_CONNECTION_ID = -1; | 44 | const int64_t DEFAULT_CONNECTION_ID = -1; |
| 45 | -const uint64_t MILLI_SECOND = 1000; | ||
| 46 | const std::unordered_map<uint32_t, std::string> deviceTaskAcsqTypeMap{ | 45 | const std::unordered_map<uint32_t, std::string> deviceTaskAcsqTypeMap{ |
| 47 | {0, "AI_CORE"}, {1, "AI_CPU"}, {2, "AIV_SQE"}, {3, "PLACE_HOLDER_SQE"}, | 46 | {0, "AI_CORE"}, {1, "AI_CPU"}, {2, "AIV_SQE"}, {3, "PLACE_HOLDER_SQE"}, |
| 48 | {4, "EVENT_RECORD_SQE"}, {5, "EVENT_WAIT_SQE"}, {6, "NOTIFY_RECORD_SQE"}, {7, "NOTIFY_WAIT_SQE"}, | 47 | {4, "EVENT_RECORD_SQE"}, {5, "EVENT_WAIT_SQE"}, {6, "NOTIFY_RECORD_SQE"}, {7, "NOTIFY_WAIT_SQE"}, |
| @@ -66,28 +65,6 @@ const std::unordered_map<uint32_t, std::string> deviceTaskFftsPlusTypeMap{{0, "A | |||
| 66 | {13, "Load Context"}, | 65 | {13, "Load Context"}, |
| 67 | {15, "DSA"}}; | 66 | {15, "DSA"}}; |
| 68 | 67 | ||
| 69 | -SyscntConversionParams GetSyscntConversionParams(const DeviceContext& context) | ||
| 70 | -{ | ||
| 71 | - CpuInfo cpuInfo; | ||
| 72 | - context.Getter(cpuInfo); | ||
| 73 | - HostStartLog hostStartLog; | ||
| 74 | - context.Getter(hostStartLog); | ||
| 75 | - uint64_t hostMonotonic = hostStartLog.clockMonotonicRaw; | ||
| 76 | - DeviceInfo deviceInfo; | ||
| 77 | - context.Getter(deviceInfo); | ||
| 78 | - DeviceStartLog deviceStartLog; | ||
| 79 | - context.Getter(deviceStartLog); | ||
| 80 | - if (!IsDoubleEqual(cpuInfo.frequency, 0.0) && hostStartLog.cntVctDiff) | ||
| 81 | - { | ||
| 82 | - uint64_t diffTime = static_cast<uint64_t>(hostStartLog.cntVctDiff * MILLI_SECOND / cpuInfo.frequency); | ||
| 83 | - if (UINT64_MAX - hostStartLog.clockMonotonicRaw >= diffTime) | ||
| 84 | - { | ||
| 85 | - hostMonotonic = hostStartLog.clockMonotonicRaw + diffTime; | ||
| 86 | - } | ||
| 87 | - } | ||
| 88 | - SyscntConversionParams params{deviceInfo.hwtsFrequency, deviceStartLog.cntVct, hostMonotonic}; | ||
| 89 | - return params; | ||
| 90 | -} | ||
| 91 | } // namespace | 68 | } // namespace |
| 92 | 69 | ||
| 93 | std::string GetDeviceTaskTypeStr(const DeviceTask& task) | 70 | std::string GetDeviceTaskTypeStr(const DeviceTask& task) |
| @@ -224,7 +201,7 @@ void FillDeviceTaskStreamId(std::shared_ptr<HostStreamInfo> streamIdInfo, | |||
| 224 | uint32_t AscendTaskAssociation::ProcessEntry(DataInventory& dataInventory, const Context& context) | 201 | uint32_t AscendTaskAssociation::ProcessEntry(DataInventory& dataInventory, const Context& context) |
| 225 | { | 202 | { |
| 226 | const DeviceContext& deviceContext = static_cast<const DeviceContext&>(context); | 203 | const DeviceContext& deviceContext = static_cast<const DeviceContext&>(context); |
| 227 | - auto params = GetSyscntConversionParams(deviceContext); | 204 | + auto params = deviceContext.GetSyscntConversionParams(); |
| 228 | auto hostTasks = dataInventory.GetPtr<std::map<TaskId, std::vector<HostTask>>>(); | 205 | auto hostTasks = dataInventory.GetPtr<std::map<TaskId, std::vector<HostTask>>>(); |
| 229 | auto deviceTasks = dataInventory.GetPtr<std::map<TaskId, std::vector<DeviceTask>>>(); | 206 | auto deviceTasks = dataInventory.GetPtr<std::map<TaskId, std::vector<DeviceTask>>>(); |
| 230 | if (deviceContext.isChipV6()) | 207 | if (deviceContext.isChipV6()) |
| @@ -24,6 +24,7 @@ | |||
| 24 | 24 | ||
| 25 | 25 | ||
| 26 | 26 | ||
| 27 | + | ||
| 27 | 28 | ||
| 28 | namespace Analysis | 29 | namespace Analysis |
| 29 | { | 30 | { |
| @@ -51,6 +52,8 @@ class PmuAssociation : public Process | |||
| 51 | std::map<TaskId, std::vector<HalPmuData*>> blockPmuTask_; | 52 | std::map<TaskId, std::vector<HalPmuData*>> blockPmuTask_; |
| 52 | std::unique_ptr<MetricCalculator> aicCalculator_; | 53 | std::unique_ptr<MetricCalculator> aicCalculator_; |
| 53 | std::unique_ptr<MetricCalculator> aivCalculator_; | 54 | std::unique_ptr<MetricCalculator> aivCalculator_; |
| 55 | + // context侧 syscnt 转 wall-clock 的换算参数,ProcessEntry 中按 deviceContext 计算一次 | ||
| 56 | + Analysis::Utils::SyscntConversionParams syscntParams_; | ||
| 54 | }; | 57 | }; |
| 55 | } // namespace Domain | 58 | } // namespace Domain |
| 56 | } // namespace Analysis | 59 | } // namespace Analysis |
| @@ -152,6 +152,8 @@ void PmuAssociation::CalculateContextPmu(HalPmuData& pmuData, DeviceTask& task, | |||
| 152 | { | 152 | { |
| 153 | task.acceleratorType = pmuData.pmu.acceleratorType; | 153 | task.acceleratorType = pmuData.pmu.acceleratorType; |
| 154 | CalculationElements params; | 154 | CalculationElements params; |
| 155 | + // 始终取 context 侧 PMU 时间(hd.timestamp),换算成 wall-clock ns 后随 pmuInfo 供下游落盘 | ||
| 156 | + uint64_t contextTimeNs = GetTimeFromSyscnt(pmuData.hd.timestamp, syscntParams_).Uint64(); | ||
| 155 | if (task.acceleratorType == MIX_AIC || task.acceleratorType == MIX_AIV) | 157 | if (task.acceleratorType == MIX_AIC || task.acceleratorType == MIX_AIV) |
| 156 | { | 158 | { |
| 157 | PmuInfoMixAccelerator pmuInfoMix; | 159 | PmuInfoMixAccelerator pmuInfoMix; |
| @@ -170,6 +172,7 @@ void PmuAssociation::CalculateContextPmu(HalPmuData& pmuData, DeviceTask& task, | |||
| 170 | pmuInfoMix.aivTime = params.totalTime; | 172 | pmuInfoMix.aivTime = params.totalTime; |
| 171 | } | 173 | } |
| 172 | pmuInfoMix.mainTimestamp = pmuData.pmu.timeList[1]; | 174 | pmuInfoMix.mainTimestamp = pmuData.pmu.timeList[1]; |
| 175 | + pmuInfoMix.timestamp = contextTimeNs; | ||
| 173 | task.pmuInfo = MAKE_UNIQUE_PTR<PmuInfoMixAccelerator>(pmuInfoMix); | 176 | task.pmuInfo = MAKE_UNIQUE_PTR<PmuInfoMixAccelerator>(pmuInfoMix); |
| 174 | } | 177 | } |
| 175 | else | 178 | else |
| @@ -187,6 +190,7 @@ void PmuAssociation::CalculateContextPmu(HalPmuData& pmuData, DeviceTask& task, | |||
| 187 | } | 190 | } |
| 188 | pmuInfoNormal.totalTime = params.totalTime; | 191 | pmuInfoNormal.totalTime = params.totalTime; |
| 189 | pmuInfoNormal.pmuResult.swap(res); | 192 | pmuInfoNormal.pmuResult.swap(res); |
| 193 | + pmuInfoNormal.timestamp = contextTimeNs; | ||
| 190 | task.pmuInfo = MAKE_UNIQUE_PTR<PmuInfoSingleAccelerator>(pmuInfoNormal); | 194 | task.pmuInfo = MAKE_UNIQUE_PTR<PmuInfoSingleAccelerator>(pmuInfoNormal); |
| 191 | } | 195 | } |
| 192 | } | 196 | } |
| @@ -196,6 +200,8 @@ void PmuAssociation::CalculateContextPmuV6(HalPmuData& pmuData, DeviceTask& task | |||
| 196 | { | 200 | { |
| 197 | task.acceleratorType = pmuData.pmu.acceleratorType; | 201 | task.acceleratorType = pmuData.pmu.acceleratorType; |
| 198 | CalculationElements params; | 202 | CalculationElements params; |
| 203 | + // 始终取 context 侧 PMU 时间(hd.timestamp),换算成 wall-clock ns 后随 pmuInfo 供下游落盘 | ||
| 204 | + uint64_t contextTimeNs = GetTimeFromSyscnt(pmuData.hd.timestamp, syscntParams_).Uint64(); | ||
| 199 | if (task.acceleratorType == MIX_AIC || task.acceleratorType == MIX_AIV) | 205 | if (task.acceleratorType == MIX_AIC || task.acceleratorType == MIX_AIV) |
| 200 | { | 206 | { |
| 201 | // mix场景:同一task有两个PMU(AIC+AIV),需要合并而非覆盖 | 207 | // mix场景:同一task有两个PMU(AIC+AIV),需要合并而非覆盖 |
| @@ -240,6 +246,7 @@ void PmuAssociation::CalculateContextPmuV6(HalPmuData& pmuData, DeviceTask& task | |||
| 240 | } | 246 | } |
| 241 | } | 247 | } |
| 242 | pmuInfoMix.mainTimestamp = pmuData.pmu.timeList[1]; | 248 | pmuInfoMix.mainTimestamp = pmuData.pmu.timeList[1]; |
| 249 | + pmuInfoMix.timestamp = contextTimeNs; | ||
| 243 | task.pmuInfo = MAKE_UNIQUE_PTR<PmuInfoMixAccelerator>(pmuInfoMix); | 250 | task.pmuInfo = MAKE_UNIQUE_PTR<PmuInfoMixAccelerator>(pmuInfoMix); |
| 244 | } | 251 | } |
| 245 | else | 252 | else |
| @@ -259,6 +266,7 @@ void PmuAssociation::CalculateContextPmuV6(HalPmuData& pmuData, DeviceTask& task | |||
| 259 | } | 266 | } |
| 260 | pmuInfoNormal.totalTime = params.totalTime; | 267 | pmuInfoNormal.totalTime = params.totalTime; |
| 261 | pmuInfoNormal.pmuResult.swap(res); | 268 | pmuInfoNormal.pmuResult.swap(res); |
| 269 | + pmuInfoNormal.timestamp = contextTimeNs; | ||
| 262 | task.pmuInfo = MAKE_UNIQUE_PTR<PmuInfoSingleAccelerator>(pmuInfoNormal); | 270 | task.pmuInfo = MAKE_UNIQUE_PTR<PmuInfoSingleAccelerator>(pmuInfoNormal); |
| 263 | } | 271 | } |
| 264 | } | 272 | } |
| @@ -438,6 +446,7 @@ uint32_t PmuAssociation::ProcessEntry(Infra::DataInventory& dataInventory, const | |||
| 438 | } | 446 | } |
| 439 | } | 447 | } |
| 440 | } | 448 | } |
| 449 | + syscntParams_ = deviceContext.GetSyscntConversionParams(); | ||
| 441 | SplitPmu(*pmuData); | 450 | SplitPmu(*pmuData); |
| 442 | if (deviceContext.GetChipID() != CHIP_V4_1_0) | 451 | if (deviceContext.GetChipID() != CHIP_V4_1_0) |
| 443 | { | 452 | { |
| @@ -22,6 +22,8 @@ | |||
| 22 | 22 | ||
| 23 | 23 | ||
| 24 | 24 | ||
| 25 | + | ||
| 26 | + | ||
| 25 | 27 | ||
| 26 | namespace Analysis | 28 | namespace Analysis |
| 27 | { | 29 | { |
| @@ -196,6 +198,27 @@ class DeviceContext : public Infra::Context | |||
| 196 | 198 | ||
| 197 | std::string GetDeviceFilePath() const { return this->deviceContextInfo.deviceFilePath; } | 199 | std::string GetDeviceFilePath() const { return this->deviceContextInfo.deviceFilePath; } |
| 198 | 200 | ||
| 201 | + // 获取 syscnt 转 wall-clock 所需的换算参数,源数据取自本 context 已加载的 host/device 启动日志 | ||
| 202 | + // 内联实现以复用宿主数据的换算逻辑,避免各调用侧重复定义相同换算代码 | ||
| 203 | + Analysis::Utils::SyscntConversionParams GetSyscntConversionParams() const | ||
| 204 | + { | ||
| 205 | + uint64_t hostMonotonic = deviceContextInfo.hostStartLog.clockMonotonicRaw; | ||
| 206 | + // host侧高频计数导致 host 单调时钟与实际开机时长存在偏差,用 cntVctDiff 校正 | ||
| 207 | + if (!Analysis::Utils::IsDoubleEqual(deviceContextInfo.cpuInfo.frequency, 0.0) && | ||
| 208 | + deviceContextInfo.hostStartLog.cntVctDiff) | ||
| 209 | + { | ||
| 210 | + uint64_t diffTime = | ||
| 211 | + static_cast<uint64_t>(deviceContextInfo.hostStartLog.cntVctDiff * Analysis::Common::MILLI_SECOND / | ||
| 212 | + deviceContextInfo.cpuInfo.frequency); | ||
| 213 | + if (UINT64_MAX - deviceContextInfo.hostStartLog.clockMonotonicRaw >= diffTime) | ||
| 214 | + { | ||
| 215 | + hostMonotonic = deviceContextInfo.hostStartLog.clockMonotonicRaw + diffTime; | ||
| 216 | + } | ||
| 217 | + } | ||
| 218 | + return Analysis::Utils::SyscntConversionParams(deviceContextInfo.deviceInfo.hwtsFrequency, | ||
| 219 | + deviceContextInfo.deviceStart.cntVct, hostMonotonic); | ||
| 220 | + } | ||
| 221 | + | ||
| 199 | const std::string &GetDfxStopAtName() const override { return deviceContextInfo.dfxInfo.stopAt; } | 222 | const std::string &GetDfxStopAtName() const override { return deviceContextInfo.dfxInfo.stopAt; } |
| 200 | 223 | ||
| 201 | bool Init(const std::string &devicePath); | 224 | bool Init(const std::string &devicePath); |
| @@ -22,7 +22,6 @@ | |||
| 22 | 22 | ||
| 23 | 23 | ||
| 24 | 24 | ||
| 25 | - | ||
| 26 | 25 | ||
| 27 | 26 | ||
| 28 | 27 | ||
| @@ -56,7 +55,7 @@ bool QosParserBase::ParseDataItem(uint8_t *binaryData, | |||
| 56 | uint32_t QosParserBase::ParseData(Infra::DataInventory &dataInventory, const Infra::Context &context) | 55 | uint32_t QosParserBase::ParseData(Infra::DataInventory &dataInventory, const Infra::Context &context) |
| 57 | { | 56 | { |
| 58 | const DeviceContext &deviceContext = static_cast<const DeviceContext &>(context); | 57 | const DeviceContext &deviceContext = static_cast<const DeviceContext &>(context); |
| 59 | - const Utils::SyscntConversionParams timeParams = GenerateSyscntConversionParams(deviceContext); | 58 | + const Utils::SyscntConversionParams timeParams = deviceContext.GetSyscntConversionParams(); |
| 60 | const size_t recordCount = binaryDataSize / Analysis::QOS_STRUCT_SIZE; | 59 | const size_t recordCount = binaryDataSize / Analysis::QOS_STRUCT_SIZE; |
| 61 | const size_t remainingBytes = binaryDataSize % Analysis::QOS_STRUCT_SIZE; | 60 | const size_t remainingBytes = binaryDataSize % Analysis::QOS_STRUCT_SIZE; |
| 62 | if (remainingBytes != 0) | 61 | if (remainingBytes != 0) |
| @@ -36,7 +36,7 @@ using ProcessedDataFormat = std::vector<std::tuple<uint16_t, uint64_t, uint64_t, | |||
| 36 | 36 | ||
| 37 | ProcessedDataFormat GenerateAccPmuData(std::vector<HalLogData>& logData, const DeviceContext& context) | 37 | ProcessedDataFormat GenerateAccPmuData(std::vector<HalLogData>& logData, const DeviceContext& context) |
| 38 | { | 38 | { |
| 39 | - auto params = GenerateSyscntConversionParams(context); | 39 | + auto params = context.GetSyscntConversionParams(); |
| 40 | ProcessedDataFormat processedData; | 40 | ProcessedDataFormat processedData; |
| 41 | for (auto& data : logData) | 41 | for (auto& data : logData) |
| 42 | { | 42 | { |
| @@ -40,29 +40,6 @@ namespace | |||
| 40 | { | 40 | { |
| 41 | static const std::string MI_NAME = "GetNext_dequeue_wait"; | 41 | static const std::string MI_NAME = "GetNext_dequeue_wait"; |
| 42 | static const std::string EMPTY_NAME; | 42 | static const std::string EMPTY_NAME; |
| 43 | -SyscntConversionParams GetSyscntConversionParams(const DeviceContext& context) | ||
| 44 | -{ | ||
| 45 | - CpuInfo cpuInfo; | ||
| 46 | - context.Getter(cpuInfo); | ||
| 47 | - HostStartLog hostStartLog; | ||
| 48 | - context.Getter(hostStartLog); | ||
| 49 | - uint64_t hostMonotonic = hostStartLog.clockMonotonicRaw; | ||
| 50 | - DeviceInfo deviceInfo; | ||
| 51 | - context.Getter(deviceInfo); | ||
| 52 | - DeviceStartLog deviceStartLog; | ||
| 53 | - context.Getter(deviceStartLog); | ||
| 54 | - if (!IsDoubleEqual(cpuInfo.frequency, 0.0) && hostStartLog.cntVctDiff) | ||
| 55 | - { | ||
| 56 | - uint64_t diffTime = static_cast<uint64_t>(hostStartLog.cntVctDiff * MILLI_SECOND / cpuInfo.frequency); | ||
| 57 | - if (UINT64_MAX - hostStartLog.clockMonotonicRaw >= diffTime) | ||
| 58 | - { | ||
| 59 | - hostMonotonic = hostStartLog.clockMonotonicRaw + diffTime; | ||
| 60 | - } | ||
| 61 | - } | ||
| 62 | - SyscntConversionParams params{deviceInfo.hwtsFrequency, deviceStartLog.cntVct, hostMonotonic}; | ||
| 63 | - return params; | ||
| 64 | -} | ||
| 65 | - | ||
| 66 | // stream_id, task_id, sys_start, sys_end, node_name, compute_time, memcpy_time, task_time, dispatch_time, total_time | 43 | // stream_id, task_id, sys_start, sys_end, node_name, compute_time, memcpy_time, task_time, dispatch_time, total_time |
| 67 | // 时间列全部为 ns;compute/memcpy/dispatch 的 payload 为 us,乘 1000 转 ns | 44 | // 时间列全部为 ns;compute/memcpy/dispatch 的 payload 为 us,乘 1000 转 ns |
| 68 | using NodeFormat = | 45 | using NodeFormat = |
| @@ -767,7 +744,7 @@ uint32_t AicpuPersistence::ProcessEntry(DataInventory& dataInventory, const Cont | |||
| 767 | ERROR("There is no aicpu data, don't need to persistence"); | 744 | ERROR("There is no aicpu data, don't need to persistence"); |
| 768 | return ANALYSIS_ERROR; | 745 | return ANALYSIS_ERROR; |
| 769 | } | 746 | } |
| 770 | - params_ = GetSyscntConversionParams(deviceContext); | 747 | + params_ = deviceContext.GetSyscntConversionParams(); |
| 771 | hostStreamInfo_ = *hostStreamInfo; | 748 | hostStreamInfo_ = *hostStreamInfo; |
| 772 | deviceStreamInfo_ = *deviceStreamInfo; | 749 | deviceStreamInfo_ = *deviceStreamInfo; |
| 773 | geHashMap_ = *geHashMap; | 750 | geHashMap_ = *geHashMap; |
| @@ -68,7 +68,7 @@ bool GenerateLowPowerData(const std::vector<HalSocProfileData>& source, const De | |||
| 68 | ERROR("Reserve for LowPower persistence data failed"); | 68 | ERROR("Reserve for LowPower persistence data failed"); |
| 69 | return false; | 69 | return false; |
| 70 | } | 70 | } |
| 71 | - const auto params = GenerateSyscntConversionParams(context); | 71 | + const auto params = context.GetSyscntConversionParams(); |
| 72 | for (const auto& item : source) | 72 | for (const auto& item : source) |
| 73 | { | 73 | { |
| 74 | if (item.type != SOC_PROFILE_LOW_POWER) | 74 | if (item.type != SOC_PROFILE_LOW_POWER) |
| @@ -89,6 +89,10 @@ bool MetricSummaryPersistence::BindAndExecuteInsert(std::unordered_map<PmuHeader | |||
| 89 | { | 89 | { |
| 90 | sqlite3_bind_double(stmt_, ++index, value); | 90 | sqlite3_bind_double(stmt_, ++index, value); |
| 91 | } | 91 | } |
| 92 | + for (auto& value : ids[PMU_TIMESTAMP]) | ||
| 93 | + { | ||
| 94 | + sqlite3_bind_int64(stmt_, ++index, value); | ||
| 95 | + } | ||
| 92 | auto rc = sqlite3_step(stmt_); | 96 | auto rc = sqlite3_step(stmt_); |
| 93 | if (rc != SQLITE_DONE) | 97 | if (rc != SQLITE_DONE) |
| 94 | { | 98 | { |
| @@ -158,6 +162,8 @@ bool MetricSummaryPersistence::ConstructData(std::unordered_map<PmuHeaderType, s | |||
| 158 | { | 162 | { |
| 159 | return false; | 163 | return false; |
| 160 | } | 164 | } |
| 165 | + // end_time列绑定在表末尾,此处对齐追加,值为context PMU时间换算后的wall-clock ns | ||
| 166 | + ids[PMU_TIMESTAMP].push_back(task.pmuInfo->timestamp); | ||
| 161 | return true; | 167 | return true; |
| 162 | } | 168 | } |
| 163 | 169 | ||
| @@ -192,6 +198,8 @@ TableColumns MetricSummaryPersistence::GetTableColumn(const DeviceContext& conte | |||
| 192 | { | 198 | { |
| 193 | res.emplace_back((AIV_PREFIX + str), SQL_NUMERIC_TYPE); | 199 | res.emplace_back((AIV_PREFIX + str), SQL_NUMERIC_TYPE); |
| 194 | } | 200 | } |
| 201 | + // 附加列放到最后,避免影响原有字段顺序;列名统一为end_time,与python侧stars落库列名保持一致 | ||
| 202 | + res.emplace_back("end_time", SQL_INTEGER_TYPE); | ||
| 195 | } | 203 | } |
| 196 | return res; | 204 | return res; |
| 197 | } | 205 | } |
| @@ -314,7 +322,7 @@ uint32_t MetricSummaryPersistence::SaveV6BlockPmuData(DataInventory& dataInvento | |||
| 314 | ERROR("Hal pmu data is null."); | 322 | ERROR("Hal pmu data is null."); |
| 315 | return ANALYSIS_ERROR; | 323 | return ANALYSIS_ERROR; |
| 316 | } | 324 | } |
| 317 | - const auto params = GenerateSyscntConversionParams(deviceContext); | 325 | + const auto params = deviceContext.GetSyscntConversionParams(); |
| 318 | if (IsDoubleEqual(params.freq, 0.0)) | 326 | if (IsDoubleEqual(params.freq, 0.0)) |
| 319 | { | 327 | { |
| 320 | ERROR("Invalid hwts frequency %, skip saving V6BlockPmu.", params.freq); | 328 | ERROR("Invalid hwts frequency %, skip saving V6BlockPmu.", params.freq); |
| @@ -36,7 +36,8 @@ enum PmuHeaderType | |||
| 36 | AIC_PMU_RESULT, | 36 | AIC_PMU_RESULT, |
| 37 | AIV_TOTAL_CYCLE, | 37 | AIV_TOTAL_CYCLE, |
| 38 | AIV_TOTAL_TIME, | 38 | AIV_TOTAL_TIME, |
| 39 | - AIV_PMU_RESULT | 39 | + AIV_PMU_RESULT, |
| 40 | + PMU_TIMESTAMP | ||
| 40 | }; | 41 | }; |
| 41 | // V6BlockPmu表落盘数据行: stream_id, task_id, subtask_id, batch_id, start_time, duration, core_type, core_id | 42 | // V6BlockPmu表落盘数据行: stream_id, task_id, subtask_id, batch_id, start_time, duration, core_type, core_id |
| 42 | using V6BlockPmuData = std::tuple<uint32_t, uint32_t, uint32_t, uint32_t, uint64_t, double, uint8_t, uint8_t>; | 43 | using V6BlockPmuData = std::tuple<uint32_t, uint32_t, uint32_t, uint32_t, uint64_t, double, uint8_t, uint8_t>; |
| @@ -15,32 +15,3 @@ | |||
| 15 | * -------------------------------------------------------------------------*/ | 15 | * -------------------------------------------------------------------------*/ |
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | - | ||
| 19 | -namespace Analysis { | ||
| 20 | -namespace Domain { | ||
| 21 | -namespace { | ||
| 22 | -const uint64_t MILLI_SECOND = 1000; | ||
| 23 | -} | ||
| 24 | - | ||
| 25 | -SyscntConversionParams GenerateSyscntConversionParams(const DeviceContext& context) | ||
| 26 | -{ | ||
| 27 | - CpuInfo cpuInfo; | ||
| 28 | - context.Getter(cpuInfo); | ||
| 29 | - HostStartLog hostStartLog; | ||
| 30 | - context.Getter(hostStartLog); | ||
| 31 | - uint64_t hostMonotonic = hostStartLog.clockMonotonicRaw; | ||
| 32 | - DeviceInfo deviceInfo; | ||
| 33 | - context.Getter(deviceInfo); | ||
| 34 | - DeviceStartLog deviceStartLog; | ||
| 35 | - context.Getter(deviceStartLog); | ||
| 36 | - if (!IsDoubleEqual(cpuInfo.frequency, 0.0) && hostStartLog.cntVctDiff) { | ||
| 37 | - uint64_t diffTime = static_cast<uint64_t>(hostStartLog.cntVctDiff * MILLI_SECOND / cpuInfo.frequency); | ||
| 38 | - if (UINT64_MAX - hostStartLog.clockMonotonicRaw >= diffTime) { | ||
| 39 | - hostMonotonic = hostStartLog.clockMonotonicRaw + diffTime; | ||
| 40 | - } | ||
| 41 | - } | ||
| 42 | - SyscntConversionParams params{deviceInfo.hwtsFrequency, deviceStartLog.cntVct, hostMonotonic}; | ||
| 43 | - return params; | ||
| 44 | -} | ||
| 45 | -} | ||
| 46 | -} | ||
| @@ -71,8 +71,6 @@ bool SaveData(const std::vector<std::tuple<Args...>>& data, DBInfo& dbInfo, std: | |||
| 71 | } | 71 | } |
| 72 | return true; | 72 | return true; |
| 73 | } | 73 | } |
| 74 | - | ||
| 75 | -SyscntConversionParams GenerateSyscntConversionParams(const DeviceContext& context); | ||
| 76 | } // namespace Domain | 74 | } // namespace Domain |
| 77 | } // namespace Analysis | 75 | } // namespace Analysis |
| 78 | 76 | ||
| @@ -124,7 +124,7 @@ bool SaveTaskFlipData(const std::vector<HalTrackData>& dataS, const DeviceContex | |||
| 124 | MAKE_SHARED0_RETURN_VALUE(tsTrackDB.database, StepTraceDB, ANALYSIS_ERROR); | 124 | MAKE_SHARED0_RETURN_VALUE(tsTrackDB.database, StepTraceDB, ANALYSIS_ERROR); |
| 125 | std::string dbPath = Utils::File::PathJoin({deviceContext.GetDeviceFilePath(), SQLITE, tsTrackDB.dbName}); | 125 | std::string dbPath = Utils::File::PathJoin({deviceContext.GetDeviceFilePath(), SQLITE, tsTrackDB.dbName}); |
| 126 | MAKE_SHARED_RETURN_VALUE(tsTrackDB.dbRunner, DBRunner, ANALYSIS_ERROR, dbPath); | 126 | MAKE_SHARED_RETURN_VALUE(tsTrackDB.dbRunner, DBRunner, ANALYSIS_ERROR, dbPath); |
| 127 | - auto params = GenerateSyscntConversionParams(deviceContext); | 127 | + auto params = deviceContext.GetSyscntConversionParams(); |
| 128 | std::vector<TaskFlipDataFormat> taskFlips; | 128 | std::vector<TaskFlipDataFormat> taskFlips; |
| 129 | for (const auto& data : dataS) | 129 | for (const auto& data : dataS) |
| 130 | { | 130 | { |
| @@ -47,7 +47,7 @@ from mscalculate.aic.aic_utils import AicPmuUtils | |||
| 47 | from mscalculate.aic.pmu_calculator import PmuCalculator | 47 | from mscalculate.aic.pmu_calculator import PmuCalculator |
| 48 | from mscalculate.calculate_ai_core_data import CalculateAiCoreData | 48 | from mscalculate.calculate_ai_core_data import CalculateAiCoreData |
| 49 | from mscalculate.flip.flip_calculator import FlipCalculator | 49 | from mscalculate.flip.flip_calculator import FlipCalculator |
| 50 | -from msmodel.aic.aic_pmu_model import AicPmuModel | 50 | +from msmodel.aic.aic_pmu_model import FftsV1PmuModel |
| 51 | from msmodel.freq.freq_parser_model import FreqParserModel | 51 | from msmodel.freq.freq_parser_model import FreqParserModel |
| 52 | from msmodel.iter_rec.iter_rec_model import HwtsIterModel | 52 | from msmodel.iter_rec.iter_rec_model import HwtsIterModel |
| 53 | from msmodel.stars.ffts_pmu_model import FftsPmuModel | 53 | from msmodel.stars.ffts_pmu_model import FftsPmuModel |
| @@ -225,9 +225,6 @@ class FftsPmuCalculator(PmuCalculator, MsMultiProcess): | |||
| 225 | self.calculate_pmu_list(self.pmu_data) | 225 | self.calculate_pmu_list(self.pmu_data) |
| 226 | if ChipManager().is_chip_all_data_export() and InfoConfReader().is_all_export_version(): | 226 | if ChipManager().is_chip_all_data_export() and InfoConfReader().is_all_export_version(): |
| 227 | self.pmu_data = FlipCalculator.set_device_batch_id(self.pmu_data, self._result_dir) | 227 | self.pmu_data = FlipCalculator.set_device_batch_id(self.pmu_data, self._result_dir) |
| 228 | - if not self._is_mix_needed: | ||
| 229 | - # 去除timestamp字段 | ||
| 230 | - self.pmu_data = [pmu_data[:-1] for pmu_data in self.pmu_data] | ||
| 231 | 228 | ||
| 232 | def save(self: any) -> None: | 229 | def save(self: any) -> None: |
| 233 | """ | 230 | """ |
| @@ -677,7 +674,8 @@ class FftsPmuCalculator(PmuCalculator, MsMultiProcess): | |||
| 677 | self._block_num['mix_block_num'].setdefault(_key, []).append(int(data.mix_block_num)) | 674 | self._block_num['mix_block_num'].setdefault(_key, []).append(int(data.mix_block_num)) |
| 678 | 675 | ||
| 679 | def __update_model_instance(self): | 676 | def __update_model_instance(self): |
| 680 | - self._model = AicPmuModel(self._project_path) | 677 | + # 非mix(7/8/11)场景:AIC表尾追加end_time |
| 678 | + self._model = FftsV1PmuModel(self._project_path) | ||
| 681 | 679 | ||
| 682 | def _set_ffts_table_name_list(self): | 680 | def _set_ffts_table_name_list(self): |
| 683 | """ | 681 | """ |
| @@ -64,9 +64,6 @@ class V5AicPmuModel(AicPmuModel): | |||
| 64 | v5 pmu model. | 64 | v5 pmu model. |
| 65 | """ | 65 | """ |
| 66 | 66 | ||
| 67 | - def __init__(self: any, result_dir: str) -> None: | ||
| 68 | - super().__init__(result_dir) | ||
| 69 | - | ||
| 70 | def create_table(self: any) -> None: | 67 | def create_table(self: any) -> None: |
| 71 | """ | 68 | """ |
| 72 | create aic and aiv table by sample.json | 69 | create aic and aiv table by sample.json |
| @@ -76,3 +73,20 @@ class V5AicPmuModel(AicPmuModel): | |||
| 76 | aic_profiling_events = get_metrics_from_sample_config(self.result_dir) | 73 | aic_profiling_events = get_metrics_from_sample_config(self.result_dir) |
| 77 | column_list = AicPmuUtils.remove_unused_column(aic_profiling_events) | 74 | column_list = AicPmuUtils.remove_unused_column(aic_profiling_events) |
| 78 | create_metric_table(self.conn, column_list, DBNameConstant.TABLE_METRIC_SUMMARY) | 75 | create_metric_table(self.conn, column_list, DBNameConstant.TABLE_METRIC_SUMMARY) |
| 76 | + | ||
| 77 | + | ||
| 78 | +class FftsV1PmuModel(AicPmuModel): | ||
| 79 | + """ | ||
| 80 | + 7/8/11(V1.1.x) ffts 非mix场景的MetricSummary模型。 | ||
| 81 | + 在AIC表基础上于表尾追加end_time列,保存每算子context PMU的wall-clock结束时间, | ||
| 82 | + 供C++ unified task-pmu读取作为算子的时间(与chip5/chip6 python侧写end_time语义一致)。 | ||
| 83 | + """ | ||
| 84 | + | ||
| 85 | + def create_table(self: any) -> None: | ||
| 86 | + """ | ||
| 87 | + create aic metric table and append end_time column at the tail. | ||
| 88 | + :return: | ||
| 89 | + """ | ||
| 90 | + super().create_table() | ||
| 91 | + sql = "ALTER TABLE {0} ADD COLUMN end_time INT".format(DBNameConstant.TABLE_METRIC_SUMMARY) | ||
| 92 | + DBManager.execute_sql(self.conn, sql) | ||
C 【review】【编码】FftsV1PmuModel.create_table() 未检查 ALTER TABLE 返回值
![]() ![]() | |||
| @@ -391,6 +391,7 @@ The `--task-time`, `--hccl`, and `--ascendcl` options control the collection of | |||
| 391 | 391 | ||
| 392 | |Field|Type| Description | | 392 | |Field|Type| Description | |
| 393 | |--|--|------------------------------------------------------------------------| | 393 | |--|--|------------------------------------------------------------------------| |
| 394 | +|timestampNs|INTEGER| Start time of the small communication operator (ns). | | ||
| 394 | |name|INTEGER| Operator name, which maps to `STRING_IDS(name)`. | | 395 | |name|INTEGER| Operator name, which maps to `STRING_IDS(name)`. | |
| 395 | |globalTaskId|INTEGER| Global operator task ID, which is used as an index named `CommunicationTaskIndex` to associate with the `TASK` table. | | 396 | |globalTaskId|INTEGER| Global operator task ID, which is used as an index named `CommunicationTaskIndex` to associate with the `TASK` table. | |
| 396 | |taskType|INTEGER| Operator task type, which maps to `STRING_IDS(taskType)`. | | 397 | |taskType|INTEGER| Operator task type, which maps to `STRING_IDS(taskType)`. | |
| @@ -507,7 +508,7 @@ This table is controlled by `--sys-hardware-mem` and `--sys-hardware-mem-freq`. | |||
| 507 | |Field|Type|Description| | 508 | |Field|Type|Description| |
| 508 | |--|--|--| | 509 | |--|--|--| |
| 509 | |l2BufferBwLevel|INTEGER|L2 buffer bandwidth level| | 510 | |l2BufferBwLevel|INTEGER|L2 buffer bandwidth level| |
| 510 | -|mataBwLevel|INTEGER|Mata bandwidth level| | 511 | +|mataBwLevel|INTEGER|Mata bandwidth level| <!-- codespell:ignore --> |
| 511 | |timestampNs|NUMERIC|Local time (ns)| | 512 | |timestampNs|NUMERIC|Local time (ns)| |
| 512 | |deviceId|INTEGER|Device ID| | 513 | |deviceId|INTEGER|Device ID| |
| 513 | 514 | ||
| @@ -424,6 +424,7 @@ task数据,呈现所有硬件执行的算子信息。 | |||
| 424 | 424 | ||
| 425 | |字段名|类型| 含义 | | 425 | |字段名|类型| 含义 | |
| 426 | |--|--|------------------------------------------------------------------------| | 426 | |--|--|------------------------------------------------------------------------| |
| 427 | +|timestampNs|INTEGER| 通信小算子开始时间,单位ns | | ||
| 427 | |name|INTEGER| 算子名,STRING_IDS(name) | | 428 | |name|INTEGER| 算子名,STRING_IDS(name) | |
| 428 | |globalTaskId|INTEGER| 索引,索引名称CommunicationTaskIndex,全局算子任务ID,用于关联TASK表 | | 429 | |globalTaskId|INTEGER| 索引,索引名称CommunicationTaskIndex,全局算子任务ID,用于关联TASK表 | |
| 429 | |taskType|INTEGER| 算子类型,STRING_IDS(taskType) | | 430 | |taskType|INTEGER| 算子类型,STRING_IDS(taskType) | |
| @@ -634,6 +634,7 @@ static std::vector<UnifiedTaskPmu> GenerateUnifiedTaskPmuData() | |||
| 634 | data.batchId = 4294967295; // batchId 4294967295 | 634 | data.batchId = 4294967295; // batchId 4294967295 |
| 635 | data.header = "aic_total_time"; | 635 | data.header = "aic_total_time"; |
| 636 | data.value = 318360.0; // value 318360.0 | 636 | data.value = 318360.0; // value 318360.0 |
| 637 | + data.timestamp = 1701121739053206801; // context PMU时间换算后的wall-clock ns | ||
| 637 | res.push_back(data); | 638 | res.push_back(data); |
| 638 | return res; | 639 | return res; |
| 639 | } | 640 | } |
| @@ -1009,17 +1010,19 @@ TEST_F(DBAssemblerUTest, TestRunHcclDataShouldReturnTrueWhenRunSuccess) | |||
| 1009 | 1010 | ||
| 1010 | uint64_t expectName = IdPool::GetInstance().GetUint64Id("hcom_broadcast__674_0_1"); | 1011 | uint64_t expectName = IdPool::GetInstance().GetUint64Id("hcom_broadcast__674_0_1"); |
| 1011 | // 小算子数据 | 1012 | // 小算子数据 |
| 1012 | - // name, globalTaskId, taskType, planeId, groupName, notifyId, rdmaType, srcRank, dstRank, transportType, | 1013 | + // timestampNs, name, globalTaskId, taskType, planeId, groupName, notifyId, rdmaType, srcRank, dstRank, |
| 1013 | - // size, dataType, linkType, opId, isMaster, bandwidth | 1014 | + // transportType, size, dataType, linkType, opId, isMaster, bandwidth |
| 1014 | - using CommunicationTaskDataFormat = std::vector<std::tuple<uint64_t, uint64_t, uint64_t, uint32_t, uint64_t, | 1015 | + using CommunicationTaskDataFormat = |
| 1015 | - uint64_t, uint64_t, int64_t, int64_t, uint64_t, uint64_t, uint64_t, uint64_t, int64_t, uint16_t, | 1016 | + std::vector<std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, uint32_t, uint64_t, uint64_t, uint64_t, int64_t, |
| 1016 | - double>>; | 1017 | + int64_t, uint64_t, uint64_t, uint64_t, uint64_t, int64_t, uint16_t, double>>; |
| 1017 | CommunicationTaskDataFormat taskResult; | 1018 | CommunicationTaskDataFormat taskResult; |
| 1018 | std::string sql{"SELECT * FROM " + TABLE_NAME_COMMUNICATION_TASK_INFO}; | 1019 | std::string sql{"SELECT * FROM " + TABLE_NAME_COMMUNICATION_TASK_INFO}; |
| 1019 | std::shared_ptr<DBRunner> msprofDBRunner; | 1020 | std::shared_ptr<DBRunner> msprofDBRunner; |
| 1020 | MAKE_SHARED0_NO_OPERATION(msprofDBRunner, DBRunner, GetMsprofDbPath()); | 1021 | MAKE_SHARED0_NO_OPERATION(msprofDBRunner, DBRunner, GetMsprofDbPath()); |
| 1021 | msprofDBRunner->QueryData(sql, taskResult); | 1022 | msprofDBRunner->QueryData(sql, taskResult); |
| 1022 | - uint64_t opName = std::get<0>(taskResult[0]); | 1023 | + ASSERT_FALSE(taskResult.empty()); |
| 1024 | + EXPECT_EQ(std::get<0>(taskResult[0]), 1717575960213957957); | ||
| 1025 | + uint64_t opName = std::get<1>(taskResult[0]); | ||
| 1023 | EXPECT_EQ(expectName, opName); | 1026 | EXPECT_EQ(expectName, opName); |
| 1024 | 1027 | ||
| 1025 | // 大算子数据 | 1028 | // 大算子数据 |
| @@ -1036,11 +1039,11 @@ TEST_F(DBAssemblerUTest, TestRunHcclDataShouldReturnTrueWhenRunSuccess) | |||
| 1036 | TEST_F(DBAssemblerUTest, TestRunHcclDataShouldReturnFalseWhenReserveFailed) | 1039 | TEST_F(DBAssemblerUTest, TestRunHcclDataShouldReturnFalseWhenReserveFailed) |
| 1037 | { | 1040 | { |
| 1038 | // 小算子数据 | 1041 | // 小算子数据 |
| 1039 | - // name, globalTaskId, taskType, planeId, groupName, notifyId, rdmaType, srcRank, dstRank, transportType, | 1042 | + // timestampNs, name, globalTaskId, taskType, planeId, groupName, notifyId, rdmaType, srcRank, dstRank, |
| 1040 | - // size, dataType, linkType, opId, isMaster, bandwidth | 1043 | + // transportType, size, dataType, linkType, opId, isMaster, bandwidth |
| 1041 | - using CommunicationTaskDataFormat = std::vector<std::tuple<uint64_t, uint64_t, uint64_t, uint32_t, uint64_t, | 1044 | + using CommunicationTaskDataFormat = |
| 1042 | - uint64_t, uint64_t, int64_t, int64_t, uint64_t, uint64_t, uint64_t, uint64_t, int64_t, uint16_t, | 1045 | + std::vector<std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, uint32_t, uint64_t, uint64_t, uint64_t, int64_t, |
| 1043 | - double>>; | 1046 | + int64_t, uint64_t, uint64_t, uint64_t, uint64_t, int64_t, uint16_t, double>>; |
| 1044 | // 大算子数据 | 1047 | // 大算子数据 |
| 1045 | // opName, start, end, connectionId, group_name, opId, relay, retry, data_type, alg_type, count, op_type, deviceId, | 1048 | // opName, start, end, connectionId, group_name, opId, relay, retry, data_type, alg_type, count, op_type, deviceId, |
| 1046 | // rank_size | 1049 | // rank_size |
| @@ -1771,6 +1774,18 @@ TEST_F(DBAssemblerUTest, TestRunSaveTaskPmuDataShouldReturnTrueWhenRunSuccess) | |||
| 1771 | MAKE_SHARED0_NO_OPERATION(dataS, std::vector<UnifiedTaskPmu>, data); | 1774 | MAKE_SHARED0_NO_OPERATION(dataS, std::vector<UnifiedTaskPmu>, data); |
| 1772 | dataInventory.Inject<std::vector<UnifiedTaskPmu>>(dataS); | 1775 | dataInventory.Inject<std::vector<UnifiedTaskPmu>>(dataS); |
| 1773 | EXPECT_TRUE(assembler.Run(dataInventory)); | 1776 | EXPECT_TRUE(assembler.Run(dataInventory)); |
| 1777 | + | ||
| 1778 | + // 读回校验:TASK_PMU_INFO 表列为 timestampNs, globalTaskId, name(header), value | ||
| 1779 | + using TaskPmuResultFormat = std::vector<std::tuple<uint64_t, uint64_t, uint64_t, double>>; | ||
| 1780 | + TaskPmuResultFormat result; | ||
| 1781 | + std::string sql{"SELECT * FROM " + TABLE_NAME_TASK_PMU_INFO}; | ||
| 1782 | + std::shared_ptr<DBRunner> msprofDBRunner; | ||
| 1783 | + MAKE_SHARED0_NO_OPERATION(msprofDBRunner, DBRunner, GetMsprofDbPath()); | ||
| 1784 | + EXPECT_TRUE(msprofDBRunner->QueryData(sql, result)); | ||
| 1785 | + ASSERT_EQ(result.size(), data.size()); | ||
| 1786 | + EXPECT_EQ(std::get<0>(result[0]), data[0].timestamp); | ||
| 1787 | + EXPECT_EQ(std::get<2>(result[0]), IdPool::GetInstance().GetUint64Id(data[0].header)); | ||
| 1788 | + EXPECT_DOUBLE_EQ(std::get<3>(result[0]), data[0].value); | ||
| 1774 | } | 1789 | } |
| 1775 | 1790 | ||
| 1776 | TEST_F(DBAssemblerUTest, TestRunSaveSamplePmuTimelineDataShouldReturnTrueWhenRunSuccess) | 1791 | TEST_F(DBAssemblerUTest, TestRunSaveSamplePmuTimelineDataShouldReturnTrueWhenRunSuccess) |
| @@ -1797,7 +1812,8 @@ TEST_F(DBAssemblerUTest, TestRunSaveSamplePmuSummaryDataShouldReturnTrueWhenRunS | |||
| 1797 | 1812 | ||
| 1798 | TEST_F(DBAssemblerUTest, TestRunSaveTaskPmuDataShouldReturnFalseWhenReserveFailedThenDataIsEmpty) | 1813 | TEST_F(DBAssemblerUTest, TestRunSaveTaskPmuDataShouldReturnFalseWhenReserveFailedThenDataIsEmpty) |
| 1799 | { | 1814 | { |
| 1800 | - using PTFormat = std::vector<std::tuple<uint64_t, uint64_t, double>>; | 1815 | + // 与 SaveTaskPmuData 中 PTFormat 保持一致:timestampNs, globalTaskId, name(header), value |
| 1816 | + using PTFormat = std::vector<std::tuple<uint64_t, uint64_t, uint64_t, double>>; | ||
| 1801 | auto assembler = DBAssembler(PROF, File::PathJoin(std::vector<std::string>{PROF, OUTPUT_PATH})); | 1817 | auto assembler = DBAssembler(PROF, File::PathJoin(std::vector<std::string>{PROF, OUTPUT_PATH})); |
| 1802 | auto dataInventory = DataInventory(); | 1818 | auto dataInventory = DataInventory(); |
| 1803 | auto data = GenerateUnifiedTaskPmuData(); | 1819 | auto data = GenerateUnifiedTaskPmuData(); |
| @@ -2059,7 +2075,7 @@ TEST_F(DBAssemblerUTest, TestRunSaveDPUDataShouldReturnTrueWhenRunSuccess) | |||
| 2059 | EXPECT_TRUE(assembler.Run(dataInventory)); | 2075 | EXPECT_TRUE(assembler.Run(dataInventory)); |
C 【review】【测试】建议补充 info.json 缺失 pid 的边界用例
![]() ![]() | |||
| 2060 | 2076 | ||
| 2061 | // dpuDeviceId, globalTid, startNs, endNs, globalTaskId, streamId, taskId, opName, args | 2077 | // dpuDeviceId, globalTid, startNs, endNs, globalTaskId, streamId, taskId, opName, args |
| 2062 | - using DPUDataFormat = std::vector<std::tuple<uint16_t, uint32_t, uint64_t, uint64_t, | 2078 | + using DPUDataFormat = std::vector<std::tuple<uint16_t, uint64_t, uint64_t, uint64_t, |
| 2063 | uint64_t, uint32_t, uint32_t, uint64_t, uint64_t>>; | 2079 | uint64_t, uint32_t, uint32_t, uint64_t, uint64_t>>; |
| 2064 | DPUDataFormat dpuResult; | 2080 | DPUDataFormat dpuResult; |
| 2065 | std::shared_ptr<DBRunner> msprofDBRunner; | 2081 | std::shared_ptr<DBRunner> msprofDBRunner; |
| @@ -2070,13 +2086,13 @@ TEST_F(DBAssemblerUTest, TestRunSaveDPUDataShouldReturnTrueWhenRunSuccess) | |||
| 2070 | EXPECT_TRUE(msprofDBRunner->QueryData(sql, dpuResult)); | 2086 | EXPECT_TRUE(msprofDBRunner->QueryData(sql, dpuResult)); |
| 2071 | ASSERT_EQ(2, dpuResult.size()); | 2087 | ASSERT_EQ(2, dpuResult.size()); |
| 2072 | EXPECT_EQ(2, std::get<0>(dpuResult[0])); | 2088 | EXPECT_EQ(2, std::get<0>(dpuResult[0])); |
| 2073 | - EXPECT_EQ(123, std::get<1>(dpuResult[0])); | 2089 | + EXPECT_EQ(Contact(1, 123), std::get<1>(dpuResult[0])); // globalTid = pid(1)<<32 | threadId |
| 2074 | EXPECT_EQ(1717575960208020750, std::get<2>(dpuResult[0])); | 2090 | EXPECT_EQ(1717575960208020750, std::get<2>(dpuResult[0])); |
| 2075 | EXPECT_EQ(1717575960208021750, std::get<3>(dpuResult[0])); | 2091 | EXPECT_EQ(1717575960208021750, std::get<3>(dpuResult[0])); |
| 2076 | EXPECT_EQ(7, std::get<5>(dpuResult[0])); | 2092 | EXPECT_EQ(7, std::get<5>(dpuResult[0])); |
| 2077 | EXPECT_EQ(23, std::get<6>(dpuResult[0])); | 2093 | EXPECT_EQ(23, std::get<6>(dpuResult[0])); |
| 2078 | EXPECT_EQ(3, std::get<0>(dpuResult[1])); | 2094 | EXPECT_EQ(3, std::get<0>(dpuResult[1])); |
| 2079 | - EXPECT_EQ(124, std::get<1>(dpuResult[1])); | 2095 | + EXPECT_EQ(Contact(1, 124), std::get<1>(dpuResult[1])); // globalTid = pid(1)<<32 | threadId |
| 2080 | EXPECT_EQ(8, std::get<5>(dpuResult[1])); | 2096 | EXPECT_EQ(8, std::get<5>(dpuResult[1])); |
| 2081 | EXPECT_EQ(24, std::get<6>(dpuResult[1])); | 2097 | EXPECT_EQ(24, std::get<6>(dpuResult[1])); |
| 2082 | 2098 | ||
| @@ -2102,9 +2118,34 @@ TEST_F(DBAssemblerUTest, TestRunSaveDPUDataShouldReturnTrueWhenRunSuccess) | |||
| 2102 | EXPECT_NE(std::string::npos, hcclArgs.find("1024000")); | 2118 | EXPECT_NE(std::string::npos, hcclArgs.find("1024000")); |
| 2103 | } | 2119 | } |
| 2104 | 2120 | ||
| 2121 | +TEST_F(DBAssemblerUTest, TestRunSaveDPUDataShouldUseZeroPidWhenPidMissing) | ||
| 2122 | +{ | ||
| 2123 | + MOCKER_CPP(&Analysis::Domain::Environment::Context::GetPidFromInfoJson).stubs().will(returnValue(0u)); | ||
| 2124 | + auto assembler = DBAssembler(PROF, File::PathJoin(std::vector<std::string>{PROF, OUTPUT_PATH})); | ||
| 2125 | + auto dataInventory = DataInventory(); | ||
| 2126 | + auto data = GenerateDPUData(); | ||
| 2127 | + std::shared_ptr<std::vector<DPUData>> dataS; | ||
| 2128 | + MAKE_SHARED0_NO_OPERATION(dataS, std::vector<DPUData>, data); | ||
| 2129 | + dataInventory.Inject<std::vector<DPUData>>(dataS); | ||
| 2130 | + EXPECT_TRUE(assembler.Run(dataInventory)); | ||
| 2131 | + | ||
| 2132 | + using DPUDataFormat = std::vector<std::tuple<uint16_t, uint64_t, uint64_t, uint64_t, | ||
| 2133 | + uint64_t, uint32_t, uint32_t, uint64_t, uint64_t>>; | ||
| 2134 | + DPUDataFormat dpuResult; | ||
| 2135 | + std::shared_ptr<DBRunner> msprofDBRunner; | ||
| 2136 | + MAKE_SHARED0_NO_OPERATION(msprofDBRunner, DBRunner, GetMsprofDbPath()); | ||
| 2137 | + ASSERT_NE(msprofDBRunner, nullptr); | ||
| 2138 | + std::string sql = "SELECT dpuDeviceId, globalTid, startNs, endNs, globalTaskId, streamId, taskId, opName, args FROM " | ||
| 2139 | + + TABLE_NAME_DPU_TASK + " ORDER BY startNs"; | ||
| 2140 | + EXPECT_TRUE(msprofDBRunner->QueryData(sql, dpuResult)); | ||
| 2141 | + ASSERT_EQ(2, dpuResult.size()); | ||
| 2142 | + EXPECT_EQ(Contact(0, 123), std::get<1>(dpuResult[0])); | ||
| 2143 | + EXPECT_EQ(Contact(0, 124), std::get<1>(dpuResult[1])); | ||
| 2144 | +} | ||
| 2145 | + | ||
| 2105 | TEST_F(DBAssemblerUTest, TestRunSaveDPUDataShouldReturnFalseWhenReserveFailed) | 2146 | TEST_F(DBAssemblerUTest, TestRunSaveDPUDataShouldReturnFalseWhenReserveFailed) |
| 2106 | { | 2147 | { |
| 2107 | - using DPUDataFormat = std::vector<std::tuple<uint16_t, uint32_t, uint64_t, uint64_t, | 2148 | + using DPUDataFormat = std::vector<std::tuple<uint16_t, uint64_t, uint64_t, uint64_t, |
| 2108 | uint64_t, uint32_t, uint32_t, uint64_t, uint64_t>>; | 2149 | uint64_t, uint32_t, uint32_t, uint64_t, uint64_t>>; |
| 2109 | auto assembler = DBAssembler(PROF, File::PathJoin(std::vector<std::string>{PROF, OUTPUT_PATH})); | 2150 | auto assembler = DBAssembler(PROF, File::PathJoin(std::vector<std::string>{PROF, OUTPUT_PATH})); |
| 2110 | auto dataInventory = DataInventory(); | 2151 | auto dataInventory = DataInventory(); |
| @@ -31,9 +31,9 @@ using OSTFormat = std::vector<std::tuple<uint64_t, std::string, uint32_t>>; | |||
| 31 | // Original Sample Summary Format:aicore/ai_vector_core中的MetricSummary | 31 | // Original Sample Summary Format:aicore/ai_vector_core中的MetricSummary |
| 32 | // metric, value, coreid | 32 | // metric, value, coreid |
| 33 | using OSSFormat = std::vector<std::tuple<std::string, double, uint32_t>>; | 33 | using OSSFormat = std::vector<std::tuple<std::string, double, uint32_t>>; |
| 34 | -// Original Task Format: 只取id + 对应字段的value | 34 | +// Original Task Format: 只取id + 对应字段的value + 时间列end_time |
| 35 | -// stream_id, task_id, subtask_id, batch_id, value | 35 | +// stream_id, task_id, subtask_id, batch_id, value, end_time |
| 36 | -using OTFormat = std::vector<std::tuple<uint32_t, uint32_t, uint32_t, uint32_t, double>>; | 36 | +using OTFormat = std::vector<std::tuple<uint32_t, uint32_t, uint32_t, uint32_t, double, uint64_t>>; |
| 37 | // 手动设置task-based pmu表Format | 37 | // 手动设置task-based pmu表Format |
| 38 | // aic_total_time, aic_total_cycles, aic_mac_time, aic_mac_ratio_extra, | 38 | // aic_total_time, aic_total_cycles, aic_mac_time, aic_mac_ratio_extra, |
| 39 | // aiv_total_time, aiv_total_cycles, aiv_vec_time, aiv_vec_ratio, task_id, stream_id, subtask_id, | 39 | // aiv_total_time, aiv_total_cycles, aiv_vec_time, aiv_vec_ratio, task_id, stream_id, subtask_id, |
| @@ -170,6 +170,150 @@ TEST_F(UnifiedPmuProcessorUTest, TestTaskRunShouldReturnTrueWhenRunSuccess) | |||
| 170 | MOCKER_CPP(&Context::GetInfoByDeviceId).reset(); | 170 | MOCKER_CPP(&Context::GetInfoByDeviceId).reset(); |
| 171 | } | 171 | } |
| 172 | 172 | ||
| 173 | +TEST_F(UnifiedPmuProcessorUTest, TestTaskRunShouldCarryEndTimeForChipV1WithoutSubtaskColumn) | ||
| 174 | +{ | ||
| 175 | + // 7/8/11(chipV1)场景:python侧FftsV1落库的metric_summary无subtask_id列、时间在表尾end_time列 | ||
| 176 | + // C++读该表应回退subtask_id为UINT32_MAX常量,并读end_time使每条metric行携带所属算子的wall-clock时间 | ||
| 177 | + nlohmann::json record = { | ||
| 178 | + {"startCollectionTimeBegin", "1701069323851824"}, | ||
| 179 | + {"endCollectionTimeEnd", "1701069338041681"}, | ||
| 180 | + {"startClockMonotonicRaw", "36470610791630"}, | ||
| 181 | + {"DeviceInfo", {{{"aic_frequency", "1000"}}}}, | ||
| 182 | + {"ai_core_profiling_mode", TASK_BASED}, | ||
| 183 | + {"platform_version", "8"}, | ||
| 184 | + }; | ||
| 185 | + MOCKER_CPP(&Context::GetInfoByDeviceId).stubs().will(returnValue(record)); | ||
| 186 | + | ||
| 187 | + std::string profDir = File::PathJoin({UNIFIED_PMU_DIR, "PROF_TS_V1"}); | ||
| 188 | + std::string deviceDir = File::PathJoin({profDir, DEVICE_PREFIX + "0"}); | ||
| 189 | + std::string sqliteDir = File::PathJoin({deviceDir, SQLITE}); | ||
| 190 | + EXPECT_TRUE(File::CreateDir(profDir)); | ||
| 191 | + EXPECT_TRUE(File::CreateDir(deviceDir)); | ||
| 192 | + EXPECT_TRUE(File::CreateDir(sqliteDir)); | ||
| 193 | + std::shared_ptr<DBRunner> metricRunner; | ||
| 194 | + MAKE_SHARED0_NO_OPERATION(metricRunner, DBRunner, File::PathJoin({sqliteDir, "metric_summary.db"})); | ||
| 195 | + ASSERT_NE(metricRunner, nullptr); | ||
| 196 | + | ||
| 197 | + // 列顺序对齐python FftsV1 metric_summary:metric列/算子id列在前,无subtask_id列,end_time在表末尾 | ||
| 198 | + const TableColumns v1MetricSummary = { | ||
| 199 | + {"aic_total_time", SQL_NUMERIC_TYPE}, | ||
| 200 | + {"aiv_vec_time", SQL_NUMERIC_TYPE}, | ||
| 201 | + {"stream_id", SQL_INTEGER_TYPE}, | ||
| 202 | + {"task_id", SQL_INTEGER_TYPE}, | ||
| 203 | + {"core_type", SQL_INTEGER_TYPE}, | ||
| 204 | + {"batch_id", SQL_INTEGER_TYPE}, | ||
| 205 | + {"end_time", SQL_INTEGER_TYPE}, | ||
| 206 | + }; | ||
| 207 | + // aic_total_time, aiv_vec_time, stream_id, task_id, core_type, batch_id, end_time | ||
| 208 | + using V1TaskFormat = std::vector<std::tuple<double, double, uint32_t, uint32_t, uint32_t, uint32_t, uint64_t>>; | ||
| 209 | + const V1TaskFormat v1TaskData = { | ||
| 210 | + {318.36, 75.1, 68, 22, 0, 0, 1701121739053206801}, | ||
| 211 | + {313.94, 61.91, 68, 23, 0, 0, 1701121739053206803}, | ||
| 212 | + }; | ||
| 213 | + EXPECT_TRUE(metricRunner->CreateTable("MetricSummary", v1MetricSummary)); | ||
| 214 | + EXPECT_TRUE(metricRunner->InsertData("MetricSummary", v1TaskData)); | ||
| 215 | + | ||
| 216 | + DataInventory dataInventory; | ||
| 217 | + auto processor = UnifiedPmuProcessor(profDir); | ||
| 218 | + EXPECT_TRUE(processor.Run(dataInventory, PROCESSOR_NAME_UNIFIED_PMU)); | ||
| 219 | + | ||
| 220 | + // 2个metric列 × 2个算子行 = 4条metric,end_time列不作为metric行落盘 | ||
| 221 | + auto pmuData = dataInventory.GetPtr<std::vector<UnifiedTaskPmu>>(); | ||
| 222 | + ASSERT_NE(pmuData, nullptr); | ||
| 223 | + ASSERT_EQ(pmuData->size(), 4u); | ||
| 224 | + for (const auto &item : *pmuData) | ||
| 225 | + { | ||
| 226 | + EXPECT_NE(item.header, "end_time"); | ||
| 227 | + // chipV1无subtask_id列,读取时统一归一到UINT32_MAX,作为op四元组(subtask)取end_time | ||
| 228 | + EXPECT_EQ(item.subtaskId, UINT32_MAX); | ||
| 229 | + uint64_t expectTs = 0; | ||
| 230 | + // end_time列值为host开机monotonic ns,读侧经GetLocalTime叠加世界时偏移后才是与task对齐的时间: | ||
| 231 | + // 偏移 = startTimeNs - baseTimeNs = 1701069323851824000 - 36470610791630 = 1701032853241032370 | ||
| 232 | + constexpr uint64_t LOCAL_TIME_OFFSET = 1701032853241032370; | ||
| 233 | + if (item.taskId == 22) { | ||
| 234 | + expectTs = 1701121739053206801 + LOCAL_TIME_OFFSET; | ||
| 235 | + } else { | ||
| 236 | + ASSERT_EQ(item.taskId, 23u); | ||
| 237 | + expectTs = 1701121739053206803 + LOCAL_TIME_OFFSET; | ||
| 238 | + } | ||
| 239 | + // 同一算子的metric行携带同一end_time,不同算子各取各的 | ||
| 240 | + EXPECT_EQ(item.timestamp, expectTs); | ||
| 241 | + } | ||
| 242 | + MOCKER_CPP(&Context::GetInfoByDeviceId).reset(); | ||
| 243 | + EXPECT_TRUE(File::RemoveDir(profDir, 0)); | ||
| 244 | +} | ||
| 245 | + | ||
| 246 | +TEST_F(UnifiedPmuProcessorUTest, TestTaskRunShouldCarryEndTimeWhenMetricSummaryHasEndTimeColumn) | ||
| 247 | +{ | ||
| 248 | + // metric_summary统一以end_time为时间列(如C++侧metric_summary_persistence chipV4落库、python侧stars落库) | ||
| 249 | + // 该场景下每条metric行都应携带所属算子的end_time,end_time列不落成metric行 | ||
| 250 | + nlohmann::json record = { | ||
| 251 | + {"startCollectionTimeBegin", "1701069323851824"}, | ||
| 252 | + {"endCollectionTimeEnd", "1701069338041681"}, | ||
| 253 | + {"startClockMonotonicRaw", "36470610791630"}, | ||
| 254 | + {"DeviceInfo", {{{"aic_frequency", "1000"}}}}, | ||
| 255 | + {"ai_core_profiling_mode", TASK_BASED}, | ||
| 256 | + {"platform_version", "5"}, | ||
| 257 | + }; | ||
| 258 | + MOCKER_CPP(&Context::GetInfoByDeviceId).stubs().will(returnValue(record)); | ||
| 259 | + | ||
| 260 | + std::string profDir = File::PathJoin({UNIFIED_PMU_DIR, "PROF_TS_END"}); | ||
| 261 | + std::string deviceDir = File::PathJoin({profDir, DEVICE_PREFIX + "0"}); | ||
| 262 | + std::string sqliteDir = File::PathJoin({deviceDir, SQLITE}); | ||
| 263 | + EXPECT_TRUE(File::CreateDir(profDir)); | ||
| 264 | + EXPECT_TRUE(File::CreateDir(deviceDir)); | ||
| 265 | + EXPECT_TRUE(File::CreateDir(sqliteDir)); | ||
| 266 | + std::shared_ptr<DBRunner> metricRunner; | ||
| 267 | + MAKE_SHARED0_NO_OPERATION(metricRunner, DBRunner, File::PathJoin({sqliteDir, "metric_summary.db"})); | ||
| 268 | + ASSERT_NE(metricRunner, nullptr); | ||
| 269 | + | ||
| 270 | + // 列顺序对齐metric_summary:metric列/算子id列在前,end_time在表末尾 | ||
| 271 | + const TableColumns endTsMetricSummary = { | ||
| 272 | + {"aic_total_time", SQL_NUMERIC_TYPE}, | ||
| 273 | + {"aiv_vec_time", SQL_NUMERIC_TYPE}, | ||
| 274 | + {"task_id", SQL_INTEGER_TYPE}, | ||
| 275 | + {"stream_id", SQL_INTEGER_TYPE}, | ||
| 276 | + {"subtask_id", SQL_INTEGER_TYPE}, | ||
| 277 | + {"batch_id", SQL_INTEGER_TYPE}, | ||
| 278 | + {"end_time", SQL_INTEGER_TYPE}, | ||
| 279 | + }; | ||
| 280 | + // aic_total_time, aiv_vec_time, task_id, stream_id, subtask_id, batch_id, end_time | ||
| 281 | + using EndTsTaskFormat = std::vector<std::tuple<double, double, uint32_t, uint32_t, uint32_t, uint32_t, uint64_t>>; | ||
| 282 | + const EndTsTaskFormat endTsTaskData = { | ||
| 283 | + {318.36, 75.1, 22, 68, 2344, 0, 1701121739053206801}, | ||
| 284 | + {313.94, 61.91, 22, 68, 2357, 0, 1701121739053206803}, | ||
| 285 | + }; | ||
| 286 | + EXPECT_TRUE(metricRunner->CreateTable("MetricSummary", endTsMetricSummary)); | ||
| 287 | + EXPECT_TRUE(metricRunner->InsertData("MetricSummary", endTsTaskData)); | ||
| 288 | + | ||
| 289 | + DataInventory dataInventory; | ||
| 290 | + auto processor = UnifiedPmuProcessor(profDir); | ||
| 291 | + EXPECT_TRUE(processor.Run(dataInventory, PROCESSOR_NAME_UNIFIED_PMU)); | ||
| 292 | + | ||
| 293 | + // 2个metric列 × 2个算子行 = 4条metric,end_time列不作为metric行落盘 | ||
| 294 | + auto pmuData = dataInventory.GetPtr<std::vector<UnifiedTaskPmu>>(); | ||
| 295 | + ASSERT_NE(pmuData, nullptr); | ||
| 296 | + ASSERT_EQ(pmuData->size(), 4u); | ||
| 297 | + for (const auto &item : *pmuData) | ||
| 298 | + { | ||
| 299 | + EXPECT_NE(item.header, "end_time"); | ||
| 300 | + uint64_t expectTs = 0; | ||
| 301 | + // end_time列值为host开机monotonic ns,读侧经GetLocalTime叠加世界时偏移后才是与task对齐的时间: | ||
| 302 | + // 偏移 = startTimeNs - baseTimeNs = 1701069323851824000 - 36470610791630 = 1701032853241032370 | ||
| 303 | + constexpr uint64_t LOCAL_TIME_OFFSET = 1701032853241032370; | ||
| 304 | + if (item.subtaskId == 2344) { | ||
| 305 | + expectTs = 1701121739053206801 + LOCAL_TIME_OFFSET; | ||
| 306 | + } else { | ||
| 307 | + ASSERT_EQ(item.subtaskId, 2357u); | ||
| 308 | + expectTs = 1701121739053206803 + LOCAL_TIME_OFFSET; | ||
| 309 | + } | ||
| 310 | + // 同一算子的metric行携带同一end_time,不同算子各取各的 | ||
| 311 | + EXPECT_EQ(item.timestamp, expectTs); | ||
| 312 | + } | ||
| 313 | + MOCKER_CPP(&Context::GetInfoByDeviceId).reset(); | ||
| 314 | + EXPECT_TRUE(File::RemoveDir(profDir, 0)); | ||
| 315 | +} | ||
| 316 | + | ||
| 173 | TEST_F(UnifiedPmuProcessorUTest, TestTaskRunShouldReturnFalseWhenCheckColumnsFailed) | 317 | TEST_F(UnifiedPmuProcessorUTest, TestTaskRunShouldReturnFalseWhenCheckColumnsFailed) |
| 174 | { | 318 | { |
| 175 | nlohmann::json record = { | 319 | nlohmann::json record = { |
| @@ -18,6 +18,7 @@ from unittest import mock | |||
| 18 | 18 | ||
| 19 | from common_func.info_conf_reader import InfoConfReader | 19 | from common_func.info_conf_reader import InfoConfReader |
| 20 | from msmodel.aic.aic_pmu_model import AicPmuModel | 20 | from msmodel.aic.aic_pmu_model import AicPmuModel |
| 21 | +from msmodel.aic.aic_pmu_model import FftsV1PmuModel | ||
| 21 | 22 | ||
| 22 | NAMESPACE = 'msmodel.aic.aic_pmu_model' | 23 | NAMESPACE = 'msmodel.aic.aic_pmu_model' |
| 23 | 24 | ||
| @@ -52,3 +53,13 @@ class TestPcieModel(unittest.TestCase): | |||
| 52 | check = AicPmuModel('test') | 53 | check = AicPmuModel('test') |
| 53 | check.clear() | 54 | check.clear() |
| 54 | 55 | ||
| 56 | + def test_ffts_v1_create_table_should_append_end_time_column(self): | ||
| 57 | + # FftsV1PmuModel(7/8/11 ffts非mix)在AIC表基础上于表尾追加end_time,供unified task-pmu读取wall-clock时间 | ||
| 58 | + with mock.patch(NAMESPACE + '.AicPmuModel.create_table') as mock_base_create, \ | ||
| 59 | + mock.patch(NAMESPACE + '.DBManager.execute_sql') as mock_execute: | ||
| 60 | + check = FftsV1PmuModel('test') | ||
| 61 | + check.create_table() | ||
| 62 | + mock_base_create.assert_called_once() | ||
| 63 | + alter_sql = mock_execute.call_args[0][1] | ||
| 64 | + self.assertIn('ALTER TABLE MetricSummary ADD COLUMN end_time INT', alter_sql) | ||
| 65 | + | ||
| @@ -31,6 +31,7 @@ from common_func.profiling_scene import ExportMode | |||
| 31 | from common_func.profiling_scene import ProfilingScene | 31 | from common_func.profiling_scene import ProfilingScene |
| 32 | from constant.constant import CONFIG | 32 | from constant.constant import CONFIG |
| 33 | from mscalculate.stars.ffts_pmu_calculator import FftsPmuCalculator | 33 | from mscalculate.stars.ffts_pmu_calculator import FftsPmuCalculator |
| 34 | +from msmodel.aic.aic_pmu_model import FftsV1PmuModel | ||
| 34 | from profiling_bean.prof_enum.chip_model import ChipModel | 35 | from profiling_bean.prof_enum.chip_model import ChipModel |
| 35 | from profiling_bean.prof_enum.data_tag import DataTag | 36 | from profiling_bean.prof_enum.data_tag import DataTag |
| 36 | from profiling_bean.stars.ffts_block_pmu import FftsBlockPmuBean | 37 | from profiling_bean.stars.ffts_block_pmu import FftsBlockPmuBean |
| @@ -640,5 +641,42 @@ class TestFftsPmuCalculator(TestCase): | |||
| 640 | check.calculate_pmu_list(pmu_data_list) | 641 | check.calculate_pmu_list(pmu_data_list) |
| 641 | self.assertEqual(3, len(pmu_data_list)) | 642 | self.assertEqual(3, len(pmu_data_list)) |
| 642 | 643 | ||
| 644 | + def test_calculate_pmu_list_non_mix_should_use_ffts_v1_model_and_keep_end_time(self): | ||
| 645 | + # 7/8/11(V1.1.x) ffts非mix:__update_model_instance应切换到FftsV1PmuModel(AIC表尾带end_time列), | ||
| 646 | + # 且行尾保留每算子wall-clock结束时间(此前calculate()中会被[:-1]剥掉,导致unified读取落0) | ||
| 647 | + context_task = [ | ||
| 648 | + FftsPmuBean([0, 0, 1, 1, 0, 0, 4294967295, 8192, 0, 0, 1111, 0, | ||
| 649 | + 0, 0, 0, 0, 0, 0, 0, 0, 10000, 10100]), | ||
| 650 | + ] | ||
| 651 | + pmu_value = { | ||
| 652 | + "l0a_read_bw(GB/s)": [0], | ||
| 653 | + "l0a_write_bw(GB/s)": [0], | ||
| 654 | + "l0b_read_bw(GB/s)": [0], | ||
| 655 | + "l0b_write_bw(GB/s)": [0], | ||
| 656 | + "l0c_read_bw(GB/s)": [0], | ||
| 657 | + "l0c_read_bw_cube(GB/s)": [0], | ||
| 658 | + "l0c_write_bw(GB/s)": [0], | ||
| 659 | + "l0c_write_bw_cube(GB/s)": [0], | ||
| 660 | + } | ||
| 661 | + pmu_data_list = [None] * len(context_task) | ||
| 662 | + InfoConfReader()._info_json = {"DeviceInfo": [{'aic_frequency': 1500, 'hwts_frequency': 1000}]} | ||
| 663 | + with mock.patch("common_func.config_mgr.ConfigMgr.read_sample_config", return_value={}), \ | ||
| 664 | + mock.patch(NAMESPACE + '.FftsPmuCalculator._get_current_block', return_value=10), \ | ||
| 665 | + mock.patch(NAMESPACE + '.CalculateAiCoreData.compute_ai_core_data', return_value=[0, pmu_value]): | ||
| 666 | + check = FftsPmuCalculator(self.file_list, CONFIG) | ||
| 667 | + check._data_list['context_task'] = context_task | ||
| 668 | + check._freq = 1000 | ||
| 669 | + check._core_num_dict = { | ||
| 670 | + "aic": 1, | ||
| 671 | + "aiv": 1, | ||
| 672 | + } | ||
| 673 | + check.aic_table_name_list = list(pmu_value.keys()) | ||
| 674 | + check.calculate_pmu_list(pmu_data_list) | ||
| 675 | + self.assertIsInstance(check._model, FftsV1PmuModel) | ||
| 676 | + # 行尾字段为timestamp(即wall-clock结束时间),保留以按位落入表尾end_time列 | ||
| 677 | + self.assertEqual(pmu_data_list[0]._fields[-1], 'timestamp') | ||
| 678 | + self.assertEqual(pmu_data_list[0].timestamp, | ||
| 679 | + InfoConfReader().time_from_syscnt(context_task[0].time_list[1])) | ||
| 680 | + | ||
| 643 | if __name__ == '__main__': | 681 | if __name__ == '__main__': |
| 644 | unittest.main() | 682 | unittest.main() |
| @@ -36,6 +36,7 @@ class TableFields: | |||
| 36 | "rankSize", | 36 | "rankSize", |
| 37 | ] | 37 | ] |
| 38 | COMMUNICATION_TASK_INFO = [ | 38 | COMMUNICATION_TASK_INFO = [ |
| 39 | + "timestampNs", | ||
| 39 | "name", | 40 | "name", |
| 40 | "globalTaskId", | 41 | "globalTaskId", |
| 41 | "taskType", | 42 | "taskType", |
| @@ -246,7 +247,7 @@ class TableFields: | |||
| 246 | "taskId", | 247 | "taskId", |
| 247 | "modelId", | 248 | "modelId", |
| 248 | ] | 249 | ] |
| 249 | - TASK_PMU_INFO = ["globalTaskId", "name", "value"] | 250 | + TASK_PMU_INFO = ["timestampNs", "globalTaskId", "name", "value"] |
| 250 | RANK_DEVICE_MAP = ["rankId", "deviceId"] | 251 | RANK_DEVICE_MAP = ["rankId", "deviceId"] |
| 251 | ClusterCommunicationBandwidth = [ | 252 | ClusterCommunicationBandwidth = [ |
| 252 | "step", | 253 | "step", |


[review] [建议] [代码冗余] 问题:GetSyscntConversionParams 与 persistence_utils.cpp 中已有实现功能完全一致,存在重复定义。 修改建议:仅保留一份实现,删除重复函数,避免逻辑散落在多处,降低后续维护成本。