已合并
【PR】: Host tensor value symbolize #4443
chengyutao3创建于 2 天前
【PR】: Host tensor value symbolize #4443
已合并
chengyutao3创建于 2 天前
14 个文件变更+696-110
Mapi/session/jit_execution/exe_points/execution_order.cc+1-0
@@ -20,6 +20,7 @@ namespace ge {
20namespace {20namespace {
21const std::unordered_set<std::string> kFirstEPOptions = {INPUT_SHAPE,21const std::unordered_set<std::string> kFirstEPOptions = {INPUT_SHAPE,
22 INPUT_HINT_SHAPE,22 INPUT_HINT_SHAPE,
23+ INPUT_HINT_VALUE,
23 INPUT_SHAPE_RANGE,24 INPUT_SHAPE_RANGE,
24 INPUT_FORMAT,25 INPUT_FORMAT,
25 ge::OPTION_INPUT_REUSE_MEM_INDEXES,26 ge::OPTION_INPUT_REUSE_MEM_INDEXES,
Mapi/session/jit_execution/jit_executor.cc+72-12
@@ -20,6 +20,7 @@
20#include "graph/utils/op_type_utils.h"20#include "graph/utils/op_type_utils.h"
21#include "graph/debug/ge_attr_define.h"21#include "graph/debug/ge_attr_define.h"
22#include "acl/acl_rt.h"22#include "acl/acl_rt.h"
23+#include <set>
23 24 
24#define JIT_ASSERT(exp, tsk, ...) \25#define JIT_ASSERT(exp, tsk, ...) \
25 do { \26 do { \
@@ -78,18 +79,65 @@ bool IsEnableBatchCpy(const std::vector<gert::Tensor> &inputs) {
78 79 
79// todo if host exec option, remember to handle80// todo if host exec option, remember to handle
80Status CopyHostInputsToDevice(UserGraphExecution &execution_task, Allocator *const allocator,81Status CopyHostInputsToDevice(UserGraphExecution &execution_task, Allocator *const allocator,
81- std::vector<gert::Tensor> &device_gert_tensors) {82+ std::vector<gert::Tensor> &device_gert_tensors,
83+ const std::set<size_t> &keep_on_host_idxs = {}) {
82 const auto *external_rt_inputs = execution_task.external_rt_inputs;84 const auto *external_rt_inputs = execution_task.external_rt_inputs;
83 auto &inputs_memblocks = execution_task.inputs_memblocks;85 auto &inputs_memblocks = execution_task.inputs_memblocks;
84 bool enable_input_batch_cpy = IsEnableBatchCpy(*external_rt_inputs);86 bool enable_input_batch_cpy = IsEnableBatchCpy(*external_rt_inputs);
85- GE_ASSERT_SUCCESS(TensorTransUtils::TransHostGertTensorsToDevice(allocator, *external_rt_inputs, device_gert_tensors,87+ if (keep_on_host_idxs.empty()) {
86- inputs_memblocks, enable_input_batch_cpy));88+ GE_ASSERT_SUCCESS(TensorTransUtils::TransHostGertTensorsToDevice(
89+ allocator, *external_rt_inputs, device_gert_tensors, inputs_memblocks, enable_input_batch_cpy));
90+ return SUCCESS;
91+ }
92+ 
93+ std::vector<gert::Tensor> to_device_src;
94+ std::vector<gert::Tensor> host_vec;
95+ to_device_src.reserve(external_rt_inputs->size());
96+ host_vec.reserve(keep_on_host_idxs.size());
97+ GELOGI("copy host inputs to device, keep_on_host_idxs size %zu, external inputs size %zu.", keep_on_host_idxs.size(),
98+ external_rt_inputs->size());
99+ for (size_t i = 0U; i < external_rt_inputs->size(); ++i) {
100+ gert::Tensor src((*external_rt_inputs)[i].GetShape(), (*external_rt_inputs)[i].GetFormat(),
101+ (*external_rt_inputs)[i].GetDataType());
102+ src.MutableOriginShape() = (*external_rt_inputs)[i].GetOriginShape();
103+ src.MutableStorageShape() = (*external_rt_inputs)[i].GetStorageShape();
104+ src.MutableTensorData().ShareFrom((*external_rt_inputs)[i].GetTensorData());
105+ if (keep_on_host_idxs.count(i) > 0U) {
106+ GELOGI("input[%zu] keep on host, not transfer to device.", i);
107+ host_vec.emplace_back(std::move(src));
108+ } else {
109+ to_device_src.emplace_back(std::move(src));
110+ }
111+ }
112+ 
113+ std::vector<gert::Tensor> to_device_dst;
114+ std::vector<MemBlock *> to_device_blocks(to_device_src.size(), nullptr);
115+ if (!to_device_src.empty()) {
116+ GE_ASSERT_SUCCESS(TensorTransUtils::TransHostGertTensorsToDevice(allocator, to_device_src, to_device_dst,
117+ to_device_blocks, enable_input_batch_cpy));
118+ }
119+ 
120+ device_gert_tensors.resize(external_rt_inputs->size());
121+ inputs_memblocks.resize(external_rt_inputs->size(), nullptr);
122+ size_t host_pos = 0U;
123+ size_t device_pos = 0U;
124+ for (size_t i = 0U; i < external_rt_inputs->size(); ++i) {
125+ if (keep_on_host_idxs.count(i) > 0U) {
126+ device_gert_tensors[i] = std::move(host_vec[host_pos++]);
127+ } else {
128+ device_gert_tensors[i] = std::move(to_device_dst[device_pos]);
129+ inputs_memblocks[i] = to_device_blocks[device_pos];
130+ ++device_pos;
131+ }
132+ }
87 return SUCCESS;133 return SUCCESS;
88}134}
89 135 
90Status FreeInputsAllocByJit(std::vector<MemBlock *> &input_blocks) {136Status FreeInputsAllocByJit(std::vector<MemBlock *> &input_blocks) {
91 for (auto &mem_block : input_blocks) {137 for (auto &mem_block : input_blocks) {
92- GE_ASSERT_NOTNULL(mem_block);138+ if (mem_block == nullptr) {
139+ continue;
140+ }
93 mem_block->Free();141 mem_block->Free();
94 }142 }
95 return SUCCESS;143 return SUCCESS;
@@ -117,11 +165,16 @@ Status BuildCompileInputs(const std::vector<gert::Tensor> &ori_inputs, const Com
117 std::vector<gert::Tensor> &compile_inputs) {165 std::vector<gert::Tensor> &compile_inputs) {
118 std::set<size_t> need_host_data_idx;166 std::set<size_t> need_host_data_idx;
119 GE_ASSERT_SUCCESS(GetAllCondInputData(graph, need_host_data_idx));167 GE_ASSERT_SUCCESS(GetAllCondInputData(graph, need_host_data_idx));
168+ GE_ASSERT_SUCCESS(SymbolicInferUtil::GetValueDependentInputIdxs(graph, need_host_data_idx));
atomgit-bot
atomgit-botatomgit-bot2 天前

🔴 Critical

  当前建议代码无改动
likedislike
120 169 
121 compile_inputs = TensorTransUtils::ShareFromGertTenosrs(ori_inputs);170 compile_inputs = TensorTransUtils::ShareFromGertTenosrs(ori_inputs);
122 for (size_t data_idx : need_host_data_idx) {171 for (size_t data_idx : need_host_data_idx) {
123- GELOGD("input[%u] need copy data to host.", data_idx);
124 GE_ASSERT_TRUE(data_idx < compile_inputs.size());172 GE_ASSERT_TRUE(data_idx < compile_inputs.size());
173+ if (gert::TensorPlacementUtils::IsOnHost(compile_inputs[data_idx].GetPlacement())) {
174+ GELOGI("input[%zu] already on host, skip copy.", data_idx);
175+ continue;
atomgit-bot
atomgit-botatomgit-bot2 天前

🔴 Critical

建议:将第 175 行内容补全为 continue;

  当前建议代码无改动
likedislike
176+ }
177+ GELOGI("input[%zu] need copy data to host.", data_idx);
125 gert::Tensor host_tensor;178 gert::Tensor host_tensor;
126 GE_ASSERT_SUCCESS(TensorTransUtils::TransGertTensorToHost(compile_inputs[data_idx], host_tensor));179 GE_ASSERT_SUCCESS(TensorTransUtils::TransGertTensorToHost(compile_inputs[data_idx], host_tensor));
127 compile_inputs[data_idx] = std::move(host_tensor);180 compile_inputs[data_idx] = std::move(host_tensor);
@@ -129,12 +182,11 @@ Status BuildCompileInputs(const std::vector<gert::Tensor> &ori_inputs, const Com
129 return SUCCESS;182 return SUCCESS;
130}183}
131 184 
132-void MarkHostTensorOnDataNodes(const std::vector<gert::Tensor> &inputs, const ExecutionPoint &ep) {185+void MarkHostTensorOnDataNodes(const std::vector<gert::Tensor> &inputs, const ComputeGraphPtr &graph) {
133- auto sliced_graph = ep.GetSlicedGraph();186+ if (graph == nullptr) {
134- if (sliced_graph == nullptr) {
135 return;187 return;
136 }188 }
137- for (const auto &node : sliced_graph->GetDirectNode()) {189+ for (const auto &node : graph->GetDirectNode()) {
138 if (!OpTypeUtils::IsDataNode(node->GetType())) {190 if (!OpTypeUtils::IsDataNode(node->GetType())) {
139 continue;191 continue;
140 }192 }
@@ -143,8 +195,9 @@ void MarkHostTensorOnDataNodes(const std::vector<gert::Tensor> &inputs, const Ex
143 if (data_index < 0 || static_cast<size_t>(data_index) >= inputs.size()) {195 if (data_index < 0 || static_cast<size_t>(data_index) >= inputs.size()) {
144 continue;196 continue;
145 }197 }
146- if (inputs[data_index].GetPlacement() == gert::TensorPlacement::kOnHost) {198+ if (gert::TensorPlacementUtils::IsOnHost(inputs[data_index].GetPlacement())) {
147 (void)AttrUtils::SetBool(node->GetOpDesc(), ATTR_NAME_HOST_TENSOR_AS_MODEL_INPUT, true);199 (void)AttrUtils::SetBool(node->GetOpDesc(), ATTR_NAME_HOST_TENSOR_AS_MODEL_INPUT, true);
200+ GELOGI("mark data node %s input index %d as host tensor.", node->GetNamePtr(), data_index);
148 }201 }
149 }202 }
150}203}
@@ -267,7 +320,14 @@ Status JitExecutor::RunWithCallback(UserGraphExecution &&task) {
267 320 
268 std::vector<gert::Tensor> tensors0;321 std::vector<gert::Tensor> tensors0;
269 GE_MAKE_GUARD(free_input_mem, [&task]() { (void)FreeInputsAllocByJit(task.inputs_memblocks); });322 GE_MAKE_GUARD(free_input_mem, [&task]() { (void)FreeInputsAllocByJit(task.inputs_memblocks); });
270- JIT_ASSERT_SUCCESS(CopyHostInputsToDevice(task, device_allocator_.get(), tensors0), task);323+ std::set<size_t> keep_on_host_idxs;
324+ if (ep != nullptr && ep->GetSlicedGraph() != nullptr) {
325+ JIT_ASSERT_SUCCESS(SymbolicInferUtil::GetValueDependentInputIdxs(ep->GetSlicedGraph(), keep_on_host_idxs), task);
326+ }
327+ JIT_ASSERT_SUCCESS(CopyHostInputsToDevice(task, device_allocator_.get(), tensors0, keep_on_host_idxs), task);
328+ if (ep != nullptr && ep->GetSlicedGraph() != nullptr) {
329+ MarkHostTensorOnDataNodes(tensors0, ep->GetSlicedGraph());
330+ }
271 331 
272 std::vector<gert::Tensor> tensors1;332 std::vector<gert::Tensor> tensors1;
273 auto inputs = &tensors0;333 auto inputs = &tensors0;
@@ -282,7 +342,7 @@ Status JitExecutor::RunWithCallback(UserGraphExecution &&task) {
282 JIT_ASSERT_SUCCESS(order_.NextPoint(*ep, ge_tensors, ep), task);342 JIT_ASSERT_SUCCESS(order_.NextPoint(*ep, ge_tensors, ep), task);
283 if (ep != nullptr) {343 if (ep != nullptr) {
284 std::swap(inputs, outputs);344 std::swap(inputs, outputs);
285- MarkHostTensorOnDataNodes(*inputs, *ep);345+ MarkHostTensorOnDataNodes(*inputs, ep->GetSlicedGraph());
286 }346 }
287 }347 }
288 JIT_ASSERT_RT_OK(aclrtSynchronizeStream(stream_), task);348 JIT_ASSERT_RT_OK(aclrtSynchronizeStream(stream_), task);
Mbase/common/option_supportion_checker/option_supportion_checker.cc+2-2
@@ -224,8 +224,8 @@ const std::set<std::string> graph_options = {
224 OPTION_BUILD_GRAPH_MODE, OPTION_BUILD_CONFIG, OPTION_EXEC_FORMAT_MODEL, AICORE_NUM, OPTION_EXEC_INPUT_FUSION_SIZE,224 OPTION_BUILD_GRAPH_MODE, OPTION_BUILD_CONFIG, OPTION_EXEC_FORMAT_MODEL, AICORE_NUM, OPTION_EXEC_INPUT_FUSION_SIZE,
225 OPTION_EXEC_DYNAMIC_GRAPH_PARALLEL_MODE, OO_LEVEL, OO_CONSTANT_FOLDING, OO_DEAD_CODE_ELIMINATION,225 OPTION_EXEC_DYNAMIC_GRAPH_PARALLEL_MODE, OO_LEVEL, OO_CONSTANT_FOLDING, OO_DEAD_CODE_ELIMINATION,
226 OPTION_EXPORT_COMPILE_STAT, OPTION_ALL_TENSOR_NOT_EMPTY, OPTION_EXEC_HOST_INPUT_INDEXES, "ge.inputHintShape",226 OPTION_EXPORT_COMPILE_STAT, OPTION_ALL_TENSOR_NOT_EMPTY, OPTION_EXEC_HOST_INPUT_INDEXES, "ge.inputHintShape",
227- configure_option::INPUT_BATCH_CPY, OPTIMIZATION_SWITCH, OUTPUT_DATATYPE, OPTION_OUTPUT_REUSE_INPUT_MEM_INDEXES,227+ "ge.inputHintValue", configure_option::INPUT_BATCH_CPY, OPTIMIZATION_SWITCH, OUTPUT_DATATYPE,
228- TILING_SCHEDULE_OPTIMIZE};228+ OPTION_OUTPUT_REUSE_INPUT_MEM_INDEXES, TILING_SCHEDULE_OPTIMIZE};
229 229 
230static Status CheckSupportedOptions(const std::map<std::string, std::string> &input_options,230static Status CheckSupportedOptions(const std::map<std::string, std::string> &input_options,
231 const std::set<std::string> &supported_options, const std::string &level) {231 const std::set<std::string> &supported_options, const std::string &level) {
Mcompiler/api/aclgrph/option_utils.cc+85-42
@@ -113,6 +113,7 @@ const char *const kInputShapeRangeSample5 = "\"16\"";
113const char *const kInputShapeRangeSample6 = "\"input_name1:n1~n2,c1,h1,w1\"";113const char *const kInputShapeRangeSample6 = "\"input_name1:n1~n2,c1,h1,w1\"";
114const char *const kInputShapeRangeSample7 = "\"n1~n2,c1,h1,w1;n3,c2,h2,w2\"";114const char *const kInputShapeRangeSample7 = "\"n1~n2,c1,h1,w1;n3,c2,h2,w2\"";
115const char *const kHintInputShape = "ge.inputHintShape";115const char *const kHintInputShape = "ge.inputHintShape";
116+const char *const kHintInputValue = "ge.inputHintValue";
116 117 
117const std::unordered_set<std::string> kSupportedPrintMode = {"enable", "disable"};118const std::unordered_set<std::string> kSupportedPrintMode = {"enable", "disable"};
118const std::unordered_set<std::string> kValidHostEnvOs = {"minios", "linux"};119const std::unordered_set<std::string> kValidHostEnvOs = {"minios", "linux"};
@@ -152,6 +153,65 @@ Status ConstructShapeFromStr(const std::string &shape_str, GeShape &shape) {
152 return GRAPH_SUCCESS;153 return GRAPH_SUCCESS;
153}154}
154 155 
156+Status ConstructValueListFromStr(const std::string &value_str, std::vector<int64_t> &values) {
157+ GE_ASSERT_TRUE(value_str.length() >= kLeastStrElementNum && value_str.front() == '[' && value_str.back() == ']');
158+ auto value_content_str = value_str.substr(1, value_str.length() - kLeastStrElementNum);
159+ auto val_strs = ge::StringUtils::Split(value_content_str, ',');
160+ values.clear();
161+ for (auto &str : val_strs) {
162+ if (str.empty()) {
163+ continue;
164+ }
165+ int64_t val = -1;
166+ GE_ASSERT_SUCCESS(ConvertToInt64(ge::StringUtils::Trim(str), val), "Value: %s is invalid in option",
167+ value_str.c_str());
168+ GE_ASSERT_TRUE(val >= 0L, "Value in %s should not less than 0, but get: %lld.", kHintInputValue, val);
169+ values.push_back(val);
170+ }
171+ return GRAPH_SUCCESS;
172+}
173+ 
174+template <typename ElemType, typename ElemParser>
175+Status ParseIndexedListOption(const std::string &option_name, const std::string &option_value,
176+ std::vector<std::pair<int64_t, ElemType>> &result, ElemParser parse_elem) {
177+ std::vector<std::string> input_option_strs = ge::StringUtils::Split(option_value, ';');
178+ result.reserve(input_option_strs.size());
179+ std::set<int64_t> index_set;
180+ for (size_t i = 0U; i < input_option_strs.size(); i++) {
181+ auto &input_option_local = StringUtils::Trim(input_option_strs[i]);
182+ if (input_option_local.empty()) {
183+ GELOGW("Options[%s] is invalid, Input[%zu] is empty.", option_name.c_str(), i);
184+ continue;
185+ }
186+ std::vector<std::string> index_and_value_str = ge::StringUtils::Split(input_option_local, ':');
187+ if (index_and_value_str.size() != kLeastStrElementNum) {
188+ REPORT_PREDEFINED_ERR_MSG("E10014", std::vector<const char *>({"parameter", "value"}),
189+ std::vector<const char *>({option_name.c_str(), option_value.c_str()}));
190+ GELOGE(PARAM_INVALID, "Options[%s] is invalid, input[%zu][%s] not match pattern: input_index:[v0,v1,...]",
191+ option_name.c_str(), i, input_option_local.c_str());
192+ return PARAM_INVALID;
193+ }
194+ int64_t index = -1;
195+ if (ConvertToInt64(index_and_value_str.front(), index) != SUCCESS || index < 0 || !index_set.insert(index).second) {
196+ REPORT_PREDEFINED_ERR_MSG("E10014", std::vector<const char *>({"parameter", "value"}),
197+ std::vector<const char *>({option_name.c_str(), option_value.c_str()}));
198+ GELOGE(PARAM_INVALID, "Option[%s] is invalid, input[%zu][%s] check index fail.", option_name.c_str(), i,
199+ input_option_local.c_str());
200+ return PARAM_INVALID;
201+ }
202+ ElemType elem;
203+ if (parse_elem(StringUtils::Trim(index_and_value_str.back()), elem) != GRAPH_SUCCESS) {
204+ REPORT_PREDEFINED_ERR_MSG("E10014", std::vector<const char *>({"parameter", "value"}),
205+ std::vector<const char *>({option_name.c_str(), option_value.c_str()}));
206+ GELOGE(PARAM_INVALID, "Option[%s] is invalid, Input[%zu] parse value[%s] failed.", option_name.c_str(), i,
207+ input_option_local.c_str());
208+ return PARAM_INVALID;
209+ }
210+ result.emplace_back(std::make_pair(index, elem));
211+ }
212+ return GRAPH_SUCCESS;
213+}
214+ 
155static bool StringToLongNoThrow(const std::string &str, long &val) {215static bool StringToLongNoThrow(const std::string &str, long &val) {
156 std::string val_str(str);216 std::string val_str(str);
157 std::stringstream ss(StringUtils::Trim(val_str));217 std::stringstream ss(StringUtils::Trim(val_str));
@@ -1067,51 +1127,15 @@ Status ParseHintInputShape(std::vector<GeShape> &option_shape) {
1067 return GRAPH_SUCCESS;1127 return GRAPH_SUCCESS;
1068 }1128 }
1069 GELOGI("Option %s is set, value: %s.", INPUT_HINT_SHAPE, input_option.c_str());1129 GELOGI("Option %s is set, value: %s.", INPUT_HINT_SHAPE, input_option.c_str());
1070- std::vector<std::string> input_option_strs = ge::StringUtils::Split(input_option, ';');1130+ std::vector<std::pair<int64_t, GeShape>> parse_shape;
1131+ GE_ASSERT_SUCCESS(ParseIndexedListOption<GeShape>(
1132+ "ge.inputHintShape", input_option, parse_shape,
1133+ [](const std::string &s, GeShape &shape) { return ConstructShapeFromStr(s, shape); }));
1071 1134 
1072- std::vector<pair<int64_t, GeShape>> parse_shape;
1073- parse_shape.reserve(input_option_strs.size());
1074- std::set<int64_t> index_set;
1075 int64_t max_index = 0L;1135 int64_t max_index = 0L;
1076- for (size_t i = 0U; i < input_option_strs.size(); i++) {1136+ for (const auto &item : parse_shape) {
1077- auto &input_option_local = StringUtils::Trim(input_option_strs[i]);1137+ max_index = item.first > max_index ? item.first : max_index;
1078- // 如果配置的input是空跳过解析
1079- if (input_option_local.empty()) {
1080- GELOGW("Options[%s] is invalid, Input[%u] is empty.", INPUT_HINT_SHAPE);
1081- continue;
1082- }
1083- std::vector<std::string> index_and_shape_str = ge::StringUtils::Split(input_option_local, ':');
1084- // 的左右两边必须是有元素的,key和value元素
1085- if (index_and_shape_str.size() != kLeastStrElementNum) {
1086- REPORT_PREDEFINED_ERR_MSG("E10014", std::vector<const char *>({"parameter", "value"}),
1087- std::vector<const char *>({"input_hint_shape", input_option.c_str()}));
1088- GELOGE(PARAM_INVALID,
1089- "Options[--input_hint_shape] is invalid, input[%u][%s] not match pattern: input_index:[n,c,h,w]", i,
1090- input_option_local.c_str());
1091- return PARAM_INVALID;
1092- }
1093- 
1094- int64_t index = -1;
1095- if (ConvertToInt64(index_and_shape_str.front(), index) != SUCCESS || index < 0 || !index_set.insert(index).second) {
1096- REPORT_PREDEFINED_ERR_MSG("E10014", std::vector<const char *>({"parameter", "value"}),
1097- std::vector<const char *>({"input_hint_shape", input_option.c_str()}));
1098- GELOGE(PARAM_INVALID, "Option[--input_hint_shape] is invalid, input[%u][%s] check index fail.", i,
1099- input_option_local.c_str());
1100- return PARAM_INVALID;
1101- }
1102- max_index = index > max_index ? index : max_index;
1103- 
1104- GeShape shape;
1105- if (ConstructShapeFromStr(StringUtils::Trim(index_and_shape_str.back()), shape) != GRAPH_SUCCESS) {
1106- REPORT_PREDEFINED_ERR_MSG("E10014", std::vector<const char *>({"parameter", "value"}),
1107- std::vector<const char *>({"input_hint_shape", input_option.c_str()}));
1108- GELOGE(PARAM_INVALID, "Option[--input_hint_shape] is invalid, Input[%u] parse shape[%s] failed.", i,
1109- input_option_local.c_str());
1110- return PARAM_INVALID;
1111- }
1112- parse_shape.emplace_back(std::make_pair(index, shape));
1113 }1138 }
1114- 
1115 option_shape.resize(max_index + 1, GeShape(DUMMY_SHAPE));1139 option_shape.resize(max_index + 1, GeShape(DUMMY_SHAPE));
1116 for (const auto &shape : parse_shape) {1140 for (const auto &shape : parse_shape) {
1117 option_shape[shape.first] = shape.second;1141 option_shape[shape.first] = shape.second;
@@ -1119,6 +1143,25 @@ Status ParseHintInputShape(std::vector<GeShape> &option_shape) {
1119 return GRAPH_SUCCESS;1143 return GRAPH_SUCCESS;
1120}1144}
1121 1145 
1146+Status ParseHintInputValue(std::map<int64_t, std::vector<int64_t>> &option_value) {
1147+ std::string input_option;
1148+ (void)ge::GetContext().GetOption(kHintInputValue, input_option);
1149+ if (input_option.empty()) {
1150+ GELOGT(TRACE_RUNNING, "Option %s is not set, skip parse hint value.", kHintInputValue);
1151+ return GRAPH_SUCCESS;
1152+ }
1153+ GELOGI("option %s is set, value: %s.", kHintInputValue, input_option.c_str());
1154+ std::vector<std::pair<int64_t, std::vector<int64_t>>> parse_values;
1155+ GE_ASSERT_SUCCESS(ParseIndexedListOption<std::vector<int64_t>>(
1156+ "ge.inputHintValue", input_option, parse_values,
1157+ [](const std::string &s, std::vector<int64_t> &values) { return ConstructValueListFromStr(s, values); }));
1158+ for (auto &item : parse_values) {
1159+ option_value[item.first] = std::move(item.second);
1160+ }
1161+ GELOGI("parse hint value done, input count %zu.", option_value.size());
1162+ return GRAPH_SUCCESS;
1163+}
1164+ 
1122std::string GetAutofuseFlagValue(const std::string &option) {1165std::string GetAutofuseFlagValue(const std::string &option) {
1123 // 自动融合新的环境变量1166 // 自动融合新的环境变量
1124 const char_t *auto_fuse_options = nullptr;1167 const char_t *auto_fuse_options = nullptr;
Mcompiler/api/aclgrph/option_utils.h+8-0
@@ -17,6 +17,7 @@
17#include <utility>17#include <utility>
18#include <vector>18#include <vector>
19#include <set>19#include <set>
20+#include <map>
20 21 
21#include "framework/common/debug/ge_log.h"22#include "framework/common/debug/ge_log.h"
22#include "framework/common/ge_inner_error_codes.h"23#include "framework/common/ge_inner_error_codes.h"
@@ -80,6 +81,13 @@ Status CheckAndTransferInputShapeToRange(std::string &input_shape, std::string &
80 */81 */
81Status ParseHintInputShape(std::vector<GeShape> &option_shape);82Status ParseHintInputShape(std::vector<GeShape> &option_shape);
82 83 
84+/*
85+ * @brief 获取ge.inputHintValue中对应option的值, 并将其转化为map<int64_t, vector<int64_t>>
86+ * @out_param option_value 从option中解析的字符串转成成的value map
87+ * @return 成功返回GRAPH_SUCCESS, 失败返回FAILED
88+ */
89+Status ParseHintInputValue(std::map<int64_t, std::vector<int64_t>> &option_value);
90+ 
83Status ParserShapeRangeByName(std::string &input_shape, std::string &input_shape_range);91Status ParserShapeRangeByName(std::string &input_shape, std::string &input_shape_range);
84 92 
85Status CheckDynamicInputParamValid(std::string &dynamic_batch_size, std::string &dynamic_image_size,93Status CheckDynamicInputParamValid(std::string &dynamic_batch_size, std::string &dynamic_image_size,
Mcompiler/graph/optimize/symbolic/infer_symbolic_shape/symbolic_infer_util.cc+99-0
@@ -10,13 +10,23 @@
10 10 
11#include "symbolic_infer_util.h"11#include "symbolic_infer_util.h"
12 12 
13+#include <algorithm>
14+#include <vector>
13#include "graph/utils/node_utils.h"15#include "graph/utils/node_utils.h"
16+#include "graph/utils/op_desc_utils.h"
17+#include "graph/utils/attr_utils.h"
18+#include "graph/debug/ge_attr_define.h"
19+#include "base/registry/op_impl_space_registry_v2.h"
14 20 
15#include <op_type_utils.h>21#include <op_type_utils.h>
16 22 
17namespace ge {23namespace ge {
18constexpr static size_t kByteBitCount = 8UL;24constexpr static size_t kByteBitCount = 8UL;
19 25 
26+namespace {
27+constexpr const char *const kValueDependentIdxsAttr = "_ge_value_dependent_idxs";
28+} // namespace
29+ 
20graphStatus SymbolicInferUtil::GetConstInt(const gert::SymbolTensor *tensor, DataType dt, int64_t &value) {30graphStatus SymbolicInferUtil::GetConstInt(const gert::SymbolTensor *tensor, DataType dt, int64_t &value) {
21 if (dt == DT_INT32) {31 if (dt == DT_INT32) {
22 int32_t tmp_value = 0;32 int32_t tmp_value = 0;
@@ -120,4 +130,93 @@ NodePtr SymbolicInferUtil::GetCondInput(const NodePtr &node) {
120 return parent_input == nullptr ? cond_input : parent_input;130 return parent_input == nullptr ? cond_input : parent_input;
121}131}
122 132 
133+bool SymbolicInferUtil::IsValueDependentDataNode(const NodePtr &data_node) {
134+ const auto space_registry = gert::DefaultOpImplSpaceRegistryV2::GetInstance().GetSpaceRegistry();
135+ for (const auto *out_anchor : data_node->GetAllOutDataAnchorsPtr()) {
136+ if (out_anchor == nullptr) {
137+ continue;
138+ }
139+ for (const auto *peer_anchor : out_anchor->GetPeerInDataAnchorsPtr()) {
140+ if (peer_anchor == nullptr) {
141+ continue;
142+ }
143+ auto *owner_node = peer_anchor->GetOwnerNodeBarePtr();
144+ if (owner_node == nullptr) {
145+ continue;
146+ }
147+ const auto &consumer_op = owner_node->GetOpDesc();
148+ if (consumer_op == nullptr) {
149+ continue;
150+ }
151+ const size_t input_idx = static_cast<size_t>(peer_anchor->GetIdx());
152+ 
153+ auto functions = gert::OpImplInferSymbolShapeRegistry::GetInstance().GetOpImpl(consumer_op->GetType().c_str());
154+ if (functions != nullptr) {
155+ const gert::OpImplKernelRegistry::OpImplFunctionsV2 *function_new = functions;
156+ if (space_registry != nullptr) {
157+ const auto *space_func = space_registry->GetOpImpl(consumer_op->GetType().c_str());
158+ if (space_func != nullptr) {
159+ function_new = space_func;
160+ }
161+ }
162+ size_t ir_index = 0UL;
163+ if (ge::OpDescUtils::GetInputIrIndexByInstanceIndex(consumer_op, input_idx, ir_index) != GRAPH_SUCCESS) {
164+ ir_index = input_idx;
165+ }
166+ if (function_new->IsInputDataDependency(ir_index)) {
167+ GELOGI("data node %s is value-dependent, consumer %s input idx %zu is data dependency.",
168+ data_node->GetNamePtr(), consumer_op->GetNamePtr(), input_idx);
169+ return true;
170+ }
171+ }
172+ 
173+ const auto &op_infer_depends = consumer_op->GetOpInferDepends();
174+ if (op_infer_depends.empty()) {
175+ continue;
176+ }
177+ auto input_name = consumer_op->GetValidInputNameByIndex(static_cast<uint32_t>(input_idx));
178+ if (std::find(op_infer_depends.cbegin(), op_infer_depends.cend(), input_name) != op_infer_depends.cend()) {
179+ GELOGI("data node %s is value-dependent, consumer %s input name %s in op_infer_depends.",
180+ data_node->GetNamePtr(), consumer_op->GetNamePtr(), input_name.c_str());
181+ return true;
182+ }
183+ }
184+ }
185+ return false;
186+}
187+ 
188+Status SymbolicInferUtil::GetValueDependentInputIdxs(const ComputeGraphPtr &graph,
189+ std::set<size_t> &value_dependent_idxs) {
190+ if (graph == nullptr) {
191+ return SUCCESS;
192+ }
193+ std::vector<int64_t> cached_idxs;
194+ if (ge::AttrUtils::GetListInt(graph, kValueDependentIdxsAttr, cached_idxs)) {
195+ for (const auto idx : cached_idxs) {
196+ value_dependent_idxs.insert(static_cast<size_t>(idx));
197+ }
198+ return SUCCESS;
199+ }
200+ std::set<size_t> computed_idxs;
201+ for (const auto &node : graph->GetDirectNode()) {
202+ if (node == nullptr) {
203+ continue;
204+ }
205+ const auto &op_desc = node->GetOpDesc();
206+ if (op_desc == nullptr || !OpTypeUtils::IsDataNode(op_desc->GetType())) {
207+ continue;
208+ }
209+ int32_t data_index = -1;
210+ (void)AttrUtils::GetInt(op_desc, ATTR_NAME_INDEX, data_index);
211+ if (data_index >= 0 && IsValueDependentDataNode(node)) {
212+ computed_idxs.insert(static_cast<size_t>(data_index));
213+ GELOGI("graph %s input data index %d is value-dependent.", graph->GetName().c_str(), data_index);
214+ }
215+ }
216+ std::vector<int64_t> cached_vec(computed_idxs.cbegin(), computed_idxs.cend());
217+ (void)ge::AttrUtils::SetListInt(graph, kValueDependentIdxsAttr, cached_vec);
218+ value_dependent_idxs.insert(computed_idxs.cbegin(), computed_idxs.cend());
219+ return SUCCESS;
220+}
221+ 
123} // namespace ge222} // namespace ge
Mcompiler/graph/optimize/symbolic/infer_symbolic_shape/symbolic_infer_util.h+4-0
@@ -10,6 +10,8 @@
10 10 
11#ifndef AIR_CXX_COMPILER_GRAPH_OPTIMIZE_AUTOFUSE_SYMBOLIC_INFER_SYMBOLIC_SHAPE_SYMBOLIC_SHAPE_INFER_UTIL_H_11#ifndef AIR_CXX_COMPILER_GRAPH_OPTIMIZE_AUTOFUSE_SYMBOLIC_INFER_SYMBOLIC_SHAPE_SYMBOLIC_SHAPE_INFER_UTIL_H_
12#define AIR_CXX_COMPILER_GRAPH_OPTIMIZE_AUTOFUSE_SYMBOLIC_INFER_SYMBOLIC_SHAPE_SYMBOLIC_SHAPE_INFER_UTIL_H_12#define AIR_CXX_COMPILER_GRAPH_OPTIMIZE_AUTOFUSE_SYMBOLIC_INFER_SYMBOLIC_SHAPE_SYMBOLIC_SHAPE_INFER_UTIL_H_
13+#include <set>
14+ 
13#include "ge_common/ge_common_api_types.h"15#include "ge_common/ge_common_api_types.h"
14#include "exe_graph/runtime/infer_symbol_shape_context.h"16#include "exe_graph/runtime/infer_symbol_shape_context.h"
15#include "common/checker.h"17#include "common/checker.h"
@@ -139,6 +141,8 @@ class SymbolicInferUtil {
139 static std::string DumpSymbolTensor(const gert::SymbolTensor &symbolic_tensor);141 static std::string DumpSymbolTensor(const gert::SymbolTensor &symbolic_tensor);
140 static bool IsSupportCondNode(const NodePtr &node);142 static bool IsSupportCondNode(const NodePtr &node);
141 static NodePtr GetCondInput(const NodePtr &node);143 static NodePtr GetCondInput(const NodePtr &node);
144+ static bool IsValueDependentDataNode(const NodePtr &data_node);
145+ static Status GetValueDependentInputIdxs(const ComputeGraphPtr &graph, std::set<size_t> &value_dependent_idxs);
142};146};
143} // namespace ge147} // namespace ge
144 148 
Mcompiler/graph/optimize/symbolic/infer_symbolic_shape/symbolic_shape_symbolizer.cc+115-3
@@ -8,7 +8,9 @@
8 * See LICENSE in the root of the software repository for the full text of the License.8 * See LICENSE in the root of the software repository for the full text of the License.
9 */9 */
10 10 
11+#include <set>
11#include <string>12#include <string>
13+#include <map>
12#include "common/checker.h"14#include "common/checker.h"
13#include "common/plugin/ge_make_unique_util.h"15#include "common/plugin/ge_make_unique_util.h"
14#include "common/context/local_context.h"16#include "common/context/local_context.h"
@@ -26,6 +28,8 @@
26#include "graph/optimize/symbolic/shape_env_guarder.h"28#include "graph/optimize/symbolic/shape_env_guarder.h"
27#include "graph/symbolizer/guard_dfx_context.h"29#include "graph/symbolizer/guard_dfx_context.h"
28#include "graph/debug/ge_attr_define.h"30#include "graph/debug/ge_attr_define.h"
31+#include "api/aclgrph/option_utils.h"
32+#include "base/registry/op_impl_space_registry_v2.h"
29 33 
30namespace ge {34namespace ge {
31namespace {35namespace {
@@ -75,6 +79,10 @@ std::map<ge::DataType, std::string> kGeDType2CppDtype = {
75 {ge::DT_UINT64, "uint64_t"},79 {ge::DT_UINT64, "uint64_t"},
76};80};
77 81 
82+// 值符号化仅针对shape/索引类小tensor,元素个数超过该阈值时不进行值符号化,
83+// 与 symbolic_shape_inference.cc 中的 kMaxSymbolicValueSize 保持一致
84+constexpr int64_t kMaxSymbolizeValueElemNum = 200;
85+ 
78// 泛化value的类型,可扩展为:只泛化value、泛化value并且求和,泛化value并且求平均86// 泛化value的类型,可扩展为:只泛化value、泛化value并且求和,泛化value并且求平均
79const char_t *const kSymbolizeValueType = "_symbolize_value_type";87const char_t *const kSymbolizeValueType = "_symbolize_value_type";
80enum SymbolizeValueType {88enum SymbolizeValueType {
@@ -153,7 +161,7 @@ Status SymbolizeInputValueForRepeat(const GeTensor &tensor, SymbolicDescAttr *at
153 return GRAPH_SUCCESS;161 return GRAPH_SUCCESS;
154}162}
155 163 
156-bool SupportSymbolizeValueSum(const GeTensor &ge_tensor) {164+bool SupportSymbolizeValue(const GeTensor &ge_tensor) {
157 const auto &tensor_desc = ge_tensor.GetTensorDesc();165 const auto &tensor_desc = ge_tensor.GetTensorDesc();
158 if (tensor_desc.GetPlacement() != kPlacementHost) {166 if (tensor_desc.GetPlacement() != kPlacementHost) {
159 GELOGI("tensor data is on %d, Current we do not support symbolize tensor data value which is not on host",167 GELOGI("tensor data is on %d, Current we do not support symbolize tensor data value which is not on host",
@@ -172,6 +180,83 @@ bool SupportSymbolizeValueSum(const GeTensor &ge_tensor) {
172 return true;180 return true;
173}181}
174 182 
183+template <typename T>
184+std::vector<Expression> CreateSymbolValueElement(const GeTensor &tensor, int32_t data_index, ge::DataType dtype,
185+ ShapeEnvAttr *shape_env_attr) {
186+ std::vector<Expression> result;
187+ const T *const data = reinterpret_cast<const T *>(tensor.GetData().GetData());
188+ GE_ASSERT_NOTNULL(data);
189+ const size_t elem_num = tensor.GetData().size() / sizeof(T);
190+ for (size_t i = 0UL; i < elem_num; i++) {
191+ auto source = MakeShared<InputValueElementSource>(data_index, i, dtype);
192+ auto symbol = shape_env_attr->CreateSymbol<int64_t>(static_cast<int64_t>(data[i]), source);
193+ result.emplace_back(symbol);
194+ GELOGT(TRACE_RUNNING,
195+ "symbolize value from data, data_index %d, elem_idx %zu, value %lld, symbol name %s, "
196+ "source str is %s",
197+ data_index, i, static_cast<int64_t>(data[i]), symbol.GetName().get(), source->GetSourceStr().c_str());
198+ }
199+ return result;
200+}
201+ 
202+Status SymbolizeInputValue(const GeTensor &tensor, int32_t data_index, const NodePtr &data_node,
203+ const std::map<int64_t, std::vector<int64_t>> &hint_value_map,
204+ const std::set<size_t> &value_dependent_idxs, ShapeEnvAttr *shape_env_attr,
205+ SymbolicDescAttr *symbolic_desc_attr) {
206+ if (symbolic_desc_attr->symbolic_tensor.GetSymbolicValue() != nullptr) {
207+ return SUCCESS;
208+ }
209+ 
210+ std::vector<Expression> sym_value;
211+ if (SupportSymbolizeValue(tensor) && value_dependent_idxs.count(static_cast<size_t>(data_index)) > 0U) {
212+ const int64_t shape_size = tensor.GetTensorDesc().GetShape().GetShapeSize();
213+ if (shape_size >= 0 && shape_size <= kMaxSymbolizeValueElemNum) {
214+ GELOGI("symbolize input[%d] value from real host data, data size %zu.", data_index, data_node->GetNamePtr(),
215+ tensor.GetData().size());
216+ const auto dtype = tensor.GetTensorDesc().GetDataType();
217+ switch (dtype) {
218+ case DT_INT32:
219+ sym_value = CreateSymbolValueElement<int32_t>(tensor, data_index, dtype, shape_env_attr);
220+ break;
221+ case DT_INT64:
222+ sym_value = CreateSymbolValueElement<int64_t>(tensor, data_index, dtype, shape_env_attr);
223+ break;
224+ case DT_UINT32:
225+ sym_value = CreateSymbolValueElement<uint32_t>(tensor, data_index, dtype, shape_env_attr);
226+ break;
227+ case DT_UINT64:
228+ sym_value = CreateSymbolValueElement<uint64_t>(tensor, data_index, dtype, shape_env_attr);
229+ break;
230+ default:
231+ GELOGW("hint value unsupported data type %s, skip.",
232+ TypeUtils::DataTypeToSerialString(tensor.GetTensorDesc().GetDataType()).c_str());
233+ break;
234+ }
235+ } else {
236+ GELOGW("input[%d] shape size %lld is invalid or exceeds value symbolize limit %lld, skip.", data_index,
237+ shape_size, kMaxSymbolizeValueElemNum);
238+ }
239+ } else {
240+ auto it = hint_value_map.find(data_index);
241+ if (it != hint_value_map.end()) {
242+ GELOGI("symbolize input[%d] value from hint option, elem num %zu.", data_index, it->second.size());
243+ for (size_t elem_idx = 0; elem_idx < it->second.size(); ++elem_idx) {
244+ auto source = MakeShared<InputValueElementSource>(data_index, elem_idx, tensor.GetTensorDesc().GetDataType());
245+ auto symbol = shape_env_attr->CreateSymbol<int64_t>(it->second[elem_idx], source);
246+ sym_value.emplace_back(symbol);
247+ GELOGD(
248+ "symbolize value from option, data_index %d, elem_idx %zu, value %lld, symbol name %s, "
249+ "source str is %s",
250+ data_index, elem_idx, it->second[elem_idx], symbol.GetName().get(), source->GetSourceStr().c_str());
251+ }
252+ }
253+ }
254+ if (!sym_value.empty()) {
255+ symbolic_desc_attr->symbolic_tensor.SetSymbolicValue(ge::MakeUnique<std::vector<Expression>>(std::move(sym_value)));
256+ }
257+ return SUCCESS;
258+}
259+ 
175bool IsAippInput(const NodePtr &data_node) {260bool IsAippInput(const NodePtr &data_node) {
176 auto output_nodes = NodeUtils::GetOutDataNodes(*data_node, nullptr);261 auto output_nodes = NodeUtils::GetOutDataNodes(*data_node, nullptr);
177 return output_nodes.size() == 1 && output_nodes[0]->GetType() == AIPP;262 return output_nodes.size() == 1 && output_nodes[0]->GetType() == AIPP;
@@ -318,6 +403,12 @@ Status SymbolizeRootGraph(const ComputeGraphPtr &graph, const std::vector<GeTens
318 GE_ASSERT_SUCCESS(GetSupportSymbolizeInputDataNodes(graph, data_nodes, graph_inputs.size()));403 GE_ASSERT_SUCCESS(GetSupportSymbolizeInputDataNodes(graph, data_nodes, graph_inputs.size()));
319 auto shape_env_attr = graph->GetAttrsGroup<ShapeEnvAttr>();404 auto shape_env_attr = graph->GetAttrsGroup<ShapeEnvAttr>();
320 GE_ASSERT_NOTNULL(shape_env_attr);405 GE_ASSERT_NOTNULL(shape_env_attr);
406+ std::map<int64_t, std::vector<int64_t>> hint_value_map;
407+ GE_ASSERT_SUCCESS(ParseHintInputValue(hint_value_map));
408+ std::set<size_t> value_dependent_idxs;
409+ GE_ASSERT_SUCCESS(SymbolicInferUtil::GetValueDependentInputIdxs(graph, value_dependent_idxs));
410+ GELOGI("symbolize root graph %s, hint value map size %zu, value dependent idx count %zu.", graph->GetName().c_str(),
411+ hint_value_map.size(), value_dependent_idxs.size());
321 for (auto &data_node : data_nodes) {412 for (auto &data_node : data_nodes) {
322 auto op_desc = data_node->GetOpDescBarePtr();413 auto op_desc = data_node->GetOpDescBarePtr();
323 DataSymbolizeInfo info;414 DataSymbolizeInfo info;
@@ -339,10 +430,14 @@ Status SymbolizeRootGraph(const ComputeGraphPtr &graph, const std::vector<GeTens
339 const auto symbolic_desc_attr = op_desc->MutableOutputDesc(0)->GetOrCreateAttrsGroup<SymbolicDescAttr>();430 const auto symbolic_desc_attr = op_desc->MutableOutputDesc(0)->GetOrCreateAttrsGroup<SymbolicDescAttr>();
340 GE_ASSERT_SUCCESS(SymbolizeShape(info, op_desc, shape_env_attr, symbolic_desc_attr, ge_shape));431 GE_ASSERT_SUCCESS(SymbolizeShape(info, op_desc, shape_env_attr, symbolic_desc_attr, ge_shape));
341 432 
342- int64_t symbolize_value_type = SYMBOLIZE_VALUE_TYPE_NONE;
343 const auto &tensor = graph_inputs.at(data_index);433 const auto &tensor = graph_inputs.at(data_index);
434+ GE_ASSERT_SUCCESS(SymbolizeInputValue(tensor, data_index, data_node, hint_value_map, value_dependent_idxs,
435+ shape_env_attr, symbolic_desc_attr));
436+ 
437+ int64_t symbolize_value_type = SYMBOLIZE_VALUE_TYPE_NONE;
344 if (AttrUtils::GetInt(op_desc, kSymbolizeValueType, symbolize_value_type) &&438 if (AttrUtils::GetInt(op_desc, kSymbolizeValueType, symbolize_value_type) &&
345- symbolize_value_type == static_cast<ino64_t>(SYMBOLIZE_VALUE_TYPE_SUM) && SupportSymbolizeValueSum(tensor)) {439+ symbolize_value_type == static_cast<int64_t>(SYMBOLIZE_VALUE_TYPE_SUM) && SupportSymbolizeValue(tensor) &&
440+ symbolic_desc_attr->symbolic_tensor.GetSymbolicValue() == nullptr) {
346 GELOGI("Symbolize value sum for node %s[%s]", op_desc->GetNamePtr(), op_desc->GetTypePtr());441 GELOGI("Symbolize value sum for node %s[%s]", op_desc->GetNamePtr(), op_desc->GetTypePtr());
347 GE_ASSERT_SUCCESS(SymbolizeInputValueForRepeat(tensor, symbolic_desc_attr, shape_env_attr, data_index));442 GE_ASSERT_SUCCESS(SymbolizeInputValueForRepeat(tensor, symbolic_desc_attr, shape_env_attr, data_index));
348 }443 }
@@ -381,6 +476,23 @@ std::string InputValueSumSource::GetSourceStr() const {
381 )";476 )";
382}477}
383 478 
479+std::string InputValueElementSource::GetSourceStr() const {
480+ return R"([&]() -> int64_t {
481+ const auto* tensor = context->GetGraphInputTensor()" +
482+ std::to_string(input_data_idx_) + R"();
483+ if (tensor == nullptr) {
484+ return -1;
485+ }
486+ const auto* data = tensor->GetData<)" +
487+ kGeDType2CppDtype[dtype_] + R"(>();
488+ if (data == nullptr) {
489+ return -1;
490+ }
491+ return static_cast<int64_t>(data[)" +
492+ std::to_string(elem_idx_) + R"(]);
493+ }())";
494+}
495+ 
384std::string InputRankSource::GetSourceStr() const {496std::string InputRankSource::GetSourceStr() const {
385 return R"([&]() -> size_t {497 return R"([&]() -> size_t {
386 const auto *tensor = context->GetGraphInputTensor()" +498 const auto *tensor = context->GetGraphInputTensor()" +
Mcompiler/graph/optimize/symbolic/infer_symbolic_shape/symbolic_shape_symbolizer.h+13-0
@@ -46,6 +46,19 @@ class InputValueSumSource : public ge::Source {
46 ge::DataType dtype_; // 描述value的数据类型,用于后续执行时取值46 ge::DataType dtype_; // 描述value的数据类型,用于后续执行时取值
47};47};
48 48 
49+class InputValueElementSource : public ge::Source {
50+ public:
51+ InputValueElementSource(int32_t input_data_idx, size_t elem_idx, ge::DataType dtype)
52+ : input_data_idx_(input_data_idx), elem_idx_(elem_idx), dtype_(dtype) {}
53+ 
54+ [[nodiscard]] std::string GetSourceStr() const override;
55+ 
56+ private:
57+ int32_t input_data_idx_; // Data的index,描述symbol来自于graph输入中第几个输入data
58+ size_t elem_idx_; // 描述symbol来自于tensor data中第几个元素
59+ ge::DataType dtype_; // 描述value的数据类型,用于后续执行时取值
60+};
61+ 
49class InputRankSource final : public ge::Source {62class InputRankSource final : public ge::Source {
50 public:63 public:
51 explicit InputRankSource(const int32_t input_data_idx) : input_data_idx_(input_data_idx) {}64 explicit InputRankSource(const int32_t input_data_idx) : input_data_idx_(input_data_idx) {}
Mtests/ge/st/testcase/autofuse/test_symbolize_value_and_infer.cc+97-0
@@ -301,4 +301,101 @@ TEST_F(SymbolizeValueST, test_symbolize_value_and_repeat_infer) {
301 EXPECT_EQ(symbol_expr3.GetHint(hint), true);301 EXPECT_EQ(symbol_expr3.GetHint(hint), true);
302 EXPECT_EQ(hint, 16 * 2);302 EXPECT_EQ(hint, 16 * 2);
303}303}
304+ 
305+// ============ Reshape + hint value helpers ============
306+ComputeGraphPtr BuildReshapeGraphForTest() {
307+ auto data0 = OP_CFG("Data")
308+ .InCnt(1)
309+ .Attr(ATTR_NAME_INDEX, 0)
310+ .TensorDesc(FORMAT_ND, DT_FLOAT16, {-1, -1, -1, -1})
311+ .OutCnt(1)
312+ .OutNames({"y"})
313+ .Build("data0");
314+ auto data1 = OP_CFG("Data")
315+ .InCnt(1)
316+ .Attr(ATTR_NAME_INDEX, 1)
317+ .TensorDesc(FORMAT_ND, DT_INT64, {2})
318+ .OutCnt(1)
319+ .OutNames({"y"})
320+ .Build("data1");
321+ auto reshape =
322+ OP_CFG("Reshape").TensorDesc(FORMAT_ND, DT_FLOAT16, {-1, -1}).InCnt(2).OutCnt(1).OutNames({"y"}).Build("reshape");
323+ DEF_GRAPH(g1) {
324+ CHAIN(NODE(data0)->EDGE(0, 0)->NODE(reshape)->NODE("NetOutput", "NetOutput"));
325+ CHAIN(NODE(data1)->EDGE(0, 1)->NODE(reshape));
326+ };
327+ auto graph = ToComputeGraph(g1);
328+ graph->TopologicalSorting();
329+ for (auto &node : graph->GetAllNodes()) {
330+ if (node->GetType() == DATA) {
331+ node->GetOpDesc()->MutableOutputDesc(0)->SetPlacement(kPlacementHost);
332+ }
333+ }
334+ // 设置 Reshape 的 shape 输入为 DT_INT64,与 data1 一致,避免 autofuse 插入 Cast
335+ auto reshape_node = graph->FindNode("reshape");
336+ if (reshape_node != nullptr) {
337+ reshape_node->GetOpDesc()->MutableInputDesc(1)->SetDataType(DT_INT64);
338+ reshape_node->GetOpDesc()->MutableInputDesc(1)->SetOriginDataType(DT_INT64);
339+ reshape_node->GetOpDesc()->AppendIrInput("x", ge::kIrInputRequired);
340+ reshape_node->GetOpDesc()->AppendIrInput("shape", ge::kIrInputRequired);
341+ }
342+ return graph;
343+}
344+ 
345+// 空 graph_inputs data + option → Reshape 符号化推导成功
346+TEST_F(SymbolizeValueST, reshape_symbolize_infer_with_input_hint_value) {
347+ dlog_setlevel(0, 0, 0);
348+ auto graph = BuildReshapeGraphForTest();
349+ ASSERT_NE(graph, nullptr);
350+ GeTensor tensor0(GeTensorDesc(GeShape({5, 1, 20, 20}), FORMAT_ND, DT_FLOAT16));
351+ GeTensor tensor1(GeTensorDesc(GeShape({2}), FORMAT_ND, DT_INT64));
352+ GetThreadLocalContext().SetGraphOption({
353+ {INPUT_HINT_SHAPE, "0:[5, 1, 20, 20]"},
354+ {INPUT_HINT_VALUE, "1:[5, 400]"},
355+ });
356+ AutofuseOptimize autofuser;
357+ ASSERT_EQ(autofuser.Run(graph, {tensor0, tensor1}), ge::GRAPH_SUCCESS);
358+ 
359+ auto shape_env = graph->GetAttrsGroup<ShapeEnvAttr>();
360+ ASSERT_NE(shape_env, nullptr);
361+ ShapeEnvGuarder guarder(shape_env);
362+ auto reshape_sym = graph->FindNode("reshape")->GetOpDesc()->MutableOutputDesc(0)->GetAttrsGroup<SymbolicDescAttr>();
363+ ASSERT_NE(reshape_sym, nullptr);
364+ auto out_shape = reshape_sym->symbolic_tensor.GetOriginSymbolShape();
365+ ASSERT_EQ(out_shape.GetDimNum(), 2U);
366+ int64_t hint = -1;
367+ EXPECT_EQ(out_shape.GetDim(0).GetHint(hint), true);
368+ EXPECT_EQ(hint, 5);
369+ hint = -1;
370+ EXPECT_EQ(out_shape.GetDim(1).GetHint(hint), true);
371+ EXPECT_EQ(hint, 400);
372+}
373+ 
374+// graph_inputs 有真实 data → 以真实 data 为准
375+TEST_F(SymbolizeValueST, reshape_symbolize_infer_with_real_data) {
376+ dlog_setlevel(0, 0, 0);
377+ auto graph = BuildReshapeGraphForTest();
378+ ASSERT_NE(graph, nullptr);
379+ GeTensor tensor0(GeTensorDesc(GeShape({5, 1, 20, 20}), FORMAT_ND, DT_FLOAT16));
380+ GeTensor tensor1(GeTensorDesc(GeShape({2}), FORMAT_ND, DT_INT64));
381+ vector<int64_t> shape_val = {100, 20};
382+ tensor1.SetData(reinterpret_cast<uint8_t *>(shape_val.data()), shape_val.size() * sizeof(int64_t));
383+ AutofuseOptimize autofuser;
384+ ASSERT_EQ(autofuser.Run(graph, {tensor0, tensor1}), ge::GRAPH_SUCCESS);
385+ 
386+ auto shape_env = graph->GetAttrsGroup<ShapeEnvAttr>();
387+ ASSERT_NE(shape_env, nullptr);
388+ ShapeEnvGuarder guarder(shape_env);
389+ auto reshape_sym = graph->FindNode("reshape")->GetOpDesc()->MutableOutputDesc(0)->GetAttrsGroup<SymbolicDescAttr>();
390+ ASSERT_NE(reshape_sym, nullptr);
391+ auto out_shape = reshape_sym->symbolic_tensor.GetOriginSymbolShape();
392+ ASSERT_EQ(out_shape.GetDimNum(), 2U);
393+ int64_t hint = -1;
394+ EXPECT_EQ(out_shape.GetDim(0).GetHint(hint), true);
395+ EXPECT_EQ(hint, 100);
396+ hint = -1;
397+ EXPECT_EQ(out_shape.GetDim(1).GetHint(hint), true);
398+ EXPECT_EQ(hint, 20);
399+}
400+ 
304} // namespace ge401} // namespace ge
Atests/ge/ut/ge/graph/optimize/symbolic/symbolic_value_inference_unittest.cc+163-0
@@ -0,0 +1,163 @@
1+/**
2+ * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+#include <memory>
12+#include <utility>
13+#include <gtest/gtest.h>
14+#include "graph/utils/graph_utils_ex.h"
15+#include "common/plugin/ge_make_unique_util.h"
16+#include "compiler/graph/optimize/symbolic/infer_symbolic_shape/symbolic_shape_inference.h"
17+#include "attribute_group/attr_group_shape_env.h"
18+#include "framework/common/framework_types_internal.h"
19+#include "faker/space_registry_faker.h"
20+#include "ge_graph_dsl/graph_dsl.h"
21+#include "graph/utils/tensor_adapter.h"
22+#include "graph/operator_reg.h"
23+#include "graph/optimize/symbolic/shape_env_guarder.h"
24+#include "attribute_group/attr_group_symbolic_desc.h"
25+#include "common/env_path.h"
26+#include "mmpa/mmpa_api.h"
27+#include "ge_local_context.h"
28+#include "register/optimization_option_registry.h"
29+#include "expect_node_info_check_test.h"
30+#include "api/aclgrph/option_utils.h"
31+#include "compiler/graph/optimize/symbolic/infer_symbolic_shape/symbolic_shape_symbolizer.h"
32+ 
33+namespace ge {
34+ 
35+class SymbolicValueInferenceUT : public testing::Test {
36+ public:
37+ protected:
38+ void SetUp() override {
39+ EnableSliceScheduleEnv();
40+ dlog_setlevel(0, 0, 0);
41+ global_options_ = GetThreadLocalContext().GetAllGlobalOptions();
42+ graph_options_ = GetThreadLocalContext().GetAllGraphOptions();
43+ session_options_ = GetThreadLocalContext().GetAllSessionOptions();
44+ GetThreadLocalContext().SetGlobalOption({});
45+ GetThreadLocalContext().SetGraphOption({});
46+ GetThreadLocalContext().SetSessionOption({});
47+ std::map<std::string, std::string> options;
48+ GetThreadLocalContext().GetOo().Initialize(options, OptionRegistry::GetInstance().GetRegisteredOptTable());
49+ }
50+ void TearDown() override {
51+ GetThreadLocalContext().SetGlobalOption(global_options_);
52+ GetThreadLocalContext().SetGraphOption(graph_options_);
53+ GetThreadLocalContext().SetSessionOption(session_options_);
54+ DisableSliceScheduleEnv();
55+ }
56+ 
57+ ComputeGraphPtr CreateReshapeGraph() {
58+ auto data0 = OP_CFG("Data")
59+ .InCnt(1)
60+ .Attr(ATTR_NAME_INDEX, 0)
61+ .TensorDesc(FORMAT_ND, DT_FLOAT16, {-1, -1, -1, -1})
62+ .OutCnt(1)
63+ .OutNames({"y"})
64+ .Build("data0");
65+ auto data1 = OP_CFG("Data")
66+ .InCnt(1)
67+ .Attr(ATTR_NAME_INDEX, 1)
68+ .TensorDesc(FORMAT_ND, DT_INT64, {2})
69+ .OutCnt(1)
70+ .OutNames({"y"})
71+ .Build("data1");
72+ auto reshape = OP_CFG("Reshape")
73+ .TensorDesc(FORMAT_ND, DT_FLOAT16, {-1, -1})
74+ .InCnt(2)
75+ .OutCnt(1)
76+ .OutNames({"y"})
77+ .Build("reshape");
78+ DEF_GRAPH(g1) {
79+ CHAIN(NODE(data0)->EDGE(0, 0)->NODE(reshape)->NODE("NetOutput", "NetOutput"));
80+ CHAIN(NODE(data1)->EDGE(0, 1)->NODE(reshape));
81+ };
82+ auto cg = ToComputeGraph(g1);
83+ for (auto &node : cg->GetAllNodes()) {
84+ if (node->GetType() == DATA) {
85+ node->GetOpDesc()->MutableOutputDesc(0)->SetPlacement(kPlacementHost);
86+ }
87+ }
88+ SetNoStorage(cg, "data0", {FORMAT_ND, DT_FLOAT16, {-1, -1, -1, -1}}, 0);
89+ SetNoStorage(cg, "data1", {FORMAT_ND, DT_INT64, {2}}, 1);
90+ auto reshape_node = cg->FindNode("reshape");
91+ if (reshape_node != nullptr) {
92+ reshape_node->GetOpDesc()->AppendIrInput("x", ge::kIrInputRequired);
93+ reshape_node->GetOpDesc()->AppendIrInput("shape", ge::kIrInputRequired);
94+ }
95+ return cg;
96+ }
97+ 
98+ void RunSymbolize(const ComputeGraphPtr &cg, const std::vector<GeTensor> &graph_inputs) {
99+ GetThreadLocalContext().SetGraphOption({
100+ {INPUT_HINT_SHAPE, "0:[5, 1, 20, 20];1:[]"},
101+ {INPUT_HINT_VALUE, "1:[5, 400]"},
102+ });
103+ ASSERT_EQ(SymbolicShapeSymbolizer::Symbolize(cg, graph_inputs), SUCCESS);
104+ SymbolicShapeInference ssi;
105+ ASSERT_EQ(ssi.Infer(cg), SUCCESS);
106+ }
107+ 
108+ private:
109+ std::map<std::string, std::string> global_options_;
110+ std::map<std::string, std::string> graph_options_;
111+ std::map<std::string, std::string> session_options_;
112+};
113+ 
114+// 空 graph_inputs data + option → Reshape 符号化推导成功
115+TEST_F(SymbolicValueInferenceUT, compile_path_reshape_with_hint_value) {
116+ auto cg = CreateReshapeGraph();
117+ ASSERT_NE(cg, nullptr);
118+ std::vector<GeTensor> graph_inputs;
119+ graph_inputs.emplace_back(BuildGeTensor<float, DT_FLOAT16>({5, 1, 20, 20}, {}));
120+ graph_inputs.emplace_back(BuildGeTensor<int64_t, DT_INT64>({2}, {}));
121+ RunSymbolize(cg, graph_inputs);
122+ 
123+ auto shape_env = cg->GetAttrsGroup<ShapeEnvAttr>();
124+ ASSERT_NE(shape_env, nullptr);
125+ ShapeEnvGuarder guarder(shape_env);
126+ auto reshape_sym = cg->FindNode("reshape")->GetOpDesc()->MutableOutputDesc(0)->GetAttrsGroup<SymbolicDescAttr>();
127+ ASSERT_NE(reshape_sym, nullptr);
128+ auto out_shape = reshape_sym->symbolic_tensor.GetOriginSymbolShape();
129+ ASSERT_EQ(out_shape.GetDimNum(), 2U);
130+ int64_t hint = -1;
131+ EXPECT_EQ(out_shape.GetDim(0).GetHint(hint), true);
132+ EXPECT_EQ(hint, 5);
133+ hint = -1;
134+ EXPECT_EQ(out_shape.GetDim(1).GetHint(hint), true);
135+ EXPECT_EQ(hint, 400);
136+}
137+ 
138+// graph_inputs 有真实 data + option → 以真实 data 为准
139+TEST_F(SymbolicValueInferenceUT, execute_path_reshape_with_real_data) {
140+ auto cg = CreateReshapeGraph();
141+ ASSERT_NE(cg, nullptr);
142+ std::vector<GeTensor> graph_inputs;
143+ graph_inputs.emplace_back(BuildGeTensor<float, DT_FLOAT16>({5, 1, 20, 20}, {}));
144+ std::vector<int64_t> shape_data = {100, 20};
145+ graph_inputs.emplace_back(BuildGeTensor<int64_t, DT_INT64>({2}, shape_data));
146+ RunSymbolize(cg, graph_inputs);
147+ 
148+ auto shape_env = cg->GetAttrsGroup<ShapeEnvAttr>();
149+ ASSERT_NE(shape_env, nullptr);
150+ ShapeEnvGuarder guarder(shape_env);
151+ auto reshape_sym = cg->FindNode("reshape")->GetOpDesc()->MutableOutputDesc(0)->GetAttrsGroup<SymbolicDescAttr>();
152+ ASSERT_NE(reshape_sym, nullptr);
153+ auto out_shape = reshape_sym->symbolic_tensor.GetOriginSymbolShape();
154+ ASSERT_EQ(out_shape.GetDimNum(), 2U);
155+ int64_t hint = -1;
156+ EXPECT_EQ(out_shape.GetDim(0).GetHint(hint), true);
157+ EXPECT_EQ(hint, 100);
158+ hint = -1;
159+ EXPECT_EQ(out_shape.GetDim(1).GetHint(hint), true);
160+ EXPECT_EQ(hint, 20);
161+}
162+ 
163+} // namespace ge
Mtests/ge/ut/ge/jit_execution/jit_executor_unittest.cc+8-4
@@ -411,8 +411,9 @@ TEST_F(JitExecutorUT, run_success_when_input_graph_contain_one_reshape_node) {
411 td.SetOriginShape(Shape(shape_dim));411 td.SetOriginShape(Shape(shape_dim));
412 Tensor tensor(td);412 Tensor tensor(td);
413 std::vector<int64_t> input_data_2{2, 3, 3, 2};413 std::vector<int64_t> input_data_2{2, 3, 3, 2};
414- TensorDesc desc_2(Shape({4}), FORMAT_NCHW, DT_INT32);414+ TensorDesc desc_2(Shape({4}), FORMAT_NCHW, DT_INT64);
415 desc_2.SetOriginShape(Shape({4}));415 desc_2.SetOriginShape(Shape({4}));
416+ desc_2.SetPlacement(Placement::kPlacementHost);
416 Tensor input_tensor_2{desc_2};417 Tensor input_tensor_2{desc_2};
417 input_tensor_2.SetData(reinterpret_cast<uint8_t *>(input_data_2.data()), input_data_2.size() * sizeof(int64_t));418 input_tensor_2.SetData(reinterpret_cast<uint8_t *>(input_data_2.data()), input_data_2.size() * sizeof(int64_t));
418 std::vector<Tensor> inputs{tensor, input_tensor_2};419 std::vector<Tensor> inputs{tensor, input_tensor_2};
@@ -567,8 +568,9 @@ TEST_F(JitExecutorUT, run_success_when_input_graph_contain_one_reshape_two_relu_
567 std::vector<int64_t> input_data_1(36, 0);568 std::vector<int64_t> input_data_1(36, 0);
568 tensor.SetData(reinterpret_cast<uint8_t *>(input_data_1.data()), 36 * sizeof(int64_t));569 tensor.SetData(reinterpret_cast<uint8_t *>(input_data_1.data()), 36 * sizeof(int64_t));
569 std::vector<int64_t> input_data_2{2, 3, 3, 2};570 std::vector<int64_t> input_data_2{2, 3, 3, 2};
570- TensorDesc desc_2(Shape({4}), FORMAT_NCHW, DT_INT32);571+ TensorDesc desc_2(Shape({4}), FORMAT_NCHW, DT_INT64);
571 desc_2.SetOriginShape(Shape({4}));572 desc_2.SetOriginShape(Shape({4}));
573+ desc_2.SetPlacement(Placement::kPlacementHost);
572 Tensor input_tensor_2{desc_2};574 Tensor input_tensor_2{desc_2};
573 input_tensor_2.SetData(reinterpret_cast<uint8_t *>(input_data_2.data()), input_data_2.size() * sizeof(int64_t));575 input_tensor_2.SetData(reinterpret_cast<uint8_t *>(input_data_2.data()), input_data_2.size() * sizeof(int64_t));
574 std::vector<int64_t> data3_shape_dim = {2, 3, 3};576 std::vector<int64_t> data3_shape_dim = {2, 3, 3};
@@ -625,8 +627,9 @@ TEST_F(JitExecutorUT, run_success_when_input_graph_contain_two_reshape_node) {
625 td.SetOriginShape(Shape(shape_dim));627 td.SetOriginShape(Shape(shape_dim));
626 Tensor tensor(td);628 Tensor tensor(td);
627 std::vector<int64_t> input_data_2{2, 3, 3, 2};629 std::vector<int64_t> input_data_2{2, 3, 3, 2};
628- TensorDesc desc_2(Shape({4}), FORMAT_NCHW, DT_INT32);630+ TensorDesc desc_2(Shape({4}), FORMAT_NCHW, DT_INT64);
629 desc_2.SetOriginShape(Shape({4}));631 desc_2.SetOriginShape(Shape({4}));
632+ desc_2.SetPlacement(Placement::kPlacementHost);
630 Tensor input_tensor_2{desc_2};633 Tensor input_tensor_2{desc_2};
631 input_tensor_2.SetData(reinterpret_cast<uint8_t *>(input_data_2.data()), input_data_2.size() * sizeof(int64_t));634 input_tensor_2.SetData(reinterpret_cast<uint8_t *>(input_data_2.data()), input_data_2.size() * sizeof(int64_t));
632 std::vector<Tensor> inputs{tensor, input_tensor_2};635 std::vector<Tensor> inputs{tensor, input_tensor_2};
@@ -680,8 +683,9 @@ TEST_F(JitExecutorUT, run_success_when_input_graph_contain_two_reshape_one_const
680 td.SetOriginShape(Shape(shape_dim));683 td.SetOriginShape(Shape(shape_dim));
681 Tensor tensor(td);684 Tensor tensor(td);
682 std::vector<int64_t> input_data_2 = {2, 3, 3, 2};685 std::vector<int64_t> input_data_2 = {2, 3, 3, 2};
683- TensorDesc desc_2(Shape({4}), FORMAT_NCHW, DT_INT32);686+ TensorDesc desc_2(Shape({4}), FORMAT_NCHW, DT_INT64);
684 desc_2.SetOriginShape(Shape({4}));687 desc_2.SetOriginShape(Shape({4}));
688+ desc_2.SetPlacement(Placement::kPlacementHost);
685 Tensor input_tensor_2{desc_2};689 Tensor input_tensor_2{desc_2};
686 input_tensor_2.SetData(reinterpret_cast<uint8_t *>(input_data_2.data()), input_data_2.size() * sizeof(int64_t));690 input_tensor_2.SetData(reinterpret_cast<uint8_t *>(input_data_2.data()), input_data_2.size() * sizeof(int64_t));
687 std::vector<Tensor> inputs{tensor, input_tensor_2};691 std::vector<Tensor> inputs{tensor, input_tensor_2};
Mtests/ge/ut/ge/jit_execution/jit_share_graph.cc+14-0
@@ -28,6 +28,14 @@ void AddCompileResultByGNode(ComputeGraphPtr &cg, ge::GNode *gnode, bool atomic,
28 JitShareGraph::AddCompileResult(node, atomic, compile_info_json);28 JitShareGraph::AddCompileResult(node, atomic, compile_info_json);
29 }29 }
30}30}
31+ 
32+void SetDataNodeDtype(ComputeGraphPtr &cg, const std::string &name, DataType dt) {
33+ auto node = cg->FindNode(name);
34+ if (node != nullptr) {
35+ node->GetOpDesc()->MutableOutputDesc(0)->SetDataType(dt);
36+ node->GetOpDesc()->MutableOutputDesc(0)->SetOriginDataType(dt);
37+ }
38+}
31} // namespace39} // namespace
32 40 
33void JitShareGraph::AddCompileResult(const ge::NodePtr &node, bool atomic, const char *compile_info_json) {41void JitShareGraph::AddCompileResult(const ge::NodePtr &node, bool atomic, const char *compile_info_json) {
@@ -168,6 +176,7 @@ UniqueGraphPtr JitShareGraph::OneReshapeNodeWithHostInput(const std::vector<int6
168 es::EsGraphBuilder::SetOutput(relu1, 0);176 es::EsGraphBuilder::SetOutput(relu1, 0);
169 auto graph = es_graph.BuildAndReset();177 auto graph = es_graph.BuildAndReset();
170 auto cg = GraphUtilsEx::GetComputeGraph(*graph);178 auto cg = GraphUtilsEx::GetComputeGraph(*graph);
179+ SetDataNodeDtype(cg, "data2", DT_INT64);
171 AddCompileResultByGNode(180 AddCompileResultByGNode(
172 cg, relu1.GetProducer(), true,181 cg, relu1.GetProducer(), true,
173 "{\"vars\": {\"srcFormat\": \"NCHW\", \"dstFormat\": \"NC1HWC0\", \"dType\": \"float16\", "182 "{\"vars\": {\"srcFormat\": \"NCHW\", \"dstFormat\": \"NC1HWC0\", \"dType\": \"float16\", "
@@ -206,6 +215,7 @@ UniqueGraphPtr JitShareGraph::OneReshapeNode(const std::vector<int64_t> &input1_
206 es::EsGraphBuilder::SetOutput(relu1, 0);215 es::EsGraphBuilder::SetOutput(relu1, 0);
207 auto graph = es_graph.BuildAndReset();216 auto graph = es_graph.BuildAndReset();
208 auto cg = GraphUtilsEx::GetComputeGraph(*graph);217 auto cg = GraphUtilsEx::GetComputeGraph(*graph);
218+ SetDataNodeDtype(cg, "data1", DT_INT64);
209 AddCompileResultByGNode(219 AddCompileResultByGNode(
210 cg, relu.GetProducer(), true,220 cg, relu.GetProducer(), true,
211 "{\"vars\": {\"srcFormat\": \"NCHW\", \"dstFormat\": \"NC1HWC0\", \"dType\": \"float16\", "221 "{\"vars\": {\"srcFormat\": \"NCHW\", \"dstFormat\": \"NC1HWC0\", \"dType\": \"float16\", "
@@ -240,6 +250,7 @@ UniqueGraphPtr JitShareGraph::OneReshapeNodeTwoRelu() {
240 es::EsGraphBuilder::SetOutput(relu1, 1);250 es::EsGraphBuilder::SetOutput(relu1, 1);
241 auto graph = es_graph.BuildAndReset();251 auto graph = es_graph.BuildAndReset();
242 auto cg = GraphUtilsEx::GetComputeGraph(*graph);252 auto cg = GraphUtilsEx::GetComputeGraph(*graph);
253+ SetDataNodeDtype(cg, "data1", DT_INT64);
243 AddCompileResultByGNode(254 AddCompileResultByGNode(
244 cg, relu.GetProducer(), true,255 cg, relu.GetProducer(), true,
245 "{\"vars\": {\"srcFormat\": \"NCHW\", \"dstFormat\": \"NC1HWC0\", \"dType\": \"float16\", "256 "{\"vars\": {\"srcFormat\": \"NCHW\", \"dstFormat\": \"NC1HWC0\", \"dType\": \"float16\", "
@@ -276,6 +287,7 @@ UniqueGraphPtr JitShareGraph::TwoReshapeNodeTwoRelu() {
276 es::EsGraphBuilder::SetOutput(relu1, 0);287 es::EsGraphBuilder::SetOutput(relu1, 0);
277 auto graph = es_graph.BuildAndReset();288 auto graph = es_graph.BuildAndReset();
278 auto cg = GraphUtilsEx::GetComputeGraph(*graph);289 auto cg = GraphUtilsEx::GetComputeGraph(*graph);
290+ SetDataNodeDtype(cg, "data1", DT_INT64);
279 AddCompileResultByGNode(291 AddCompileResultByGNode(
280 cg, relu.GetProducer(), true,292 cg, relu.GetProducer(), true,
281 "{\"vars\": {\"srcFormat\": \"NCHW\", \"dstFormat\": \"NC1HWC0\", \"dType\": \"float16\", "293 "{\"vars\": {\"srcFormat\": \"NCHW\", \"dstFormat\": \"NC1HWC0\", \"dType\": \"float16\", "
@@ -323,6 +335,7 @@ UniqueGraphPtr JitShareGraph::ThreeReshapeNodeThreeRelu() {
323 es::EsGraphBuilder::SetOutput(relu3, 0);335 es::EsGraphBuilder::SetOutput(relu3, 0);
324 auto graph = es_graph.BuildAndReset();336 auto graph = es_graph.BuildAndReset();
325 auto cg = GraphUtilsEx::GetComputeGraph(*graph);337 auto cg = GraphUtilsEx::GetComputeGraph(*graph);
338+ SetDataNodeDtype(cg, "data1", DT_INT64);
326 AddCompileResultByGNode(339 AddCompileResultByGNode(
327 cg, relu0.GetProducer(), true,340 cg, relu0.GetProducer(), true,
328 "{\"vars\": {\"srcFormat\": \"NCHW\", \"dstFormat\": \"NC1HWC0\", \"dType\": \"float16\", "341 "{\"vars\": {\"srcFormat\": \"NCHW\", \"dstFormat\": \"NC1HWC0\", \"dType\": \"float16\", "
@@ -424,6 +437,7 @@ UniqueGraphPtr JitShareGraph::OneConstTwoReshapeNodeTwoRelu() {
424 es::EsGraphBuilder::SetOutput(relu1, 0);437 es::EsGraphBuilder::SetOutput(relu1, 0);
425 auto graph = es_graph.BuildAndReset();438 auto graph = es_graph.BuildAndReset();
426 auto cg = GraphUtilsEx::GetComputeGraph(*graph);439 auto cg = GraphUtilsEx::GetComputeGraph(*graph);
440+ SetDataNodeDtype(cg, "data1", DT_INT64);
427 AddCompileResultByGNode(441 AddCompileResultByGNode(
428 cg, relu.GetProducer(), true,442 cg, relu.GetProducer(), true,
429 "{\"vars\": {\"srcFormat\": \"NCHW\", \"dstFormat\": \"NC1HWC0\", \"dType\": \"float16\", "443 "{\"vars\": {\"srcFormat\": \"NCHW\", \"dstFormat\": \"NC1HWC0\", \"dType\": \"float16\", "
Mtests/ge/ut/ge/jit_execution/user_graph_manager_unittest.cc+15-47
@@ -922,28 +922,6 @@ TEST_F(UserGraphsManagerlUT, add_graph_verify_options_flow_to_ep_after_slicing)
922 EXPECT_EQ(graph_manager.Finalize(), SUCCESS);922 EXPECT_EQ(graph_manager.Finalize(), SUCCESS);
923}923}
924 924 
925-static void VerifyEpOptions(const std::vector<std::unique_ptr<ge::ExecutionPoint>> &slice_graphs) {
926- EXPECT_GE(slice_graphs.size(), 2U) << "should have first + last EPs";
927- 
928- auto &first_opts = slice_graphs.front()->GetEpGraphOptions();
929- EXPECT_NE(first_opts.find("ge.inputShape"), first_opts.end());
930- EXPECT_EQ(first_opts.size(), 3U);
931- 
932- for (size_t i = 1; i < slice_graphs.size() - 1; ++i) {
933- auto &mid_opts = slice_graphs[i]->GetEpGraphOptions();
934- EXPECT_EQ(mid_opts.find("ge.inputShape"), mid_opts.end());
935- EXPECT_EQ(mid_opts.find("ge.outputDatatype"), mid_opts.end());
936- EXPECT_NE(mid_opts.find("my.custom"), mid_opts.end());
937- EXPECT_EQ(mid_opts.size(), 1U);
938- }
939- 
940- auto &last_opts = slice_graphs.back()->GetEpGraphOptions();
941- EXPECT_EQ(last_opts.find("ge.inputShape"), last_opts.end());
942- EXPECT_NE(last_opts.find("ge.outputDatatype"), last_opts.end());
943- EXPECT_NE(last_opts.find("my.custom"), last_opts.end());
944- EXPECT_EQ(last_opts.size(), 2U);
945-}
946- 
947TEST_F(UserGraphsManagerlUT, add_graph_verify_multi_ep_options_seperation) {925TEST_F(UserGraphsManagerlUT, add_graph_verify_multi_ep_options_seperation) {
948 ModelExecutor model_executor;926 ModelExecutor model_executor;
949 model_executor.Initialize({}, 0);927 model_executor.Initialize({}, 0);
@@ -967,8 +945,7 @@ TEST_F(UserGraphsManagerlUT, add_graph_verify_multi_ep_options_seperation) {
967 gert::kOnDeviceHbm,945 gert::kOnDeviceHbm,
968 ge::DT_FLOAT,946 ge::DT_FLOAT,
969 data0.data()};947 data0.data()};
970- inputs[1] = {948+ inputs[1] = {{{4}, {4}}, {ge::FORMAT_ND, ge::FORMAT_FRACTAL_NZ, {}}, gert::kOnHost, ge::DT_INT64, shape_data.data()};
971- {{4}, {4}}, {ge::FORMAT_ND, ge::FORMAT_FRACTAL_NZ, {}}, gert::kOnDeviceHbm, ge::DT_INT64, shape_data.data()};
972 949 
973 std::promise<Status> promise;950 std::promise<Status> promise;
974 auto future = promise.get_future();951 auto future = promise.get_future();
@@ -980,7 +957,12 @@ TEST_F(UserGraphsManagerlUT, add_graph_verify_multi_ep_options_seperation) {
980 promise.set_value(FAILED);957 promise.set_value(FAILED);
981 return FAILED;958 return FAILED;
982 }959 }
983- VerifyEpOptions(ctrl->order_.slice_graphs_);960+ EXPECT_EQ(ctrl->order_.slice_graphs_.size(), 1U) << "reshape not break since value symbolization";
961+ auto &opts = ctrl->order_.slice_graphs_.front()->GetEpGraphOptions();
962+ EXPECT_NE(opts.find("ge.inputShape"), opts.end());
963+ EXPECT_NE(opts.find("ge.outputDatatype"), opts.end());
964+ EXPECT_NE(opts.find("my.custom"), opts.end());
965+ EXPECT_EQ(opts.size(), 3U);
984 promise.set_value(status);966 promise.set_value(status);
985 return SUCCESS;967 return SUCCESS;
986 };968 };
@@ -992,24 +974,6 @@ TEST_F(UserGraphsManagerlUT, add_graph_verify_multi_ep_options_seperation) {
992 EXPECT_EQ(graph_manager.Finalize(), SUCCESS);974 EXPECT_EQ(graph_manager.Finalize(), SUCCESS);
993}975}
994 976 
995-static void VerifyThreeEpOptions(const std::vector<std::unique_ptr<ge::ExecutionPoint>> &slice_graphs) {
996- ASSERT_GE(slice_graphs.size(), 3U) << "should have at least 3 EPs (first + middle + ...)";
997- 
998- auto &first_opts = slice_graphs.front()->GetEpGraphOptions();
999- EXPECT_NE(first_opts.find("ge.inputShape"), first_opts.end());
1000- EXPECT_EQ(first_opts.size(), 3U);
1001- 
1002- for (size_t i = 1; i < slice_graphs.size(); ++i) {
1003- auto &mid_opts = slice_graphs[i]->GetEpGraphOptions();
1004- EXPECT_EQ(mid_opts.find("ge.inputShape"), mid_opts.end());
1005- EXPECT_NE(mid_opts.find("my.custom"), mid_opts.end());
1006- if (i < slice_graphs.size() - 1) {
1007- EXPECT_EQ(mid_opts.find("ge.outputDatatype"), mid_opts.end());
1008- EXPECT_EQ(mid_opts.size(), 1U);
1009- }
1010- }
1011-}
1012- 
1013TEST_F(UserGraphsManagerlUT, add_graph_verify_three_ep_middle_options) {977TEST_F(UserGraphsManagerlUT, add_graph_verify_three_ep_middle_options) {
1014 ModelExecutor model_executor;978 ModelExecutor model_executor;
1015 model_executor.Initialize({}, 0);979 model_executor.Initialize({}, 0);
@@ -1033,19 +997,23 @@ TEST_F(UserGraphsManagerlUT, add_graph_verify_three_ep_middle_options) {
1033 gert::kOnDeviceHbm,997 gert::kOnDeviceHbm,
1034 ge::DT_FLOAT,998 ge::DT_FLOAT,
1035 data0.data()};999 data0.data()};
1036- inputs[1] = {1000+ inputs[1] = {{{4}, {4}}, {ge::FORMAT_ND, ge::FORMAT_FRACTAL_NZ, {}}, gert::kOnHost, ge::DT_INT64, shape_data.data()};
1037- {{4}, {4}}, {ge::FORMAT_ND, ge::FORMAT_FRACTAL_NZ, {}}, gert::kOnDeviceHbm, ge::DT_INT64, shape_data.data()};
1038 1001 
1039 std::promise<Status> promise;1002 std::promise<Status> promise;
1040 auto future = promise.get_future();1003 auto future = promise.get_future();
1041 auto *ugm_ptr = &user_graph_manager;1004 auto *ugm_ptr = &user_graph_manager;
1042 const RunAsyncCallbackV2 callback = [&](Status status, std::vector<gert::Tensor> &outputs) {1005 const RunAsyncCallbackV2 callback = [&](Status status, std::vector<gert::Tensor> &outputs) {
1043 auto *ctrl = ugm_ptr->ids_to_user_graph_ctrl_[user_graph_id].get();1006 auto *ctrl = ugm_ptr->ids_to_user_graph_ctrl_[user_graph_id].get();
1044- if (ctrl == nullptr || ctrl->order_.slice_graphs_.size() < 3U) {1007+ if (ctrl == nullptr || ctrl->order_.slice_graphs_.empty()) {
1045 promise.set_value(FAILED);1008 promise.set_value(FAILED);
1046 return FAILED;1009 return FAILED;
1047 }1010 }
1048- VerifyThreeEpOptions(ctrl->order_.slice_graphs_);1011+ EXPECT_EQ(ctrl->order_.slice_graphs_.size(), 1U) << "reshape not break since value symbolization";
1012+ auto &opts = ctrl->order_.slice_graphs_.front()->GetEpGraphOptions();
1013+ EXPECT_NE(opts.find("ge.inputShape"), opts.end());
1014+ EXPECT_NE(opts.find("ge.outputDatatype"), opts.end());
1015+ EXPECT_NE(opts.find("my.custom"), opts.end());
1016+ EXPECT_EQ(opts.size(), 3U);
1049 promise.set_value(SUCCESS);1017 promise.set_value(SUCCESS);
1050 return SUCCESS;1018 return SUCCESS;
1051 };1019 };