已合并
bugfix: aicpu交付件导出增加deviceId,保持和python解析结果一致 #497
wangzixuan创建于 22 天前
bugfix: aicpu交付件导出增加deviceId,保持和python解析结果一致 #497
已合并
wangzixuan创建于 22 天前
共 14 个文件变更+83-46
@@ -67,15 +67,16 @@ bool AicpuAssembler::WriteAicpuCsv(const std::vector<AicpuSummaryData> &data)
67 {67 {
68 return false;68 return false;
69 }69 }
70- headers_ = {"Timestamp(us)", "Node", "Compute_time(us)", "Memcpy_time(us)", "Task_time(us)",70+ headers_ = {"Device_id", "Timestamp(us)", "Node", "Compute_time(us)", "Memcpy_time(us)",
71- "Dispatch_time(us)", "Total_time(us)", "Stream ID", "Task ID"};71+ "Task_time(us)", "Dispatch_time(us)", "Total_time(us)", "Stream ID", "Task ID"};
72 res_.clear();72 res_.clear();
73 for (const auto &item : data)73 for (const auto &item : data)
74 {74 {
75 res_.emplace_back(std::vector<std::string>{75 res_.emplace_back(std::vector<std::string>{
76- DivideByPowersOfTenWithPrecision(item.timestampNs), item.nodeName, DoubleToStr(item.computeTimeUs),76+ std::to_string(item.deviceId), DivideByPowersOfTenWithPrecision(item.timestampNs, true), item.nodeName,
77- DoubleToStr(item.memcpyTimeUs), DoubleToStr(item.taskTimeUs), DoubleToStr(item.dispatchTimeUs),77+ DoubleToStr(item.computeTimeUs), DoubleToStr(item.memcpyTimeUs), DoubleToStr(item.taskTimeUs),
78- DoubleToStr(item.totalTimeUs), std::to_string(item.streamId), std::to_string(item.taskId)});78+ DoubleToStr(item.dispatchTimeUs), DoubleToStr(item.totalTimeUs), std::to_string(item.streamId),
79+ std::to_string(item.taskId)});
79 }80 }
80 WriteToFile(File::PathJoin({profPath_, Analysis::Common::OUTPUT_PATH, AICPU_NAME}), {});81 WriteToFile(File::PathJoin({profPath_, Analysis::Common::OUTPUT_PATH, AICPU_NAME}), {});
81 return true;82 return true;
@@ -87,11 +88,12 @@ bool AicpuAssembler::WriteDpCsv(const std::vector<AicpuDpData> &data)
87 {88 {
88 return false;89 return false;
89 }90 }
90- headers_ = {"Timestamp(us)", "Action", "Source", "Cached Buffer Size"};91+ headers_ = {"Device_id", "Timestamp(us)", "Action", "Source", "Cached Buffer Size"};
L
Lleo92032022 天前

【review】 【问题描述】aicpu/aicpu_dp/aicpu_mi CSV 新增 Device_id 列,与 python 侧列定义不一致 aicpu_assembler.cpp 、L91、L109 的 headers 均以 Device_id 开头并输出 item.deviceId (10/5/5 列),但 python 侧:

  • msprof_export_data_config.py 中 aicpu (9 列)、 dp (4 列)headers 均 不含 Device_id;
  • aicpu_viewer.py 的 python aicpu 输出列表也不含 deviceId。 验证结论:python 导出走 DB( _get_aicpu_data / _get_dp_data 读 ai_cpu.db 等),不读 C++ 生成的 CSV,当前无功能性错位;但 C++ 产物与 python 导出配置是两条独立通路,schema 已漂移,与提交目标"和 python 解析结果一致"存在矛盾。下游若按旧列序/配置解析 C++ 落盘文件会列错位。

【问题分类】功能实现

【修改建议】确认对齐目标:若以 python 列为准,则应同步更新 msprof_export_data_config.py 与 aicpu_viewer.py 的输出列(补充 Device_id),或明确 C++ CSV 与 python 导出为独立产物并在文档/配置中保持列定义一致。

likedislike
wangzixuan
21 天前 评论:
91 res_.clear();92 res_.clear();
92 for (const auto &item : data)93 for (const auto &item : data)
93 {94 {
94- res_.emplace_back(std::vector<std::string>{DivideByPowersOfTenWithPrecision(item.timestamp), item.action,95+ res_.emplace_back(std::vector<std::string>{std::to_string(item.deviceId),
96+ DivideByPowersOfTenWithPrecision(item.timestamp), item.action,
95 item.source, std::to_string(item.bufferSize)});97 item.source, std::to_string(item.bufferSize)});
96 }98 }
97 WriteToFile(File::PathJoin({profPath_, Analysis::Common::OUTPUT_PATH, AICPU_DP_NAME}), {});99 WriteToFile(File::PathJoin({profPath_, Analysis::Common::OUTPUT_PATH, AICPU_DP_NAME}), {});
@@ -104,12 +106,13 @@ bool AicpuAssembler::WriteMiCsv(const std::vector<AicpuMiData> &data)
104 {106 {
105 return false;107 return false;
106 }108 }
107- headers_ = {"Node Name", "Start Time(us)", "End Time(us)", "Queue Size"};109+ headers_ = {"Device_id", "Node Name", "Start Time(us)", "End Time(us)", "Queue Size"};
108 res_.clear();110 res_.clear();
109 for (const auto &item : data)111 for (const auto &item : data)
110 {112 {
111- res_.emplace_back(std::vector<std::string>{item.nodeName, std::to_string(item.startTime),113+ res_.emplace_back(std::vector<std::string>{std::to_string(item.deviceId), item.nodeName,
112- std::to_string(item.endTime), std::to_string(item.queueSize)});114+ std::to_string(item.startTime), std::to_string(item.endTime),
115+ std::to_string(item.queueSize)});
113 }116 }
114 WriteToFile(File::PathJoin({profPath_, Analysis::Common::OUTPUT_PATH, AICPU_MI_NAME}), {});117 WriteToFile(File::PathJoin({profPath_, Analysis::Common::OUTPUT_PATH, AICPU_MI_NAME}), {});
115 return true;118 return true;
@@ -49,7 +49,7 @@ uint8_t NpuMemoryAssembler::AssembleData(Analysis::Infra::DataInventory &dataInv
49 std::to_string(item.ddr / Analysis::Common::BYTE_SIZE),49 std::to_string(item.ddr / Analysis::Common::BYTE_SIZE),
50 std::to_string(item.hbm / Analysis::Common::BYTE_SIZE),50 std::to_string(item.hbm / Analysis::Common::BYTE_SIZE),
51 std::to_string(item.memory / Analysis::Common::BYTE_SIZE),51 std::to_string(item.memory / Analysis::Common::BYTE_SIZE),
52- DivideByPowersOfTenWithPrecision(item.timestamp) + "\t"});52+ DivideByPowersOfTenWithPrecision(item.timestamp, true)});
53 }53 }
54 if (res_.empty())54 if (res_.empty())
55 {55 {
@@ -67,7 +67,7 @@ uint8_t NpuModuleMemAssembler::AssembleData(DataInventory &dataInventory)
67 res_.emplace_back(std::vector<std::string>{67 res_.emplace_back(std::vector<std::string>{
68 std::to_string(item.deviceId),68 std::to_string(item.deviceId),
69 moduleMap_.find(item.moduleId) != moduleMap_.end() ? moduleMap_.at(item.moduleId) : UNKNOWN,69 moduleMap_.find(item.moduleId) != moduleMap_.end() ? moduleMap_.at(item.moduleId) : UNKNOWN,
70- DivideByPowersOfTenWithPrecision(item.timestamp) + "\t",70+ DivideByPowersOfTenWithPrecision(item.timestamp, true),
71 std::to_string(item.totalReserved / Analysis::Common::BYTE_SIZE), item.deviceType});71 std::to_string(item.totalReserved / Analysis::Common::BYTE_SIZE), item.deviceType});
72 }72 }
73 if (res_.empty())73 if (res_.empty())
@@ -287,11 +287,13 @@ void OpSummaryAssembler::CalculateWaitTime()
287void OpSummaryAssembler::WriteToFile(const std::string &fileName, const std::set<int> &maskCols)287void OpSummaryAssembler::WriteToFile(const std::string &fileName, const std::set<int> &maskCols)
288{288{
289 auto timeIndex = GetIndexForVec(headers_, TASK_START_TIME);289 auto timeIndex = GetIndexForVec(headers_, TASK_START_TIME);
290+ // TASK_START_TIME 是绝对时刻(us),追加\t强制Excel按文本处理避免精度丢失;
291+ // 必须在CalculateWaitTime完成数字解析/排序后再打标,否则尾部\t会导致StrToDouble失败
290 for (auto &row : res_)292 for (auto &row : res_)
291 {293 {
292 if (timeIndex < static_cast<int>(row.size()))294 if (timeIndex < static_cast<int>(row.size()))
293 {295 {
294- row[timeIndex].append("\t");296+ row[timeIndex] = FormatHighPrecisionForCsv(row[timeIndex]);
L
Lleo92032022 天前

【review】 【问题描述】WriteToFile 中 timeIndex 未排除 -1,存在 row[-1] 越界风险(UB) op_summary_assembler.cpp 中 GetIndexForVec 未命中返回 INVALID_VALUE = -1 ( common_constant.h ),此时 if (timeIndex < row.size()) 对 -1 恒为真,执行 row[timeIndex] = ... 即 row[-1] 越界访问。当前 TASK_START_TIME 恒在 BASE_HEADER 中(索引恒为 8)故不可达,但 guard 逻辑无法防御 -1 ,属潜伏性缺陷;本次提交修改该行时沿用了不安全写法。

【问题分类】健壮性(潜在内存安全)

【修改建议】guard 增加下界判断: if (timeIndex >= 0 && timeIndex < static_cast(row.size())) 。同文件 CalculateWaitTime 等处以 GetIndexForVec 取下标的地方建议一并核对。

likedislike
wangzixuan
21 天前 评论:
295 }297 }
296 }298 }
297 299 
@@ -131,15 +131,14 @@ void SummaryStepTraceAssembler::AssembleStepTraceData(const std::vector<TrainTra
131 return;131 return;
132 }132 }
133 133 
134- const std::string DIVIDE_CHAR = "\t";
135 for (auto &trainTraceDatum : trainTraceData)134 for (auto &trainTraceDatum : trainTraceData)
136 {135 {
137 TraceId traceId = {trainTraceDatum.modelId, trainTraceDatum.iterEnd};136 TraceId traceId = {trainTraceDatum.modelId, trainTraceDatum.iterEnd};
138 std::vector<std::string> row = {std::to_string(trainTraceDatum.deviceId),137 std::vector<std::string> row = {std::to_string(trainTraceDatum.deviceId),
139 std::to_string(trainTraceDatum.indexId),138 std::to_string(trainTraceDatum.indexId),
140- DivideByPowersOfTenWithPrecision(trainTraceDatum.fpStart) + DIVIDE_CHAR,139+ DivideByPowersOfTenWithPrecision(trainTraceDatum.fpStart, true),
141- DivideByPowersOfTenWithPrecision(trainTraceDatum.bpEnd) + DIVIDE_CHAR,140+ DivideByPowersOfTenWithPrecision(trainTraceDatum.bpEnd, true),
142- DivideByPowersOfTenWithPrecision(trainTraceDatum.iterEnd) + DIVIDE_CHAR,141+ DivideByPowersOfTenWithPrecision(trainTraceDatum.iterEnd, true),
143 DivideByPowersOfTenWithPrecision(trainTraceDatum.iterTime),142 DivideByPowersOfTenWithPrecision(trainTraceDatum.iterTime),
144 DivideByPowersOfTenWithPrecision(trainTraceDatum.fpBpTime),143 DivideByPowersOfTenWithPrecision(trainTraceDatum.fpBpTime),
145 DivideByPowersOfTenWithPrecision(trainTraceDatum.gradRefreshBound),144 DivideByPowersOfTenWithPrecision(trainTraceDatum.gradRefreshBound),
@@ -151,7 +150,7 @@ void SummaryStepTraceAssembler::AssembleStepTraceData(const std::vector<TrainTra
151 int count = 0;150 int count = 0;
152 for (auto &allReduceData : it->second)151 for (auto &allReduceData : it->second)
153 {152 {
154- row.emplace_back(allReduceData.first + DIVIDE_CHAR);153+ row.emplace_back(FormatHighPrecisionForCsv(allReduceData.first));
155 row.emplace_back(allReduceData.second);154 row.emplace_back(allReduceData.second);
156 ++count;155 ++count;
157 }156 }
@@ -193,7 +193,6 @@ void TaskTimeAssembler::AssembleTaskTime(const std::vector<AscendTaskData>& asce
193 return;193 return;
194 }194 }
195 195 
196- const std::string DIVIDE_CHAR = "\t";
197 for (auto& ascendTaskDatum : FilterAscendTaskData(ascendTaskData))196 for (auto& ascendTaskDatum : FilterAscendTaskData(ascendTaskData))
198 {197 {
199 TaskId taskId{ascendTaskDatum.streamId, ascendTaskDatum.batchId, ascendTaskDatum.taskId,198 TaskId taskId{ascendTaskDatum.streamId, ascendTaskDatum.batchId, ascendTaskDatum.taskId,
@@ -222,8 +221,8 @@ void TaskTimeAssembler::AssembleTaskTime(const std::vector<AscendTaskData>& asce
222 std::to_string(taskId.streamId),221 std::to_string(taskId.streamId),
223 std::to_string(taskId.taskId),222 std::to_string(taskId.taskId),
224 DivideByPowersOfTenWithPrecision(static_cast<uint64_t>(ascendTaskDatum.duration)),223 DivideByPowersOfTenWithPrecision(static_cast<uint64_t>(ascendTaskDatum.duration)),
225- DivideByPowersOfTenWithPrecision(ascendTaskDatum.timestamp) + DIVIDE_CHAR,224+ DivideByPowersOfTenWithPrecision(ascendTaskDatum.timestamp, true),
226- DivideByPowersOfTenWithPrecision(ascendTaskDatum.end) + DIVIDE_CHAR};225+ DivideByPowersOfTenWithPrecision(ascendTaskDatum.end, true)};
227 res_.emplace_back(row);226 res_.emplace_back(row);
228 }227 }
229}228}
@@ -95,8 +95,8 @@ bool AicpuProcessor::ProcessSingleDevice(const std::string &devicePath, std::vec
95 return false;95 return false;
96 }96 }
97 bool flag = LoadAiCpuData(devicePath, deviceId, timeRecord, summaryData);97 bool flag = LoadAiCpuData(devicePath, deviceId, timeRecord, summaryData);
98- flag = LoadDpData(devicePath, timeRecord, dpData) && flag;98+ flag = LoadDpData(devicePath, deviceId, timeRecord, dpData) && flag;
99- flag = LoadMiData(devicePath, miData) && flag;99+ flag = LoadMiData(devicePath, deviceId, miData) && flag;
100 return flag;100 return flag;
101}101}
102 102 
@@ -157,7 +157,7 @@ bool AicpuProcessor::LoadAiCpuData(const std::string &devicePath, uint16_t devic
157 return true;157 return true;
158}158}
159 159 
160-bool AicpuProcessor::LoadDpData(const std::string &devicePath, const ProfTimeRecord &timeRecord,160+bool AicpuProcessor::LoadDpData(const std::string &devicePath, uint16_t deviceId, const ProfTimeRecord &timeRecord,
161 std::vector<AicpuDpData> &dpData)161 std::vector<AicpuDpData> &dpData)
162{162{
163 DBInfo dpDB(DB_NAME_AI_CPU, TABLE_NAME_AI_CPU_DP);163 DBInfo dpDB(DB_NAME_AI_CPU, TABLE_NAME_AI_CPU_DP);
@@ -184,6 +184,7 @@ bool AicpuProcessor::LoadDpData(const std::string &devicePath, const ProfTimeRec
184 AicpuDpData data;184 AicpuDpData data;
185 double rawTimestamp = 0;185 double rawTimestamp = 0;
186 std::tie(rawTimestamp, data.action, data.source, data.bufferSize) = row;186 std::tie(rawTimestamp, data.action, data.source, data.bufferSize) = row;
187+ data.deviceId = deviceId;
187 HPFloat timestamp{rawTimestamp};188 HPFloat timestamp{rawTimestamp};
188 data.timestamp = GetLocalTime(timestamp, timeRecord).Uint64();189 data.timestamp = GetLocalTime(timestamp, timeRecord).Uint64();
189 dpData.push_back(data);190 dpData.push_back(data);
@@ -191,7 +192,7 @@ bool AicpuProcessor::LoadDpData(const std::string &devicePath, const ProfTimeRec
191 return true;192 return true;
192}193}
193 194 
194-bool AicpuProcessor::LoadMiData(const std::string &devicePath, std::vector<AicpuMiData> &miData)195+bool AicpuProcessor::LoadMiData(const std::string &devicePath, uint16_t deviceId, std::vector<AicpuMiData> &miData)
195{196{
196 DBInfo miDB(DB_NAME_DATA_PREPROCESS, TABLE_NAME_DATA_QUEUE);197 DBInfo miDB(DB_NAME_DATA_PREPROCESS, TABLE_NAME_DATA_QUEUE);
197 std::string dbPath = Utils::File::PathJoin({devicePath, SQLITE, miDB.dbName});198 std::string dbPath = Utils::File::PathJoin({devicePath, SQLITE, miDB.dbName});
@@ -219,6 +220,7 @@ bool AicpuProcessor::LoadMiData(const std::string &devicePath, std::vector<Aicpu
219 double startTime = 0;220 double startTime = 0;
220 double endTime = 0;221 double endTime = 0;
221 std::tie(data.nodeName, startTime, endTime, data.queueSize) = row;222 std::tie(data.nodeName, startTime, endTime, data.queueSize) = row;
223+ data.deviceId = deviceId;
222 data.startTime = static_cast<uint64_t>(startTime);224 data.startTime = static_cast<uint64_t>(startTime);
223 data.endTime = static_cast<uint64_t>(endTime);225 data.endTime = static_cast<uint64_t>(endTime);
224 miData.push_back(data);226 miData.push_back(data);
@@ -49,9 +49,9 @@ class AicpuProcessor : public DataProcessor
49 std::vector<AicpuDpData> &dpData, std::vector<AicpuMiData> &miData);49 std::vector<AicpuDpData> &dpData, std::vector<AicpuMiData> &miData);
50 bool LoadAiCpuData(const std::string &devicePath, uint16_t deviceId, const Utils::ProfTimeRecord &timeRecord,50 bool LoadAiCpuData(const std::string &devicePath, uint16_t deviceId, const Utils::ProfTimeRecord &timeRecord,
51 std::vector<AicpuSummaryData> &summaryData);51 std::vector<AicpuSummaryData> &summaryData);
52- bool LoadDpData(const std::string &devicePath, const Utils::ProfTimeRecord &timeRecord,52+ bool LoadDpData(const std::string &devicePath, uint16_t deviceId, const Utils::ProfTimeRecord &timeRecord,
53 std::vector<AicpuDpData> &dpData);53 std::vector<AicpuDpData> &dpData);
54- bool LoadMiData(const std::string &devicePath, std::vector<AicpuMiData> &miData);54+ bool LoadMiData(const std::string &devicePath, uint16_t deviceId, std::vector<AicpuMiData> &miData);
55 void MatchBatchId(std::vector<AicpuSummaryData> &summaryData, const std::vector<AscendTaskData> &ascendTasks);55 void MatchBatchId(std::vector<AicpuSummaryData> &summaryData, const std::vector<AscendTaskData> &ascendTasks);
56 void MatchNodeName(std::vector<AicpuSummaryData> &summaryData, const std::vector<TaskInfoData> &taskInfos,56 void MatchNodeName(std::vector<AicpuSummaryData> &summaryData, const std::vector<TaskInfoData> &taskInfos,
57 bool isChipV6);57 bool isChipV6);
@@ -42,6 +42,7 @@ struct AicpuSummaryData
42 42 
43struct AicpuDpData43struct AicpuDpData
44{44{
45+ uint16_t deviceId = UINT16_MAX;
45 uint64_t timestamp = 0;46 uint64_t timestamp = 0;
46 std::string action;47 std::string action;
47 std::string source;48 std::string source;
@@ -50,6 +51,7 @@ struct AicpuDpData
50 51 
51struct AicpuMiData52struct AicpuMiData
52{53{
54+ uint16_t deviceId = UINT16_MAX;
53 std::string nodeName;55 std::string nodeName;
54 uint64_t startTime = 0;56 uint64_t startTime = 0;
55 uint64_t endTime = 0;57 uint64_t endTime = 0;
@@ -187,7 +187,13 @@ bool IsDoubleEqual(double checkDouble, double standard)
187 187 
188std::string AddQuotation(std::string str) { return Join({"\"", str, "\""}, ""); }188std::string AddQuotation(std::string str) { return Join({"\"", str, "\""}, ""); }
189 189 
190-std::string DivideByPowersOfTenWithPrecision(uint64_t value, int accuracy, int scale)190+std::string FormatHighPrecisionForCsv(const std::string &value)
191+{
192+ // Excel 打开超过15位精度的数值时会丢精度,追加\t让 Excel 按文本处理该单元格
193+ return value + "\t";
194+}
195+ 
196+std::string DivideByPowersOfTenWithPrecision(uint64_t value, bool isHighPrecision, int accuracy, int scale)
191{197{
192 // scale代表除以10的多少次幂,比如3就是除以10^3,accuracy代表保留位数198 // scale代表除以10的多少次幂,比如3就是除以10^3,accuracy代表保留位数
193 std::string numStr = std::to_string(value);199 std::string numStr = std::to_string(value);
@@ -199,16 +205,17 @@ std::string DivideByPowersOfTenWithPrecision(uint64_t value, int accuracy, int s
199 numStr.insert(numStr.size() - scale, ".");205 numStr.insert(numStr.size() - scale, ".");
200 if (scale == accuracy)206 if (scale == accuracy)
201 { // 精度与移位数相等,直接返回即可207 { // 精度与移位数相等,直接返回即可
202- return numStr;208+ return isHighPrecision ? FormatHighPrecisionForCsv(numStr) : numStr;
203 }209 }
204 else if (accuracy > scale)210 else if (accuracy > scale)
205 { // 精度比移位数大,需要末尾补0211 { // 精度比移位数大,需要末尾补0
206 numStr.insert(numStr.end(), accuracy - scale, '0');212 numStr.insert(numStr.end(), accuracy - scale, '0');
207- return numStr;213+ return isHighPrecision ? FormatHighPrecisionForCsv(numStr) : numStr;
208 }214 }
209 else215 else
210 { // 精度比移位数小,需要截取numStr.size() - (scale - accuracy)长个字符串216 { // 精度比移位数小,需要截取numStr.size() - (scale - accuracy)长个字符串
211- return numStr.substr(0, numStr.size() + accuracy - scale);217+ std::string res = numStr.substr(0, numStr.size() + accuracy - scale);
218+ return isHighPrecision ? FormatHighPrecisionForCsv(res) : res;
212 }219 }
213}220}
214 221 
@@ -52,7 +52,13 @@ bool IsNumber(const std::string &s);
52uint64_t Contact(uint32_t high, uint32_t low);52uint64_t Contact(uint32_t high, uint32_t low);
53bool IsDoubleEqual(double checkDouble, double standard);53bool IsDoubleEqual(double checkDouble, double standard);
54std::string AddQuotation(std::string str);54std::string AddQuotation(std::string str);
55-std::string DivideByPowersOfTenWithPrecision(uint64_t value, int scale = ACCURACY_THREE, int accuracy = ACCURACY_THREE);55+// Excel 对超过15位的数字会丢精度,绝对时刻(us)转字符串后追加\t可强制按文本处理,与python format_high_precision_for_csv
56+// 对齐
57+std::string FormatHighPrecisionForCsv(const std::string &value);
58+// scale代表除以10的多少次幂(如3即除以10^3),accuracy代表保留位数;
59+// isHighPrecision为true时结果追加\t,用于绝对时刻列
60+std::string DivideByPowersOfTenWithPrecision(uint64_t value, bool isHighPrecision = false,
61+ int accuracy = ACCURACY_THREE, int scale = ACCURACY_THREE);
56bool EndsWith(const std::string &str, const std::string &suffix);62bool EndsWith(const std::string &str, const std::string &suffix);
57std::string DoubleToStr(const double &value, const uint16_t &scale = ACCURACY_THREE);63std::string DoubleToStr(const double &value, const uint16_t &scale = ACCURACY_THREE);
58double RoundToDecimalPlaces(const double num, int decimalPlaces = ACCURACY_THREE);64double RoundToDecimalPlaces(const double num, int decimalPlaces = ACCURACY_THREE);
@@ -43,10 +43,10 @@ const std::string PROF_PATH = File::PathJoin({BASE_PATH, "PROF_0"});
43const std::string RESULT_PATH = File::PathJoin({PROF_PATH, Analysis::Common::OUTPUT_PATH});43const std::string RESULT_PATH = File::PathJoin({PROF_PATH, Analysis::Common::OUTPUT_PATH});
44 44 
45const std::string AICPU_HEADER =45const std::string AICPU_HEADER =
46- "Timestamp(us),Node,Compute_time(us),Memcpy_time(us),Task_time(us),Dispatch_time(us),Total_time(us),Stream ID,Task "46+ "Device_id,Timestamp(us),Node,Compute_time(us),Memcpy_time(us),Task_time(us),Dispatch_time(us),Total_time(us),"
47- "ID";47+ "Stream ID,Task ID";
48-const std::string DP_HEADER = "Timestamp(us),Action,Source,Cached Buffer Size";48+const std::string DP_HEADER = "Device_id,Timestamp(us),Action,Source,Cached Buffer Size";
49-const std::string MI_HEADER = "Node Name,Start Time(us),End Time(us),Queue Size";49+const std::string MI_HEADER = "Device_id,Node Name,Start Time(us),End Time(us),Queue Size";
50 50 
51std::string FindCsvByName(const std::string &name)51std::string FindCsvByName(const std::string &name)
52{52{
@@ -114,6 +114,7 @@ std::vector<AicpuDpData> GenerateDpData()
114{114{
115 std::vector<AicpuDpData> res;115 std::vector<AicpuDpData> res;
116 AicpuDpData first;116 AicpuDpData first;
117+ first.deviceId = 0;
117 first.timestamp = 1000000;118 first.timestamp = 1000000;
118 first.action = "enqueue";119 first.action = "enqueue";
119 first.source = "src0";120 first.source = "src0";
@@ -121,6 +122,7 @@ std::vector<AicpuDpData> GenerateDpData()
121 res.push_back(first);122 res.push_back(first);
122 123 
123 AicpuDpData second;124 AicpuDpData second;
125+ second.deviceId = 0;
124 second.timestamp = 2500000;126 second.timestamp = 2500000;
125 second.action = "dequeue";127 second.action = "dequeue";
126 second.source = "src1";128 second.source = "src1";
@@ -133,6 +135,7 @@ std::vector<AicpuMiData> GenerateMiData()
133{135{
134 std::vector<AicpuMiData> res;136 std::vector<AicpuMiData> res;
135 AicpuMiData first;137 AicpuMiData first;
138+ first.deviceId = 0;
136 first.nodeName = "QueueA";139 first.nodeName = "QueueA";
137 first.startTime = 100;140 first.startTime = 100;
138 first.endTime = 200;141 first.endTime = 200;
@@ -140,6 +143,7 @@ std::vector<AicpuMiData> GenerateMiData()
140 res.push_back(first);143 res.push_back(first);
141 144 
142 AicpuMiData second;145 AicpuMiData second;
146+ second.deviceId = 0;
143 second.nodeName = "QueueB";147 second.nodeName = "QueueB";
144 second.startTime = 300;148 second.startTime = 300;
145 second.endTime = 400;149 second.endTime = 400;
@@ -212,20 +216,21 @@ TEST_F(AicpuAssemblerUTest, ShouldWriteThreeCsvWhenAllDataExist)
212 std::vector<std::string> aicpuLines = ReadCsvLines(aicpuFile);216 std::vector<std::string> aicpuLines = ReadCsvLines(aicpuFile);
213 ASSERT_EQ(3ul, aicpuLines.size());217 ASSERT_EQ(3ul, aicpuLines.size());
214 EXPECT_EQ(AICPU_HEADER, aicpuLines[0]);218 EXPECT_EQ(AICPU_HEADER, aicpuLines[0]);
215- EXPECT_EQ("1000.000,Conv2D,1.5,2.5,500,0.5,10.5,10,20", aicpuLines[1]);219+ // 主 aicpu 的 Timestamp(us) 列对齐 python 打\t,dp/aicpu_mi 不打
216- EXPECT_EQ("2000.000,N/A,3,4,8,1,20,11,30", aicpuLines[2]);220+ EXPECT_EQ("0,1000.000\t,Conv2D,1.5,2.5,500,0.5,10.5,10,20", aicpuLines[1]);
221+ EXPECT_EQ("0,2000.000\t,N/A,3,4,8,1,20,11,30", aicpuLines[2]);
217 222 
218 std::vector<std::string> dpLines = ReadCsvLines(dpFile);223 std::vector<std::string> dpLines = ReadCsvLines(dpFile);
219 ASSERT_EQ(3ul, dpLines.size());224 ASSERT_EQ(3ul, dpLines.size());
220 EXPECT_EQ(DP_HEADER, dpLines[0]);225 EXPECT_EQ(DP_HEADER, dpLines[0]);
221- EXPECT_EQ("1000.000,enqueue,src0,128", dpLines[1]);226+ EXPECT_EQ("0,1000.000,enqueue,src0,128", dpLines[1]);
222- EXPECT_EQ("2500.000,dequeue,src1,256", dpLines[2]);227+ EXPECT_EQ("0,2500.000,dequeue,src1,256", dpLines[2]);
223 228 
224 std::vector<std::string> miLines = ReadCsvLines(miFile);229 std::vector<std::string> miLines = ReadCsvLines(miFile);
225 ASSERT_EQ(3ul, miLines.size());230 ASSERT_EQ(3ul, miLines.size());
226 EXPECT_EQ(MI_HEADER, miLines[0]);231 EXPECT_EQ(MI_HEADER, miLines[0]);
227- EXPECT_EQ("QueueA,100,200,8", miLines[1]);232+ EXPECT_EQ("0,QueueA,100,200,8", miLines[1]);
228- EXPECT_EQ("QueueB,300,400,16", miLines[2]);233+ EXPECT_EQ("0,QueueB,300,400,16", miLines[2]);
229}234}
230 235 
231TEST_F(AicpuAssemblerUTest, ShouldWriteAicpuOnly)236TEST_F(AicpuAssemblerUTest, ShouldWriteAicpuOnly)
@@ -252,6 +252,7 @@ TEST_F(AicpuProcessorUTest, ShouldLoadAllThreeTypesAndFillDerivedFields)
252 auto dp = dataInventory.GetPtr<std::vector<AicpuDpData>>();252 auto dp = dataInventory.GetPtr<std::vector<AicpuDpData>>();
253 ASSERT_NE(nullptr, dp);253 ASSERT_NE(nullptr, dp);
254 ASSERT_EQ(2ul, dp->size());254 ASSERT_EQ(2ul, dp->size());
255+ EXPECT_EQ(0u, dp->at(0).deviceId);
255 EXPECT_EQ(1000000ull, dp->at(0).timestamp);256 EXPECT_EQ(1000000ull, dp->at(0).timestamp);
256 EXPECT_EQ("enqueue", dp->at(0).action);257 EXPECT_EQ("enqueue", dp->at(0).action);
257 EXPECT_EQ("src0", dp->at(0).source);258 EXPECT_EQ("src0", dp->at(0).source);
@@ -260,6 +261,7 @@ TEST_F(AicpuProcessorUTest, ShouldLoadAllThreeTypesAndFillDerivedFields)
260 auto mi = dataInventory.GetPtr<std::vector<AicpuMiData>>();261 auto mi = dataInventory.GetPtr<std::vector<AicpuMiData>>();
261 ASSERT_NE(nullptr, mi);262 ASSERT_NE(nullptr, mi);
262 ASSERT_EQ(2ul, mi->size());263 ASSERT_EQ(2ul, mi->size());
264+ EXPECT_EQ(0u, mi->at(0).deviceId);
263 EXPECT_EQ("QueueA", mi->at(0).nodeName);265 EXPECT_EQ("QueueA", mi->at(0).nodeName);
264 EXPECT_EQ(100ull, mi->at(0).startTime);266 EXPECT_EQ(100ull, mi->at(0).startTime);
265 EXPECT_EQ(200ull, mi->at(0).endTime);267 EXPECT_EQ(200ull, mi->at(0).endTime);
@@ -514,6 +516,7 @@ TEST_F(AicpuProcessorUTest, ShouldSucceedWhenDpOnly)
514 EXPECT_EQ(nullptr, dataInventory.GetPtr<std::vector<AicpuSummaryData>>());516 EXPECT_EQ(nullptr, dataInventory.GetPtr<std::vector<AicpuSummaryData>>());
515 ASSERT_NE(nullptr, dataInventory.GetPtr<std::vector<AicpuDpData>>());517 ASSERT_NE(nullptr, dataInventory.GetPtr<std::vector<AicpuDpData>>());
516 EXPECT_EQ(1ul, dataInventory.GetPtr<std::vector<AicpuDpData>>()->size());518 EXPECT_EQ(1ul, dataInventory.GetPtr<std::vector<AicpuDpData>>()->size());
519+ EXPECT_EQ(0u, dataInventory.GetPtr<std::vector<AicpuDpData>>()->at(0).deviceId);
517 EXPECT_EQ(nullptr, dataInventory.GetPtr<std::vector<AicpuMiData>>());520 EXPECT_EQ(nullptr, dataInventory.GetPtr<std::vector<AicpuMiData>>());
518}521}
519 522 
@@ -531,6 +534,7 @@ TEST_F(AicpuProcessorUTest, ShouldSucceedWhenMiOnly)
531 EXPECT_EQ(nullptr, dataInventory.GetPtr<std::vector<AicpuSummaryData>>());534 EXPECT_EQ(nullptr, dataInventory.GetPtr<std::vector<AicpuSummaryData>>());
532 EXPECT_EQ(nullptr, dataInventory.GetPtr<std::vector<AicpuDpData>>());535 EXPECT_EQ(nullptr, dataInventory.GetPtr<std::vector<AicpuDpData>>());
533 ASSERT_NE(nullptr, dataInventory.GetPtr<std::vector<AicpuMiData>>());536 ASSERT_NE(nullptr, dataInventory.GetPtr<std::vector<AicpuMiData>>());
537+ EXPECT_EQ(0u, dataInventory.GetPtr<std::vector<AicpuMiData>>()->at(0).deviceId);
534 EXPECT_EQ("OnlyMi", dataInventory.GetPtr<std::vector<AicpuMiData>>()->at(0).nodeName);538 EXPECT_EQ("OnlyMi", dataInventory.GetPtr<std::vector<AicpuMiData>>()->at(0).nodeName);
535}539}
536 540 
@@ -249,16 +249,24 @@ TEST_F(UtilsUTest, TestDivideByPowersOfTenWithPrecisionShouldReturnTrueValue)
249 EXPECT_EQ("0.012", DivideByPowersOfTenWithPrecision(value));249 EXPECT_EQ("0.012", DivideByPowersOfTenWithPrecision(value));
250 250 
251 value = 23456; // 入参23456251 value = 23456; // 入参23456
252- EXPECT_EQ("23.4560", DivideByPowersOfTenWithPrecision(value, 4, 3)); // 长度高于3位,移动3位,精度4位252+ EXPECT_EQ("23.4560", DivideByPowersOfTenWithPrecision(value, false, 4, 3)); // 长度高于3位,移动3位,精度4位
253 253 
254 value = 58; // 入参58254 value = 58; // 入参58
255- EXPECT_EQ("0.0580", DivideByPowersOfTenWithPrecision(value, 4, 3)); // 长度低于3位,移动3位,精度4位255+ EXPECT_EQ("0.0580", DivideByPowersOfTenWithPrecision(value, false, 4, 3)); // 长度低于3位,移动3位,精度4位
256 256 
257 value = 1234567; // 入参1234567257 value = 1234567; // 入参1234567
258- EXPECT_EQ("1234.56", DivideByPowersOfTenWithPrecision(value, 2, 3)); // 长度高于3位,移动3位,精度2位258+ EXPECT_EQ("1234.56", DivideByPowersOfTenWithPrecision(value, false, 2, 3)); // 长度高于3位,移动3位,精度2位
259 259 
260 value = 78; // 入参78260 value = 78; // 入参78
261- EXPECT_EQ("0.07", DivideByPowersOfTenWithPrecision(value, 2, 3)); // 长度小于3位,移动3位,精度2位261+ EXPECT_EQ("0.07", DivideByPowersOfTenWithPrecision(value, false, 2, 3)); // 长度小于3位,移动3位,精度2位
262+}
263+ 
264+TEST_F(UtilsUTest, TestDivideByPowersOfTenWithPrecisionShouldAppendTabWhenHighPrecision)
265+{
266+ // isHighPrecision 为 true 时,结果追加\t,Excel 按文本处理绝对时刻
267+ EXPECT_EQ("123.456\t", DivideByPowersOfTenWithPrecision(123456, true));
268+ // 精度/位数与默认值不同时同样追加\t
269+ EXPECT_EQ("1234.56\t", DivideByPowersOfTenWithPrecision(1234567, true, 2, 3));
262}270}
263 271 
264// =========================================================================272// =========================================================================