You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

ge_aipp_op.cc 33 kB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702
  1. /**
  2. * Copyright 2019-2020 Huawei Technologies Co., Ltd
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "graph/preprocess/insert_op/ge_aipp_op.h"
  17. #include <memory>
  18. #include <set>
  19. #include <string>
  20. #include <utility>
  21. #include <vector>
  22. #include "base_insert_op.h"
  23. #include "common/dynamic_aipp.h"
  24. #include "common/ge/ge_util.h"
  25. #include "common/util.h"
  26. #include "external/graph/operator_factory.h"
  27. #include "framework/common/debug/ge_log.h"
  28. #include "framework/common/ge_inner_error_codes.h"
  29. #include "framework/common/op/ge_op_utils.h"
  30. #include "framework/common/types.h"
  31. #include "framework/omg/omg_inner_types.h"
  32. #include "graph/debug/ge_attr_define.h"
  33. #include "graph/optimize/common/params.h"
  34. #include "graph/utils/graph_utils.h"
  35. #include "graph/utils/node_utils.h"
  36. #include "graph/utils/op_desc_utils.h"
  37. #include "graph/utils/tensor_utils.h"
  38. #include "graph/utils/type_utils.h"
  39. #include "proto/insert_op.pb.h"
  40. #define SAVE_AIPP_ATTR(KEY, SAVE_TYPE) \
  41. do { \
  42. (void)aipp_attrs.SetAttr(#KEY, GeAttrValue::CreateFrom<SAVE_TYPE>(aipp_params_->KEY())); \
  43. } while (0)
  44. #define SAVE_AIPP_ATTR_LIST(KEY, SAVE_TYPE) \
  45. do { \
  46. if (aipp_params_->KEY##_size() > 0) { \
  47. (void)aipp_attrs.SetAttr(#KEY, GeAttrValue::CreateFrom<SAVE_TYPE>(aipp_params_->KEY(0))); \
  48. } \
  49. } while (0)
  50. namespace {
  51. const int32_t DEFAULT_MATRIX_R0C0_YUV2RGB = 298;
  52. const int32_t DEFAULT_MATRIX_R0C1_YUV2RGB = 0;
  53. const int32_t DEFAULT_MATRIX_R0C2_YUV2RGB = 409;
  54. const int32_t DEFAULT_MATRIX_R1C0_YUV2RGB = 298;
  55. const int32_t DEFAULT_MATRIX_R1C1_YUV2RGB = -100;
  56. const int32_t DEFAULT_MATRIX_R1C2_YUV2RGB = -208;
  57. const int32_t DEFAULT_MATRIX_R2C0_YUV2RGB = 298;
  58. const int32_t DEFAULT_MATRIX_R2C1_YUV2RGB = 516;
  59. const int32_t DEFAULT_MATRIX_R2C2_YUV2RGB = 0;
  60. const int32_t DEFAULT_MATRIX_R0C0_RGB2YUV = 66;
  61. const int32_t DEFAULT_MATRIX_R0C1_RGB2YUV = 129;
  62. const int32_t DEFAULT_MATRIX_R0C2_RGB2YUV = 25;
  63. const int32_t DEFAULT_MATRIX_R1C0_RGB2YUV = -38;
  64. const int32_t DEFAULT_MATRIX_R1C1_RGB2YUV = -74;
  65. const int32_t DEFAULT_MATRIX_R1C2_RGB2YUV = 112;
  66. const int32_t DEFAULT_MATRIX_R2C0_RGB2YUV = 112;
  67. const int32_t DEFAULT_MATRIX_R2C1_RGB2YUV = -94;
  68. const int32_t DEFAULT_MATRIX_R2C2_RGB2YUV = -18;
  69. const int32_t DEFAULT_OUTPUT_BIAS_0 = 16;
  70. const int32_t DEFAULT_OUTPUT_BIAS_1 = 128;
  71. const int32_t DEFAULT_OUTPUT_BIAS_2 = 128;
  72. const int32_t DEFAULT_INPUT_BIAS_0 = 16;
  73. const int32_t DEFAULT_INPUT_BIAS_1 = 128;
  74. const int32_t DEFAULT_INPUT_BIAS_2 = 128;
  75. const float DEFAULT_VAR_RECI_CHN = 1.0;
  76. } // namespace
  77. namespace ge {
  78. namespace {
  79. const char *const kMbatchSwitchnName = "mbatch-switch-name";
  80. const char *const kAippConfigPath = "aipp_config_path";
  81. const char *const kCurrentAippIndex = "current_aipp_index";
  82. const char *const kDynamicAippData = "ascend_dynamic_aipp_data";
  83. const uint64_t kMinTransferShape = 3;
  84. const int kAippImageInputIndex = 0;
  85. const int kAippParamsInputIndex = 1;
  86. const int kAippDataOutputIndex = 0;
  87. // the `format` must one NCHW or NHWC
  88. Status GetDataDimN(const ge::NodePtr &data_node, ge::Format format, int64_t &batch) {
  89. auto output_desc = NodeUtils::GetOutputDesc(*data_node, 0);
  90. auto shape = output_desc.GetShape().GetDims();
  91. if (shape.size() == kMinTransferShape) {
  92. batch = 1;
  93. return SUCCESS;
  94. }
  95. if (shape.size() == DIM_DEFAULT_SIZE) {
  96. switch (format) {
  97. case FORMAT_NCHW:
  98. batch = shape[NCHW_DIM_N];
  99. return SUCCESS;
  100. case FORMAT_NHWC:
  101. batch = shape[NHWC_DIM_N];
  102. return SUCCESS;
  103. default:
  104. GELOGE(PARAM_INVALID, "Not support data format: %s", TypeUtils::FormatToSerialString(format).c_str());
  105. return PARAM_INVALID;
  106. }
  107. }
  108. GELOGE(PARAM_INVALID, "when dynamic aipp, shape must be in range [3, 4], but is %zu", shape.size());
  109. return PARAM_INVALID;
  110. }
  111. // the batch_count must be more than 0
  112. int64_t CalcMaxSize(int64_t batch_count) {
  113. batch_count--;
  114. if (batch_count > 0) {
  115. if (INT64_MAX / batch_count < static_cast<int64_t>(sizeof(kAippDynamicBatchPara))) {
  116. return -1;
  117. }
  118. }
  119. int64_t size = batch_count * sizeof(kAippDynamicBatchPara);
  120. if (INT64_MAX - static_cast<int64_t>(sizeof(kAippDynamicPara)) < size) {
  121. return -1;
  122. }
  123. return size + sizeof(kAippDynamicPara);
  124. }
  125. Format GetAndCheckFormat() {
  126. switch (domi::GetContext().format) {
  127. case domi::DOMI_TENSOR_NCHW:
  128. return FORMAT_NCHW;
  129. case domi::DOMI_TENSOR_NHWC:
  130. return FORMAT_NHWC;
  131. default:
  132. GELOGE(PARAM_INVALID, "Unexpected format found %d", static_cast<int>(domi::GetContext().format));
  133. return FORMAT_ND;
  134. }
  135. }
  136. } // namespace
  137. Status AippOp::Init(domi::AippOpParams *aipp_params) {
  138. aipp_params_ = new (std::nothrow) domi::AippOpParams();
  139. if (aipp_params_ == nullptr) {
  140. return FAILED;
  141. }
  142. aipp_params_->CopyFrom(*aipp_params);
  143. return SUCCESS;
  144. }
  145. AippOp::~AippOp() {
  146. if (aipp_params_ != nullptr) {
  147. delete aipp_params_;
  148. aipp_params_ = nullptr;
  149. }
  150. }
  151. Status AippOp::InsertAippToGraph(ComputeGraphPtr &graph, std::string &aippConfigPath, const uint32_t index) {
  152. GE_CHECK_NOTNULL(graph);
  153. NodePtr target_input = nullptr;
  154. std::vector<std::pair<OutDataAnchorPtr, InDataAnchorPtr>> target_edges;
  155. GE_CHK_STATUS_RET(this->GetTargetPosition(graph, target_input, target_edges), "Get data nodes position failed");
  156. std::map<OutDataAnchorPtr, NodePtr> out_anchors_to_aipp;
  157. for (auto &out_in_anchors : target_edges) {
  158. auto iter = out_anchors_to_aipp.find(out_in_anchors.first);
  159. if (iter == out_anchors_to_aipp.end()) {
  160. auto aipp = CreateAipp(graph, out_in_anchors.first, aippConfigPath, index);
  161. GE_CHECK_NOTNULL(aipp);
  162. out_anchors_to_aipp[out_in_anchors.first] = aipp;
  163. auto ret = GraphUtils::InsertNodeBetweenDataAnchors(out_in_anchors.first, out_in_anchors.second, aipp);
  164. if (ret != GRAPH_SUCCESS) {
  165. GELOGE(INTERNAL_ERROR, "Failed to link edges for aipp node %s", aipp->GetName().c_str());
  166. return INTERNAL_ERROR;
  167. }
  168. // add aipp data if needed
  169. if (GetAippMode() == domi::AippOpParams::dynamic) {
  170. ret = CreateAippData(graph, aipp);
  171. if (ret != SUCCESS) {
  172. GELOGE(INTERNAL_ERROR, "Failed to create aipp data for aipp %s data %s", aipp->GetName().c_str(),
  173. out_in_anchors.first->GetOwnerNode()->GetName().c_str());
  174. return INTERNAL_ERROR;
  175. }
  176. }
  177. GELOGI("Create aipp %s and insert it to the graph", aipp->GetName().c_str());
  178. } else {
  179. out_in_anchors.second->UnlinkAll();
  180. auto &aipp = iter->second;
  181. auto ret = out_in_anchors.second->LinkFrom(aipp->GetOutDataAnchor(0));
  182. if (ret != GRAPH_SUCCESS) {
  183. GELOGE(INTERNAL_ERROR, "Failed to link aipp %s to the peer node %s", aipp->GetName().c_str(),
  184. out_in_anchors.second->GetOwnerNode()->GetName().c_str());
  185. return INTERNAL_ERROR;
  186. }
  187. }
  188. }
  189. return SUCCESS;
  190. }
  191. NodePtr AippOp::CreateAipp(const ComputeGraphPtr &graph, const OutDataAnchorPtr &out_anchor,
  192. const std::string &aippConfigPath, const uint32_t &index) {
  193. std::string current_name =
  194. out_anchor->GetOwnerNode()->GetName() + "_" + std::to_string(out_anchor->GetIdx()) + "_huawei_aipp";
  195. auto aipp_opdesc_ptr = MakeShared<OpDesc>(current_name, AIPP);
  196. if (aipp_opdesc_ptr == nullptr) {
  197. GELOGE(OUT_OF_MEMORY, "Failed to alloc aipp desc, name %s", current_name.c_str());
  198. return nullptr;
  199. }
  200. // Update attributes
  201. GeAttrValue::NAMED_ATTRS aipp_attr;
  202. ConvertParamToAttr(aipp_attr);
  203. if (!AttrUtils::SetNamedAttrs(aipp_opdesc_ptr, ATTR_NAME_AIPP, aipp_attr)) {
  204. GELOGE(INTERNAL_ERROR, "Set name attrs for aipp node failed");
  205. return nullptr;
  206. }
  207. if (!AttrUtils::SetStr(aipp_opdesc_ptr, kAippConfigPath, aippConfigPath)) {
  208. GELOGE(INTERNAL_ERROR, "Set config file path attr for aipp node failed");
  209. return nullptr;
  210. }
  211. if (!AttrUtils::SetListStr(aipp_opdesc_ptr, ATTR_NAME_DATA_DUMP_ORIGIN_OP_NAMES, std::vector<std::string>())) {
  212. GELOGE(INTERNAL_ERROR, "Set ATTR_NAME_DATA_DUMP_ORIGIN_OP_NAMES attr for aipp node failed");
  213. return nullptr;
  214. }
  215. if (!AttrUtils::SetInt(aipp_opdesc_ptr, kCurrentAippIndex, index)) {
  216. GELOGE(INTERNAL_ERROR, "Set kCurrentAippIndex attr for aipp node failed");
  217. return nullptr;
  218. }
  219. // add input/output desc
  220. GeTensorDesc tensor;
  221. auto ret = aipp_opdesc_ptr->AddInputDesc("images", tensor);
  222. if (ret != GRAPH_SUCCESS) {
  223. GELOGE(INTERNAL_ERROR, "Failed to add input images for aipp node");
  224. return nullptr;
  225. }
  226. if (GetAippMode() == domi::AippOpParams::dynamic) {
  227. ret = aipp_opdesc_ptr->AddOptionalInputDesc("params", tensor);
  228. if (ret != GRAPH_SUCCESS) {
  229. GELOGE(INTERNAL_ERROR, "Failed to add input params for aipp node");
  230. return nullptr;
  231. }
  232. }
  233. ret = aipp_opdesc_ptr->AddOutputDesc("features", tensor);
  234. if (ret != GRAPH_SUCCESS) {
  235. GELOGE(INTERNAL_ERROR, "Failed to add output features for aipp node");
  236. return nullptr;
  237. }
  238. // Update input desc, the output desc will be flushed when InferShape
  239. auto node_desc = out_anchor->GetOwnerNode()->GetOpDesc();
  240. if (node_desc == nullptr) {
  241. return nullptr;
  242. }
  243. auto opdesc_src_data = node_desc->GetOutputDesc(out_anchor->GetIdx());
  244. if (opdesc_src_data.GetDataType() != DT_FLOAT) {
  245. GELOGW("The datatype of data node %s is not FP32", node_desc->GetName().c_str());
  246. opdesc_src_data.SetDataType(DT_FLOAT);
  247. }
  248. // We must get the TensorDesc from the output anchor on the Data node,
  249. // and update the TensorDesc to the input anchor on the Aipp node.
  250. // Because the InferShape function for the Aipp node needs the input tensor format,
  251. // but the InferFormat process before InferShape can not infer the format
  252. // if the tensor on the Aipp has an unknown shape
  253. if (aipp_opdesc_ptr->UpdateInputDesc(kAippImageInputIndex, opdesc_src_data) != GRAPH_SUCCESS) {
  254. GELOGE(INTERNAL_ERROR, "Failed to update the output desc from node %s to aipp %s", node_desc->GetName().c_str(),
  255. aipp_opdesc_ptr->GetName().c_str());
  256. return nullptr;
  257. }
  258. return graph->AddNode(aipp_opdesc_ptr);
  259. }
  260. domi::AippOpParams::AippMode AippOp::GetAippMode() { return aipp_params_->aipp_mode(); }
  261. NodePtr AippOp::FindDataByIndex(const ComputeGraphPtr &graph, int rank) {
  262. int64_t data_index = 0;
  263. for (auto &node : graph->GetDirectNode()) {
  264. if (node->GetType() != DATA) {
  265. continue;
  266. }
  267. // There is no `index` attribute on the `Data` node when compile in inference scene
  268. // so we can only use the order of all `Data` nodes to infer the data index
  269. if (data_index++ != rank) {
  270. continue;
  271. }
  272. return node;
  273. }
  274. GELOGE(PARAM_INVALID, "Can not find the data node by index %d", rank);
  275. return nullptr;
  276. }
  277. Status AippOp::GetAndCheckTarget(const ComputeGraphPtr &graph, int rank, NodePtr &target,
  278. std::set<uint32_t> &edge_indexes) {
  279. auto data_node = FindDataByIndex(graph, rank);
  280. if (data_node == nullptr) {
  281. GELOGE(PARAM_INVALID, "Get target input node for rank %d failed", rank);
  282. return PARAM_INVALID;
  283. }
  284. // In scenario AIPP+CONV2D+POOLING, keep the aipp info to Data, since AIPP disappear after subgraph optimize
  285. GeAttrValue::NAMED_ATTRS aipp_attr;
  286. ConvertParamToAttr(aipp_attr);
  287. if (!AttrUtils::SetNamedAttrs(data_node->GetOpDesc(), ATTR_NAME_AIPP, aipp_attr)) {
  288. GELOGE(INTERNAL_ERROR, "Set name attrs for Data node failed. id: %d", rank);
  289. return INTERNAL_ERROR;
  290. }
  291. if (aipp_params_->input_edge_idx_size() > 0) {
  292. for (auto edge_index : aipp_params_->input_edge_idx()) {
  293. edge_indexes.insert(edge_index);
  294. }
  295. }
  296. if (!edge_indexes.empty() && (*edge_indexes.rbegin() >= data_node->GetOutDataNodes().size())) {
  297. GELOGE(PARAM_INVALID, "input_edge_idx %u should smaller than out edge size of target input %zu",
  298. *edge_indexes.rbegin(), data_node->GetOutDataNodes().size());
  299. return PARAM_INVALID;
  300. }
  301. target = data_node;
  302. std::string related_node_name;
  303. if ((GetAippMode() == domi::AippOpParams::static_) &&
  304. AttrUtils::GetStr(data_node->GetOpDesc(), kMbatchSwitchnName, related_node_name)) {
  305. if (related_node_name.empty()) {
  306. GELOGE(INTERNAL_ERROR, "The data node %s has switchn node flag, but the value is empty",
  307. data_node->GetName().c_str());
  308. return INTERNAL_ERROR;
  309. }
  310. auto switchn = graph->FindNode(related_node_name);
  311. if (switchn == nullptr) {
  312. GELOGE(INTERNAL_ERROR, "The data node %s has switchn node %s, but can not find it on the graph",
  313. data_node->GetName().c_str(), related_node_name.c_str());
  314. return INTERNAL_ERROR;
  315. }
  316. target = switchn;
  317. GELOGI(
  318. "Multi-batch/image size and static aipp for data %s, "
  319. "the aipp node will be insert after %s instead of origin data node",
  320. data_node->GetName().c_str(), switchn->GetName().c_str());
  321. }
  322. return SUCCESS;
  323. }
  324. Status AippOp::GetTargetPosition(ComputeGraphPtr graph, NodePtr &target_input,
  325. std::vector<std::pair<OutDataAnchorPtr, InDataAnchorPtr>> &target_edges) {
  326. GE_CHECK_NOTNULL(graph);
  327. GE_CHECK_NOTNULL(aipp_params_);
  328. std::set<uint32_t> edge_indexes;
  329. const uint32_t related_input_rank = aipp_params_->related_input_rank();
  330. auto ret = GetAndCheckTarget(graph, related_input_rank, target_input, edge_indexes);
  331. if (ret != SUCCESS) {
  332. GELOGE(ret, "Get target input node for rank %u failed", related_input_rank);
  333. return ret;
  334. }
  335. target_edges.clear();
  336. for (OutDataAnchorPtr &src_out : target_input->GetAllOutDataAnchors()) {
  337. auto dst_ins = src_out->GetPeerInDataAnchors();
  338. for (uint32_t i = 0; i < dst_ins.size(); ++i) {
  339. auto dst_in = dst_ins.at(i);
  340. if (edge_indexes.empty() || edge_indexes.count(i) > 0) {
  341. target_edges.emplace_back(src_out, dst_in);
  342. }
  343. }
  344. }
  345. return SUCCESS;
  346. }
  347. Status AippOp::SetDefaultParams() {
  348. GE_CHECK_NOTNULL(aipp_params_);
  349. const domi::AippOpParams::AippMode aipp_mode = aipp_params_->aipp_mode();
  350. if (aipp_mode == domi::AippOpParams::static_) {
  351. if (aipp_params_->csc_switch()) {
  352. SetCscDefaultValue();
  353. }
  354. SetDtcDefaultValue();
  355. GELOGI("parse aipp params:input_format:%s, csc_switch:%d.",
  356. domi::AippOpParams::InputFormat_Name(aipp_params_->input_format()).c_str(), aipp_params_->csc_switch());
  357. GELOGI("parse aipp params:mean_chn_0:%d, mean_chn_1:%d, mean_chn_2:%d, mean_chn_3:%d.", aipp_params_->mean_chn_0(),
  358. aipp_params_->mean_chn_1(), aipp_params_->mean_chn_2(), aipp_params_->mean_chn_3());
  359. GELOGI("parse aipp params:min_chn_0:%f, min_chn_1:%f, min_chn_2:%f.", aipp_params_->min_chn_0(),
  360. aipp_params_->min_chn_1(), aipp_params_->min_chn_2());
  361. GE_IF_BOOL_EXEC(!aipp_params_->crop(), aipp_params_->set_load_start_pos_h(0); aipp_params_->set_load_start_pos_w(0);
  362. aipp_params_->set_crop_size_h(0); aipp_params_->set_crop_size_w(0););
  363. GE_IF_BOOL_EXEC(!aipp_params_->resize(), aipp_params_->set_resize_output_h(0);
  364. aipp_params_->set_resize_output_w(0););
  365. GE_IF_BOOL_EXEC(!aipp_params_->padding(), aipp_params_->set_left_padding_size(0);
  366. aipp_params_->set_right_padding_size(0); aipp_params_->set_top_padding_size(0);
  367. aipp_params_->set_bottom_padding_size(0););
  368. }
  369. return SUCCESS;
  370. }
  371. Status AippOp::ValidateParams() {
  372. GE_CHECK_NOTNULL(aipp_params_);
  373. GE_CHK_BOOL_RET_STATUS(aipp_params_->aipp_mode() != domi::AippOpParams::undefined, PARAM_INVALID,
  374. "when insert AIPP op, aipp_mode must be configured as static or dynamic ");
  375. GE_CHK_BOOL_RET_STATUS(aipp_params_->var_reci_chn_0_size() <= 1, PARAM_INVALID,
  376. "The parameter var_reci_chn_0 can not be configed repeatedly");
  377. GE_CHK_BOOL_RET_STATUS(aipp_params_->var_reci_chn_1_size() <= 1, PARAM_INVALID,
  378. "The parameter var_reci_chn_1 can not be configed repeatedly");
  379. GE_CHK_BOOL_RET_STATUS(aipp_params_->var_reci_chn_2_size() <= 1, PARAM_INVALID,
  380. "The parameter var_reci_chn_2 can not be configed repeatedly");
  381. GE_CHK_BOOL_RET_STATUS(aipp_params_->var_reci_chn_3_size() <= 1, PARAM_INVALID,
  382. "The parameter var_reci_chn_3 can not be configed repeatedly");
  383. GE_CHK_BOOL_RET_STATUS(aipp_params_->matrix_r0c0_size() <= 1, PARAM_INVALID,
  384. "The parameter matrix_r0c0 can not be configed repeatedly");
  385. GE_CHK_BOOL_RET_STATUS(aipp_params_->matrix_r0c1_size() <= 1, PARAM_INVALID,
  386. "The parameter matrix_r0c1 can not be configed repeatedly");
  387. GE_CHK_BOOL_RET_STATUS(aipp_params_->matrix_r0c2_size() <= 1, PARAM_INVALID,
  388. "The parameter matrix_r0c2 can not be configed repeatedly");
  389. GE_CHK_BOOL_RET_STATUS(aipp_params_->matrix_r1c0_size() <= 1, PARAM_INVALID,
  390. "The parameter matrix_r1c0 can not be configed repeatedly");
  391. GE_CHK_BOOL_RET_STATUS(aipp_params_->matrix_r1c1_size() <= 1, PARAM_INVALID,
  392. "The parameter matrix_r1c1 can not be configed repeatedly");
  393. GE_CHK_BOOL_RET_STATUS(aipp_params_->matrix_r1c2_size() <= 1, PARAM_INVALID,
  394. "The parameter matrix_r1c2 can not be configed repeatedly");
  395. GE_CHK_BOOL_RET_STATUS(aipp_params_->matrix_r2c0_size() <= 1, PARAM_INVALID,
  396. "The parameter matrix_r2c0 can not be configed repeatedly");
  397. GE_CHK_BOOL_RET_STATUS(aipp_params_->matrix_r2c1_size() <= 1, PARAM_INVALID,
  398. "The parameter matrix_r2c1 can not be configed repeatedly");
  399. GE_CHK_BOOL_RET_STATUS(aipp_params_->matrix_r2c2_size() <= 1, PARAM_INVALID,
  400. "The parameter matrix_r2c2 can not be configed repeatedly");
  401. GE_CHK_BOOL_RET_STATUS(aipp_params_->output_bias_0_size() <= 1, PARAM_INVALID,
  402. "The parameter output_bias_0 can not be configed repeatedly");
  403. GE_CHK_BOOL_RET_STATUS(aipp_params_->output_bias_1_size() <= 1, PARAM_INVALID,
  404. "The parameter output_bias_1 can not be configed repeatedly");
  405. GE_CHK_BOOL_RET_STATUS(aipp_params_->output_bias_2_size() <= 1, PARAM_INVALID,
  406. "The parameter output_bias_2 can not be configed repeatedly");
  407. GE_CHK_BOOL_RET_STATUS(aipp_params_->input_bias_0_size() <= 1, PARAM_INVALID,
  408. "The parameter input_bias_0 can not be configed repeatedly");
  409. GE_CHK_BOOL_RET_STATUS(aipp_params_->input_bias_1_size() <= 1, PARAM_INVALID,
  410. "The parameter input_bias_1 can not be configed repeatedly");
  411. GE_CHK_BOOL_RET_STATUS(aipp_params_->input_bias_2_size() <= 1, PARAM_INVALID,
  412. "The parameter input_bias_2 can not be configed repeatedly");
  413. GE_CHK_BOOL_RET_STATUS(aipp_params_->input_edge_idx_size() <= 1, PARAM_INVALID,
  414. "The parameter input_edge_idx can not be configed repeatedly");
  415. const domi::AippOpParams::AippMode aipp_mode = aipp_params_->aipp_mode();
  416. if (aipp_mode == domi::AippOpParams::dynamic) {
  417. GE_CHK_BOOL_RET_STATUS(aipp_params_->max_src_image_size() > 0, PARAM_INVALID,
  418. "for dynamic AIPP params, max_src_image_size must greater than 0");
  419. } else {
  420. GE_CHK_BOOL_RET_STATUS(aipp_params_->input_format() != domi::AippOpParams::UNDEFINED, PARAM_INVALID,
  421. "Input format of AIPP conf is undefined");
  422. GE_CHK_BOOL_RET_STATUS(aipp_params_->src_image_size_w() >= 0, PARAM_INVALID,
  423. "src_image_size_w must not be configed smaller than 0");
  424. GE_CHK_BOOL_RET_STATUS(aipp_params_->src_image_size_h() >= 0, PARAM_INVALID,
  425. "src_image_size_h must not be configed smaller than 0");
  426. GE_CHK_BOOL_RET_STATUS(aipp_params_->load_start_pos_w() >= 0, PARAM_INVALID,
  427. "load_start_pos_w must not be configed smaller than 0");
  428. GE_CHK_BOOL_RET_STATUS(aipp_params_->load_start_pos_h() >= 0, PARAM_INVALID,
  429. "load_start_pos_h must not be configed smaller than 0");
  430. GE_CHK_BOOL_RET_STATUS(aipp_params_->crop_size_w() >= 0, PARAM_INVALID,
  431. "crop_size_w must not be configed smaller than 0");
  432. GE_CHK_BOOL_RET_STATUS(aipp_params_->resize_output_w() >= 0, PARAM_INVALID,
  433. "resize_output_w must not be configed smaller than 0");
  434. GE_CHK_BOOL_RET_STATUS(aipp_params_->resize_output_h() >= 0, PARAM_INVALID,
  435. "resize_output_h must not be configed smaller than 0");
  436. GE_CHK_BOOL_RET_STATUS(aipp_params_->left_padding_size() >= 0, PARAM_INVALID,
  437. "left_padding_size must not be configed smaller than 0");
  438. GE_CHK_BOOL_RET_STATUS(aipp_params_->right_padding_size() >= 0, PARAM_INVALID,
  439. "right_padding_size must not be configed smaller than 0");
  440. GE_CHK_BOOL_RET_STATUS(aipp_params_->top_padding_size() >= 0, PARAM_INVALID,
  441. "top_padding_size must not be configed smaller than 0");
  442. GE_CHK_BOOL_RET_STATUS(aipp_params_->bottom_padding_size() >= 0, PARAM_INVALID,
  443. "bottom_padding_size must not be configed smaller than 0");
  444. }
  445. return SUCCESS;
  446. }
  447. void AippOp::SetCscDefaultValue() {
  448. GE_CHECK_NOTNULL_JUST_RETURN(aipp_params_);
  449. if (aipp_params_->input_format() == domi::AippOpParams::YUV420SP_U8) {
  450. CHECK_FALSE_EXEC(aipp_params_->matrix_r0c0_size() > 0, aipp_params_->add_matrix_r0c0(DEFAULT_MATRIX_R2C0_YUV2RGB));
  451. CHECK_FALSE_EXEC(aipp_params_->matrix_r0c1_size() > 0, aipp_params_->add_matrix_r0c1(DEFAULT_MATRIX_R2C1_YUV2RGB));
  452. CHECK_FALSE_EXEC(aipp_params_->matrix_r0c2_size() > 0, aipp_params_->add_matrix_r0c2(DEFAULT_MATRIX_R2C2_YUV2RGB));
  453. CHECK_FALSE_EXEC(aipp_params_->matrix_r1c0_size() > 0, aipp_params_->add_matrix_r1c0(DEFAULT_MATRIX_R1C0_YUV2RGB));
  454. CHECK_FALSE_EXEC(aipp_params_->matrix_r1c1_size() > 0, aipp_params_->add_matrix_r1c1(DEFAULT_MATRIX_R1C1_YUV2RGB));
  455. CHECK_FALSE_EXEC(aipp_params_->matrix_r1c2_size() > 0, aipp_params_->add_matrix_r1c2(DEFAULT_MATRIX_R1C2_YUV2RGB));
  456. CHECK_FALSE_EXEC(aipp_params_->matrix_r2c0_size() > 0, aipp_params_->add_matrix_r2c0(DEFAULT_MATRIX_R0C0_YUV2RGB));
  457. CHECK_FALSE_EXEC(aipp_params_->matrix_r2c1_size() > 0, aipp_params_->add_matrix_r2c1(DEFAULT_MATRIX_R0C1_YUV2RGB));
  458. CHECK_FALSE_EXEC(aipp_params_->matrix_r2c2_size() > 0, aipp_params_->add_matrix_r2c2(DEFAULT_MATRIX_R0C2_YUV2RGB));
  459. } else {
  460. CHECK_FALSE_EXEC(aipp_params_->matrix_r0c0_size() > 0, aipp_params_->add_matrix_r0c0(DEFAULT_MATRIX_R0C0_RGB2YUV));
  461. CHECK_FALSE_EXEC(aipp_params_->matrix_r0c1_size() > 0, aipp_params_->add_matrix_r0c1(DEFAULT_MATRIX_R0C1_RGB2YUV));
  462. CHECK_FALSE_EXEC(aipp_params_->matrix_r0c2_size() > 0, aipp_params_->add_matrix_r0c2(DEFAULT_MATRIX_R0C2_RGB2YUV));
  463. CHECK_FALSE_EXEC(aipp_params_->matrix_r1c0_size() > 0, aipp_params_->add_matrix_r1c0(DEFAULT_MATRIX_R1C0_RGB2YUV));
  464. CHECK_FALSE_EXEC(aipp_params_->matrix_r1c1_size() > 0, aipp_params_->add_matrix_r1c1(DEFAULT_MATRIX_R1C1_RGB2YUV));
  465. CHECK_FALSE_EXEC(aipp_params_->matrix_r1c2_size() > 0, aipp_params_->add_matrix_r1c2(DEFAULT_MATRIX_R1C2_RGB2YUV));
  466. CHECK_FALSE_EXEC(aipp_params_->matrix_r2c0_size() > 0, aipp_params_->add_matrix_r2c0(DEFAULT_MATRIX_R2C0_RGB2YUV));
  467. CHECK_FALSE_EXEC(aipp_params_->matrix_r2c1_size() > 0, aipp_params_->add_matrix_r2c1(DEFAULT_MATRIX_R2C1_RGB2YUV));
  468. CHECK_FALSE_EXEC(aipp_params_->matrix_r2c2_size() > 0, aipp_params_->add_matrix_r2c2(DEFAULT_MATRIX_R2C2_RGB2YUV));
  469. }
  470. CHECK_FALSE_EXEC(aipp_params_->input_bias_0_size() > 0, aipp_params_->add_input_bias_0(DEFAULT_INPUT_BIAS_0));
  471. CHECK_FALSE_EXEC(aipp_params_->input_bias_1_size() > 0, aipp_params_->add_input_bias_1(DEFAULT_INPUT_BIAS_1));
  472. CHECK_FALSE_EXEC(aipp_params_->input_bias_2_size() > 0, aipp_params_->add_input_bias_2(DEFAULT_INPUT_BIAS_2));
  473. CHECK_FALSE_EXEC(aipp_params_->output_bias_0_size() > 0, aipp_params_->add_output_bias_0(DEFAULT_OUTPUT_BIAS_0));
  474. CHECK_FALSE_EXEC(aipp_params_->output_bias_1_size() > 0, aipp_params_->add_output_bias_1(DEFAULT_OUTPUT_BIAS_1));
  475. CHECK_FALSE_EXEC(aipp_params_->output_bias_2_size() > 0, aipp_params_->add_output_bias_2(DEFAULT_OUTPUT_BIAS_2));
  476. }
  477. void AippOp::SetDtcDefaultValue() {
  478. GE_CHECK_NOTNULL_JUST_RETURN(aipp_params_);
  479. CHECK_FALSE_EXEC(aipp_params_->var_reci_chn_0_size() > 0, aipp_params_->add_var_reci_chn_0(DEFAULT_VAR_RECI_CHN));
  480. GELOGD("var_reci_chn_0 is %f, size is %u.", DEFAULT_VAR_RECI_CHN, aipp_params_->var_reci_chn_0_size());
  481. CHECK_FALSE_EXEC(aipp_params_->var_reci_chn_1_size() > 0, aipp_params_->add_var_reci_chn_1(DEFAULT_VAR_RECI_CHN));
  482. GELOGD("var_reci_chn_1 is %f, size is %u.", DEFAULT_VAR_RECI_CHN, aipp_params_->var_reci_chn_1_size());
  483. CHECK_FALSE_EXEC(aipp_params_->var_reci_chn_2_size() > 0, aipp_params_->add_var_reci_chn_2(DEFAULT_VAR_RECI_CHN));
  484. GELOGD("var_reci_chn_2 is %f, size is %u.", DEFAULT_VAR_RECI_CHN, aipp_params_->var_reci_chn_2_size());
  485. CHECK_FALSE_EXEC(aipp_params_->var_reci_chn_3_size() > 0, aipp_params_->add_var_reci_chn_3(DEFAULT_VAR_RECI_CHN));
  486. GELOGD("var_reci_chn_3 is %f, size is %u.", DEFAULT_VAR_RECI_CHN, aipp_params_->var_reci_chn_3_size());
  487. }
  488. Status AippOp::GenerateOpDesc(OpDescPtr op_desc) {
  489. GE_CHECK_NOTNULL(op_desc);
  490. static int op_idx = 0;
  491. op_desc->SetName(std::string("aipp_node").append(std::to_string(op_idx++)));
  492. op_desc->SetType(AIPP);
  493. // Add two InputDesc, add the second after the first one is added successfully.
  494. if ((op_desc->AddInputDesc(GeTensorDesc()) != GRAPH_SUCCESS) ||
  495. (op_desc->AddInputDesc(GeTensorDesc()) != GRAPH_SUCCESS)) {
  496. GELOGE(FAILED, "failed to add input desc");
  497. return FAILED;
  498. }
  499. if (op_desc->AddOutputDesc(GeTensorDesc()) != GRAPH_SUCCESS) {
  500. GELOGE(FAILED, "add output desc failed.");
  501. return FAILED;
  502. }
  503. GeAttrValue::NAMED_ATTRS aipp_attrs;
  504. ConvertParamToAttr(aipp_attrs);
  505. GE_IF_BOOL_EXEC(!AttrUtils::SetNamedAttrs(op_desc, ATTR_NAME_AIPP, aipp_attrs),
  506. GELOGE(FAILED, "failed to set ATTR_NAME_AIPP");
  507. return FAILED);
  508. return SUCCESS;
  509. }
  510. void AippOp::ConvertParamToAttr(GeAttrValue::NAMED_ATTRS &aipp_attrs) {
  511. GE_CHECK_NOTNULL_JUST_RETURN(aipp_params_);
  512. SAVE_AIPP_ATTR(aipp_mode, GeAttrValue::INT);
  513. SAVE_AIPP_ATTR(related_input_rank, GeAttrValue::INT);
  514. if (aipp_params_->aipp_mode() == domi::AippOpParams::static_) {
  515. SAVE_AIPP_ATTR(input_format, GeAttrValue::INT);
  516. SAVE_AIPP_ATTR(csc_switch, GeAttrValue::BOOL);
  517. SAVE_AIPP_ATTR(crop, GeAttrValue::BOOL);
  518. SAVE_AIPP_ATTR(resize, GeAttrValue::BOOL);
  519. SAVE_AIPP_ATTR(load_start_pos_w, GeAttrValue::INT);
  520. SAVE_AIPP_ATTR(load_start_pos_h, GeAttrValue::INT);
  521. SAVE_AIPP_ATTR(crop_size_w, GeAttrValue::INT);
  522. SAVE_AIPP_ATTR(crop_size_h, GeAttrValue::INT);
  523. SAVE_AIPP_ATTR(resize, GeAttrValue::BOOL);
  524. SAVE_AIPP_ATTR(resize_output_w, GeAttrValue::INT);
  525. SAVE_AIPP_ATTR(resize_output_h, GeAttrValue::INT);
  526. SAVE_AIPP_ATTR(padding, GeAttrValue::BOOL);
  527. SAVE_AIPP_ATTR(left_padding_size, GeAttrValue::INT);
  528. SAVE_AIPP_ATTR(right_padding_size, GeAttrValue::INT);
  529. SAVE_AIPP_ATTR(top_padding_size, GeAttrValue::INT);
  530. SAVE_AIPP_ATTR(bottom_padding_size, GeAttrValue::INT);
  531. SAVE_AIPP_ATTR(src_image_size_w, GeAttrValue::INT);
  532. SAVE_AIPP_ATTR(src_image_size_h, GeAttrValue::INT);
  533. SAVE_AIPP_ATTR(cpadding_value, GeAttrValue::FLOAT);
  534. SAVE_AIPP_ATTR(rbuv_swap_switch, GeAttrValue::BOOL);
  535. SAVE_AIPP_ATTR(ax_swap_switch, GeAttrValue::BOOL);
  536. SAVE_AIPP_ATTR(single_line_mode, GeAttrValue::BOOL);
  537. SAVE_AIPP_ATTR(mean_chn_0, GeAttrValue::INT);
  538. SAVE_AIPP_ATTR(mean_chn_1, GeAttrValue::INT);
  539. SAVE_AIPP_ATTR(mean_chn_2, GeAttrValue::INT);
  540. SAVE_AIPP_ATTR(mean_chn_3, GeAttrValue::INT);
  541. SAVE_AIPP_ATTR(min_chn_0, GeAttrValue::FLOAT);
  542. SAVE_AIPP_ATTR(min_chn_1, GeAttrValue::FLOAT);
  543. SAVE_AIPP_ATTR(min_chn_2, GeAttrValue::FLOAT);
  544. SAVE_AIPP_ATTR(min_chn_3, GeAttrValue::FLOAT);
  545. SAVE_AIPP_ATTR_LIST(var_reci_chn_0, GeAttrValue::FLOAT);
  546. SAVE_AIPP_ATTR_LIST(var_reci_chn_1, GeAttrValue::FLOAT);
  547. SAVE_AIPP_ATTR_LIST(var_reci_chn_2, GeAttrValue::FLOAT);
  548. SAVE_AIPP_ATTR_LIST(var_reci_chn_3, GeAttrValue::FLOAT);
  549. SAVE_AIPP_ATTR_LIST(matrix_r0c0, GeAttrValue::INT);
  550. SAVE_AIPP_ATTR_LIST(matrix_r0c1, GeAttrValue::INT);
  551. SAVE_AIPP_ATTR_LIST(matrix_r0c2, GeAttrValue::INT);
  552. SAVE_AIPP_ATTR_LIST(matrix_r1c0, GeAttrValue::INT);
  553. SAVE_AIPP_ATTR_LIST(matrix_r1c1, GeAttrValue::INT);
  554. SAVE_AIPP_ATTR_LIST(matrix_r1c2, GeAttrValue::INT);
  555. SAVE_AIPP_ATTR_LIST(matrix_r2c0, GeAttrValue::INT);
  556. SAVE_AIPP_ATTR_LIST(matrix_r2c1, GeAttrValue::INT);
  557. SAVE_AIPP_ATTR_LIST(matrix_r2c2, GeAttrValue::INT);
  558. SAVE_AIPP_ATTR_LIST(output_bias_0, GeAttrValue::INT);
  559. SAVE_AIPP_ATTR_LIST(output_bias_1, GeAttrValue::INT);
  560. SAVE_AIPP_ATTR_LIST(output_bias_2, GeAttrValue::INT);
  561. SAVE_AIPP_ATTR_LIST(input_bias_0, GeAttrValue::INT);
  562. SAVE_AIPP_ATTR_LIST(input_bias_1, GeAttrValue::INT);
  563. SAVE_AIPP_ATTR_LIST(input_bias_2, GeAttrValue::INT);
  564. } else {
  565. SAVE_AIPP_ATTR(max_src_image_size, GeAttrValue::INT);
  566. SAVE_AIPP_ATTR(support_rotation, GeAttrValue::BOOL);
  567. }
  568. }
  569. Status AippOp::CreateAippData(const ComputeGraphPtr &graph, const NodePtr &aipp_node) {
  570. GELOGD("Enter add aipp data node process.");
  571. // get previous node, it should be DATA
  572. auto data_node = aipp_node->GetInDataNodes().at(kAippImageInputIndex);
  573. GE_CHECK_NOTNULL(data_node->GetOpDesc());
  574. auto ori_data_format = GetAndCheckFormat();
  575. if (ori_data_format != FORMAT_NCHW && ori_data_format != FORMAT_NHWC) {
  576. GELOGE(PARAM_INVALID, "when dynamic aipp, input_format must be NCHW or NHWC, but [%s] format is %s",
  577. data_node->GetName().c_str(), TypeUtils::FormatToSerialString(ori_data_format).c_str());
  578. return PARAM_INVALID;
  579. }
  580. int64_t batch_count = -1;
  581. auto ret = GetDataDimN(data_node, ori_data_format, batch_count);
  582. if (ret != ge::SUCCESS) {
  583. GELOGE(PARAM_INVALID, "Get data_node dims and transfer to nchw_dims failed!");
  584. return PARAM_INVALID;
  585. }
  586. if (batch_count <= 0) {
  587. GELOGE(PARAM_INVALID, "Batch count %ld is invalid", batch_count);
  588. return PARAM_INVALID;
  589. }
  590. int64_t max_dynamic_aipp_size = CalcMaxSize(batch_count);
  591. if (max_dynamic_aipp_size < 0) {
  592. GELOGE(PARAM_INVALID, "The dynamic aipp size is not positive.");
  593. return PARAM_INVALID;
  594. }
  595. GELOGI("Add aipp input data, batch count is %ld, max_dynamic_aipp_size is %ld", batch_count, max_dynamic_aipp_size);
  596. std::vector<int64_t> input_shape_dim(1, max_dynamic_aipp_size);
  597. GeShape input_shape(input_shape_dim);
  598. // construct input tensor
  599. GeTensorDesc input_tensor(input_shape, FORMAT_ND, DT_UINT8);
  600. TensorUtils::SetReuseInput(input_tensor, false);
  601. TensorUtils::SetSize(input_tensor, max_dynamic_aipp_size);
  602. string node_name = kDynamicAippData;
  603. // Only flush subgraph name
  604. if (graph->GetParentGraph() != nullptr) {
  605. node_name = graph->GetName() + "_" + node_name;
  606. }
  607. // new add aipp_data ops for dynamic aipp param input
  608. OpDescPtr op_desc_ptr_data = MakeShared<OpDesc>(node_name, AIPPDATA);
  609. GE_CHECK_NOTNULL(op_desc_ptr_data);
  610. auto stat1 = op_desc_ptr_data->AddInputDesc(input_tensor);
  611. GeShape output_shape(input_shape_dim);
  612. // construct output tensor
  613. GeTensorDesc output_tensor(output_shape, FORMAT_ND, DT_UINT8);
  614. TensorUtils::SetReuseInput(output_tensor, false);
  615. TensorUtils::SetSize(output_tensor, max_dynamic_aipp_size);
  616. auto stat2 = op_desc_ptr_data->AddOutputDesc(output_tensor);
  617. NodePtr aipp_data_node_ptr = graph->AddNode(op_desc_ptr_data);
  618. GE_CHECK_NOTNULL(aipp_data_node_ptr);
  619. // add node desc for aipp node
  620. auto stat3 = aipp_node->GetOpDesc()->UpdateInputDesc(kAippParamsInputIndex, output_tensor);
  621. if (stat1 != GRAPH_SUCCESS || stat2 != GRAPH_SUCCESS || stat3 != GRAPH_SUCCESS) {
  622. GELOGE(INTERNAL_ERROR, "node process desc failed!");
  623. return INTERNAL_ERROR;
  624. }
  625. // aipp_node should have two input data but now tbe only one input
  626. if (GraphUtils::AddEdge(aipp_data_node_ptr->GetOutDataAnchor(kAippDataOutputIndex),
  627. aipp_node->GetInDataAnchor(kAippParamsInputIndex)) != GRAPH_SUCCESS) {
  628. GELOGE(INTERNAL_ERROR, "Add Anchor anchor between aipp data node and aipp failed!");
  629. return INTERNAL_ERROR;
  630. }
  631. return SUCCESS;
  632. }
  633. } // namespace ge

图引擎模块(GE)是MindSpore的一个子模块,其代码由C++实现,位于前端模块ME和底层硬件之间,起到承接作用。图引擎模块以ME下发的图作为输入,然后进行一系列的深度图优化操作,最后输出一张可以在底层硬件上高效运行的图。GE针对昇腾AI处理器的硬件结构特点,做了特定的优化工作,以此来充分发挥出昇腾AI处理器的强大算力。在进行模型训练/推理时,GE会被自动调用而用户并不感知。GE主要由GE API和GE Core两部分组成,详细的架构图如下所示