已合并
【PR】: [fix] 修复Dump txt相关问题 #1907
【PR】: [fix] 修复Dump txt相关问题 #1907
已合并
xchu42创建于 19 天前
3 个文件变更+103-34
@@ -1563,44 +1563,57 @@ std::string DumpGraphStructureView(const ascir::Graph &graph, const DumpContext
1563 1563 
1564namespace {1564namespace {
1565void CollectQueueInfo(const af::AscNodePtr &node, size_t topo_id, std::map<int32_t, dumper::QueueInfo> &queues) {1565void CollectQueueInfo(const af::AscNodePtr &node, size_t topo_id, std::map<int32_t, dumper::QueueInfo> &queues) {
1566- if (node->outputs().empty()) {1566+ const size_t output_count = node->outputs().size();
1567- return;1567+ if (output_count == 0U) {
1568- }
1569- auto &output_attr = node->outputs()[0]->attr;
1570- auto &mem = output_attr.mem;
1571- if (mem.alloc_type != af::AllocType::kAllocTypeQueue) {
1572 return;1568 return;
1573 }1569 }
1570+ for (size_t i = 0U; i < output_count; ++i) {
1571+ auto &output_attr = node->outputs()[i]->attr;
1572+ auto &mem = output_attr.mem;
1573+ if (mem.alloc_type != af::AllocType::kAllocTypeQueue) {
1574+ continue;
1575+ }
1574 1576 
1575- int32_t que_id = output_attr.que.id;1577+ int32_t que_id = output_attr.que.id;
1576- if (queues.find(que_id) == queues.end()) {1578+ const int32_t buf_num = static_cast<int32_t>(output_attr.que.buf_num);
1577- dumper::QueueInfo info;1579+ if (queues.find(que_id) == queues.end()) {
1578- info.que_id = que_id;1580+ dumper::QueueInfo info;
1579- info.depth = output_attr.que.depth;1581+ info.que_id = que_id;
1580- info.buf_num = static_cast<int32_t>(output_attr.que.buf_num);1582+ info.depth = output_attr.que.depth;
1581- info.position = "TPosition::" + PositionToString(mem.position);1583+ info.buf_num = buf_num;
1582- queues[que_id] = info;1584+ info.position = "TPosition::" + PositionToString(mem.position);
1585+ queues[que_id] = info;
1586+ } else {
1587+ // 复用场景下同一 que 的多个 tensor 可能携带不同 buf_num,
1588+ // 与 codegen LocalTQueAlloc 的 que 级聚合语义保持一致:取 max
1589+ queues[que_id].buf_num = std::max(queues[que_id].buf_num, buf_num);
1590+ }
1591+ const std::string suffix = (output_count > 1U) ? ("[" + std::to_string(i) + "]") : "";
1592+ queues[que_id].nodes.push_back({topo_id, node->GetName(), static_cast<int32_t>(mem.reuse_id), "", suffix});
1583 }1593 }
1584- queues[que_id].nodes.push_back({topo_id, node->GetName(), static_cast<int32_t>(mem.reuse_id), ""});
1585}1594}
1586 1595 
1587void CollectBufferInfo(const af::AscNodePtr &node, size_t topo_id, std::map<int32_t, dumper::BufferInfo> &buffers) {1596void CollectBufferInfo(const af::AscNodePtr &node, size_t topo_id, std::map<int32_t, dumper::BufferInfo> &buffers) {
1588- if (node->outputs().empty()) {1597+ const size_t output_count = node->outputs().size();
1589- return;1598+ if (output_count == 0U) {
1590- }
1591- auto &output_attr = node->outputs()[0]->attr;
1592- auto &mem = output_attr.mem;
1593- if (mem.alloc_type != af::AllocType::kAllocTypeBuffer) {
1594 return;1599 return;
1595 }1600 }
1601+ for (size_t i = 0U; i < output_count; ++i) {
1602+ auto &output_attr = node->outputs()[i]->attr;
1603+ auto &mem = output_attr.mem;
1604+ if (mem.alloc_type != af::AllocType::kAllocTypeBuffer) {
1605+ continue;
1606+ }
1596 1607 
1597- int32_t buf_id = output_attr.buf.id;1608+ int32_t buf_id = output_attr.buf.id;
1598- if (buffers.find(buf_id) == buffers.end()) {1609+ if (buffers.find(buf_id) == buffers.end()) {
1599- dumper::BufferInfo info;1610+ dumper::BufferInfo info;
1600- info.buf_id = buf_id;1611+ info.buf_id = buf_id;
1601- buffers[buf_id] = info;1612+ buffers[buf_id] = info;
1613+ }
1614+ const std::string suffix = (output_count > 1U) ? ("[" + std::to_string(i) + "]") : "";
1615+ buffers[buf_id].nodes.push_back({topo_id, node->GetName(), "", false, 0, suffix});
1602 }1616 }
1603- buffers[buf_id].nodes.push_back({topo_id, node->GetName(), "", false, 0});
1604}1617}
1605 1618 
1606std::string GetTmpBufSizeStr(const af::TmpBufDesc &buf_desc) {1619std::string GetTmpBufSizeStr(const af::TmpBufDesc &buf_desc) {
@@ -1628,7 +1641,7 @@ void CollectTmpBufferInfo(const af::AscNodePtr &node, size_t topo_id, std::map<i
1628 buffers[buf_id] = info;1641 buffers[buf_id] = info;
1629 }1642 }
1630 std::string size_str = GetTmpBufSizeStr(tmp_buf.buf_desc);1643 std::string size_str = GetTmpBufSizeStr(tmp_buf.buf_desc);
1631- buffers[buf_id].nodes.push_back({topo_id, node->GetName(), size_str, true, static_cast<int32_t>(i)});1644+ buffers[buf_id].nodes.push_back({topo_id, node->GetName(), size_str, true, static_cast<int32_t>(i), ""});
1632 }1645 }
1633}1646}
1634 1647 
@@ -1674,7 +1687,7 @@ void DumpQueues(std::stringstream &ss, const std::map<int32_t, dumper::QueueInfo
1674 for (auto &reuse_entry : reuse_groups) {1687 for (auto &reuse_entry : reuse_groups) {
1675 auto &nodes = reuse_entry.second;1688 auto &nodes = reuse_entry.second;
1676 for (size_t i = 0; i < nodes.size(); ++i) {1689 for (size_t i = 0; i < nodes.size(); ++i) {
1677- ss << " [" << nodes[i].topo_id << "] " << nodes[i].node_name << ".y" << std::endl;1690+ ss << " [" << nodes[i].topo_id << "] " << nodes[i].node_name << ".y" << nodes[i].tensor_suffix << std::endl;
1678 }1691 }
1679 }1692 }
1680 ss << std::endl;1693 ss << std::endl;
@@ -1714,7 +1727,7 @@ void DumpBuffers(std::stringstream &ss, const std::map<int32_t, dumper::BufferIn
1714 ss << " # size:" << node_info.size_str;1727 ss << " # size:" << node_info.size_str;
1715 }1728 }
1716 } else {1729 } else {
1717- ss << ".y";1730+ ss << ".y" << node_info.tensor_suffix;
1718 }1731 }
1719 ss << std::endl;1732 ss << std::endl;
1720 }1733 }
@@ -198,7 +198,8 @@ struct QueueNodeInfo {
198 size_t topo_id = 0;198 size_t topo_id = 0;
199 std::string node_name;199 std::string node_name;
200 int32_t reuse_id = -1;200 int32_t reuse_id = -1;
201- std::string size_str; // tensor 的 vector<> 格式大小201+ std::string size_str; // tensor 的 vector<> 格式大小
202+ std::string tensor_suffix; // 多输出节点为 "[i]",单输出为 ""
202};203};
203 204 
204/**205/**
@@ -218,9 +219,10 @@ struct QueueInfo {
218struct BufferNodeInfo {219struct BufferNodeInfo {
219 size_t topo_id = 0;220 size_t topo_id = 0;
220 std::string node_name;221 std::string node_name;
221- std::string size_str; // tensor 的 vector<> 格式大小222+ std::string size_str; // tensor 的 vector<> 格式大小
222- bool is_tmpbuf = false; // 是否为节点的 tmpbuf223+ bool is_tmpbuf = false; // 是否为节点的 tmpbuf
223- int32_t tmpbuf_idx = 0; // tmpbuf 的索引(仅当 is_tmpbuf=true 时有效)224+ int32_t tmpbuf_idx = 0; // tmpbuf 的索引(仅当 is_tmpbuf=true 时有效)
225+ std::string tensor_suffix; // 多输出节点为 "[i]",单输出为 ""
224};226};
225 227 
226/**228/**
@@ -15,6 +15,7 @@
15 15 
16#include "ascendc_ir.h"16#include "ascendc_ir.h"
17#include "ascend_graph_code_dumper.h"17#include "ascend_graph_code_dumper.h"
18+#include "ascendc_graph_txt_dumper.h"
18 19 
19#include "graph_utils.h"20#include "graph_utils.h"
20#include "ascendc_ir/utils/asc_graph_utils.h"21#include "ascendc_ir/utils/asc_graph_utils.h"
@@ -1068,4 +1069,57 @@ tiling_def, host_impl, device_impl = fuser.codegen(schedule_results)
1068 EXPECT_EQ(expected_graph_code, ReadFileContent("./asc_wrong_graph_python.py"));1069 EXPECT_EQ(expected_graph_code, ReadFileContent("./asc_wrong_graph_python.py"));
1069}1070}
1070 1071 
1072+// 验证 DumpMemoryLayoutView 对多输出节点的收集:
1073+// 多输出节点的每个 output 的 que/buf 信息都应收集,且命名为 y[i]
1074+TEST_F(AscendGraphCodeDumperUT, test_memory_layout_view_multi_output) {
1075+ AscGraph graph("multi_output_layout");
1076+ Expression s0 = graph.CreateSizeVar("s0");
1077+ Expression s1 = graph.CreateSizeVar("s1");
1078+ Axis &z0 = graph.CreateAxis("z0", s0);
1079+ Axis &z1 = graph.CreateAxis("z1", s1);
1080+ 
1081+ ascir_op::Data data("data", graph);
1082+ data.attr.sched.axis = {z0.id, z1.id};
1083+ data.y.dtype = DT_FLOAT16;
1084+ 
1085+ ascir_op::Load load("load");
1086+ load.x = data.y;
1087+ load.attr.sched.axis = {z0.id, z1.id};
1088+ *load.y.axis = {z0.id, z1.id};
1089+ load.y.dtype = DT_FLOAT16;
1090+ *load.y.repeats = {s0, s1};
1091+ *load.y.strides = {s1, One};
1092+ 
1093+ ascir_op::Split split("split");
1094+ split.InstanceOutputy(3U);
1095+ split.x = load.y;
1096+ split.attr.sched.axis = {z0.id, z1.id};
1097+ split.attr.api.compute_type = ComputeType::kComputeSplit;
1098+ for (size_t i = 0UL; i < 3UL; ++i) {
1099+ split.y[i].dtype = DT_FLOAT16;
1100+ *split.y[i].axis = {z0.id, z1.id};
1101+ *split.y[i].repeats = {s0, s1};
1102+ *split.y[i].strides = {s1, One};
1103+ // output[0] 用 queue,output[1]/[2] 用 buffer,覆盖两种收集路径
1104+ split.y[i].mem->alloc_type = (i == 0UL) ? AllocType::kAllocTypeQueue : AllocType::kAllocTypeBuffer;
1105+ if (i == 0UL) {
1106+ split.y[i].que->id = 7;
1107+ split.y[i].que->depth = 2;
1108+ split.y[i].que->buf_num = 2;
1109+ } else {
1110+ split.y[i].buf->id = static_cast<int64_t>(i);
1111+ }
1112+ }
1113+ 
1114+ const std::string layout = ::ascir::dumper::DumpMemoryLayoutView(graph, true);
1115+ // Queue 7 来自 split 的 output[0]
1116+ EXPECT_NE(layout.find("Queue 7"), std::string::npos);
1117+ EXPECT_NE(layout.find("split.y[0]"), std::string::npos) << layout;
1118+ // Buffer 1/2 来自 split 的 output[1]/[2],修复前会缺失
1119+ EXPECT_NE(layout.find("Buffer 1"), std::string::npos) << layout;
1120+ EXPECT_NE(layout.find("Buffer 2"), std::string::npos) << layout;
1121+ EXPECT_NE(layout.find("split.y[1]"), std::string::npos) << layout;
1122+ EXPECT_NE(layout.find("split.y[2]"), std::string::npos) << layout;
1123+}
1124+ 
1071} // namespace af1125} // namespace af