已合并
【PR】: Host tensor value symbolize #4443
chengyutao3创建于 2 天前
【PR】: Host tensor value symbolize #4443
已合并
共 14 个文件变更+696-110
| @@ -20,6 +20,7 @@ namespace ge { | |||
| 20 | namespace { | 20 | namespace { |
| 21 | const std::unordered_set<std::string> kFirstEPOptions = {INPUT_SHAPE, | 21 | const 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, |
| @@ -20,6 +20,7 @@ | |||
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | 22 | ||
| 23 | + | ||
| 23 | 24 | ||
| 24 | 25 | ||
| 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 handle | 80 | // todo if host exec option, remember to handle |
| 80 | Status CopyHostInputsToDevice(UserGraphExecution &execution_task, Allocator *const allocator, | 81 | Status 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 | ||
| 90 | Status FreeInputsAllocByJit(std::vector<MemBlock *> &input_blocks) { | 136 | Status 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)); | ||
| 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; | ||
🔴 Critical 建议:将第 175 行内容补全为 当前建议代码无改动
![]() ![]() | |||
| 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); |
| @@ -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 | ||
| 230 | static Status CheckSupportedOptions(const std::map<std::string, std::string> &input_options, | 230 | static 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) { |
| @@ -113,6 +113,7 @@ const char *const kInputShapeRangeSample5 = "\"16\""; | |||
| 113 | const char *const kInputShapeRangeSample6 = "\"input_name1:n1~n2,c1,h1,w1\""; | 113 | const char *const kInputShapeRangeSample6 = "\"input_name1:n1~n2,c1,h1,w1\""; |
| 114 | const char *const kInputShapeRangeSample7 = "\"n1~n2,c1,h1,w1;n3,c2,h2,w2\""; | 114 | const char *const kInputShapeRangeSample7 = "\"n1~n2,c1,h1,w1;n3,c2,h2,w2\""; |
| 115 | const char *const kHintInputShape = "ge.inputHintShape"; | 115 | const char *const kHintInputShape = "ge.inputHintShape"; |
| 116 | +const char *const kHintInputValue = "ge.inputHintValue"; | ||
| 116 | 117 | ||
| 117 | const std::unordered_set<std::string> kSupportedPrintMode = {"enable", "disable"}; | 118 | const std::unordered_set<std::string> kSupportedPrintMode = {"enable", "disable"}; |
| 118 | const std::unordered_set<std::string> kValidHostEnvOs = {"minios", "linux"}; | 119 | const 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 | + | ||
| 155 | static bool StringToLongNoThrow(const std::string &str, long &val) { | 215 | static 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 | + | ||
| 1122 | std::string GetAutofuseFlagValue(const std::string &option) { | 1165 | std::string GetAutofuseFlagValue(const std::string &option) { |
| 1123 | // 自动融合新的环境变量 | 1166 | // 自动融合新的环境变量 |
| 1124 | const char_t *auto_fuse_options = nullptr; | 1167 | const char_t *auto_fuse_options = nullptr; |
| @@ -17,6 +17,7 @@ | |||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | + | ||
| 20 | 21 | ||
| 21 | 22 | ||
| 22 | 23 | ||
| @@ -80,6 +81,13 @@ Status CheckAndTransferInputShapeToRange(std::string &input_shape, std::string & | |||
| 80 | */ | 81 | */ |
| 81 | Status ParseHintInputShape(std::vector<GeShape> &option_shape); | 82 | Status 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 | + | ||
| 83 | Status ParserShapeRangeByName(std::string &input_shape, std::string &input_shape_range); | 91 | Status ParserShapeRangeByName(std::string &input_shape, std::string &input_shape_range); |
| 84 | 92 | ||
| 85 | Status CheckDynamicInputParamValid(std::string &dynamic_batch_size, std::string &dynamic_image_size, | 93 | Status CheckDynamicInputParamValid(std::string &dynamic_batch_size, std::string &dynamic_image_size, |
| @@ -10,13 +10,23 @@ | |||
| 10 | 10 | ||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | + | ||
| 14 | + | ||
| 13 | 15 | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 14 | 20 | ||
| 15 | 21 | ||
| 16 | 22 | ||
| 17 | namespace ge { | 23 | namespace ge { |
| 18 | constexpr static size_t kByteBitCount = 8UL; | 24 | constexpr static size_t kByteBitCount = 8UL; |
| 19 | 25 | ||
| 26 | +namespace { | ||
| 27 | +constexpr const char *const kValueDependentIdxsAttr = "_ge_value_dependent_idxs"; | ||
| 28 | +} // namespace | ||
| 29 | + | ||
| 20 | graphStatus SymbolicInferUtil::GetConstInt(const gert::SymbolTensor *tensor, DataType dt, int64_t &value) { | 30 | graphStatus 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 ge | 222 | } // namespace ge |
| @@ -10,6 +10,8 @@ | |||
| 10 | 10 | ||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | + | ||
| 14 | + | ||
| 13 | 15 | ||
| 14 | 16 | ||
| 15 | 17 | ||
| @@ -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 ge | 147 | } // namespace ge |
| 144 | 148 | ||
| @@ -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 | + | ||
| 11 | 12 | ||
| 13 | + | ||
| 12 | 14 | ||
| 13 | 15 | ||
| 14 | 16 | ||
| @@ -26,6 +28,8 @@ | |||
| 26 | 28 | ||
| 27 | 29 | ||
| 28 | 30 | ||
| 31 | + | ||
| 32 | + | ||
| 29 | 33 | ||
| 30 | namespace ge { | 34 | namespace ge { |
| 31 | namespace { | 35 | namespace { |
| @@ -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并且求平均 |
| 79 | const char_t *const kSymbolizeValueType = "_symbolize_value_type"; | 87 | const char_t *const kSymbolizeValueType = "_symbolize_value_type"; |
| 80 | enum SymbolizeValueType { | 88 | enum 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 | + | ||
| 175 | bool IsAippInput(const NodePtr &data_node) { | 260 | bool 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 | + | ||
| 384 | std::string InputRankSource::GetSourceStr() const { | 496 | std::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()" + |
| @@ -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 | + | ||
| 49 | class InputRankSource final : public ge::Source { | 62 | class 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) {} |
| @@ -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 ge | 401 | } // namespace ge |
| @@ -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 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + | ||
| 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 | ||
| @@ -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}; |
| @@ -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 | - | ||
| 947 | TEST_F(UserGraphsManagerlUT, add_graph_verify_multi_ep_options_seperation) { | 925 | TEST_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 | - | ||
| 1013 | TEST_F(UserGraphsManagerlUT, add_graph_verify_three_ep_middle_options) { | 977 | TEST_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 | }; |


🔴 Critical