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.

zero_copy_offset.cc 10 kB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /**
  2. * Copyright 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/load/new_model_manager/zero_copy_offset.h"
  17. #include "framework/common/debug/ge_log.h"
  18. #include "framework/common/util.h"
  19. #include "graph/load/new_model_manager/model_utils.h"
  20. #include "graph/load/new_model_manager/zero_copy_task.h"
  21. namespace ge {
  22. namespace {
  23. const uint32_t kDataIndex = 0;
  24. } // namespace
  25. ZeroCopyOffset::ZeroCopyOffset() {}
  26. ZeroCopyOffset::~ZeroCopyOffset() {}
  27. Status ZeroCopyOffset::InitInputDataInfo(const vector<int64_t> &output_size_list,
  28. const vector<void *> &virtual_addr_list, const OpDescPtr &op_desc,
  29. bool &fusion_flag) {
  30. GELOGI("[ZCPY] Start to InitInputDataInfo of %s, total_data_size is %ld, virtual_addr is %p",
  31. op_desc->GetName().c_str(), output_size_list[kDataIndex], virtual_addr_list[kDataIndex]);
  32. if (output_size_list.empty() || virtual_addr_list.empty() || (output_size_list.size() != virtual_addr_list.size())) {
  33. GELOGE(PARAM_INVALID, "Data[%s] init failed: Output size is %zu, Output addr is %zu", op_desc->GetName().c_str(),
  34. output_size_list.size(), virtual_addr_list.size());
  35. return PARAM_INVALID;
  36. }
  37. basic_addr_ = virtual_addr_list[kDataIndex];
  38. (void)ge::AttrUtils::GetListInt(op_desc, ATTR_ZERO_COPY_BASIC_OFFSET, zero_copy_basic_offset_);
  39. (void)ge::AttrUtils::GetListInt(op_desc, ATTR_ZERO_COPY_RELATIVE_OFFSET, zero_copy_relative_offset_);
  40. GE_CHK_BOOL_EXEC(zero_copy_basic_offset_.size() == zero_copy_relative_offset_.size(), return PARAM_INVALID,
  41. "basic_offset_size should be equal to relative_offset_size");
  42. GELOGI("[ZCPY] zero_copy_basic_offset size is %zu", zero_copy_basic_offset_.size());
  43. int64_t virtual_addr_offset = op_desc->GetOutputOffset().at(kDataIndex);
  44. GELOGI("virtual_addr_offset is %ld.", virtual_addr_offset);
  45. IsL2Fusion(zero_copy_basic_offset_, virtual_addr_offset, fusion_flag);
  46. uint32_t out_count = 0;
  47. data_size_ = output_size_list[kDataIndex];
  48. if (!fusion_flag) {
  49. GELOGI("[ZCPY] %s not set l2_fusion.", op_desc->GetName().c_str());
  50. out_count++;
  51. data_info_.emplace_back(output_size_list[kDataIndex], virtual_addr_list[kDataIndex]);
  52. relative_offset_.emplace_back(0);
  53. GELOGI("[ZCPY] %s size is %ld, virtual_addr is %p.", op_desc->GetName().c_str(), output_size_list[kDataIndex],
  54. virtual_addr_list[kDataIndex]);
  55. } else {
  56. GELOGI("[ZCPY] set l2_fusion for %s.", op_desc->GetName().c_str());
  57. for (size_t index = 0; index < zero_copy_basic_offset_.size(); ++index) {
  58. if (zero_copy_basic_offset_.at(index) == virtual_addr_offset) {
  59. out_count++;
  60. uint64_t out_offset =
  61. reinterpret_cast<uint64_t>(virtual_addr_list[kDataIndex]) + zero_copy_relative_offset_.at(index);
  62. int64_t real_data_size = ModelUtils::GetOutputSize(op_desc).at(kDataIndex);
  63. data_info_.emplace_back(real_data_size, reinterpret_cast<void *>(static_cast<uintptr_t>(out_offset)));
  64. relative_offset_.emplace_back(zero_copy_relative_offset_.at(index));
  65. GELOGI("[ZCPY] virtual_addr: %p has been l2-fusion to %lu, need copy data_size is %ld.", basic_addr_,
  66. out_offset, real_data_size);
  67. }
  68. }
  69. }
  70. data_count_ = out_count;
  71. return SUCCESS;
  72. }
  73. Status ZeroCopyOffset::InitOutputDataInfo(const vector<int64_t> &input_size_list,
  74. const vector<void *> &virtual_addr_list, const OpDescPtr &op_desc,
  75. const size_t &idx, bool &fusion_flag) {
  76. GELOGI("[ZCPY] Start to InitOutputDataInfo of %s.", op_desc->GetName().c_str());
  77. int64_t size = input_size_list[idx];
  78. auto tensor_desc = op_desc->GetInputDescPtr(idx);
  79. GE_CHECK_NOTNULL(tensor_desc);
  80. if (TensorUtils::GetTensorSizeInBytes(*tensor_desc, size) != GRAPH_SUCCESS) {
  81. GELOGE(FAILED, "GetTensorSizeInBytes failed!");
  82. return FAILED;
  83. }
  84. GELOGI("Tensor data size: GetSize=%ld, GetTensorSizeInBytes=%ld", input_size_list[idx], size);
  85. basic_addr_ = virtual_addr_list[idx];
  86. (void)ge::AttrUtils::GetListInt(op_desc, ATTR_ZERO_COPY_BASIC_OFFSET, zero_copy_basic_offset_);
  87. (void)ge::AttrUtils::GetListInt(op_desc, ATTR_ZERO_COPY_RELATIVE_OFFSET, zero_copy_relative_offset_);
  88. GE_CHK_BOOL_EXEC(zero_copy_basic_offset_.size() == zero_copy_relative_offset_.size(), return PARAM_INVALID,
  89. "basic_offset_size should be equal to relative_offset_size");
  90. int64_t virtual_addr_offset = op_desc->GetInputOffset().at(idx);
  91. GELOGI("virtual_addr_offset is %ld.", virtual_addr_offset);
  92. IsL2Fusion(zero_copy_basic_offset_, virtual_addr_offset, fusion_flag);
  93. uint32_t in_count = 0;
  94. data_size_ = size;
  95. if (!fusion_flag) {
  96. GELOGI("[ZCPY] %s not set l2-fusion.", op_desc->GetName().c_str());
  97. in_count++;
  98. data_info_.emplace_back(size, virtual_addr_list[idx]);
  99. // op_desc not set l2fusion when fusion_flag is false
  100. relative_offset_.emplace_back(0);
  101. GELOGI("[ZCPY] %s size is %ld, virtual_addr is %p.", op_desc->GetName().c_str(), size, virtual_addr_list[idx]);
  102. } else {
  103. GELOGI("[ZCPY] set l2-fusion for %s.", op_desc->GetName().c_str());
  104. for (size_t index = 0; index < zero_copy_basic_offset_.size(); ++index) {
  105. if (zero_copy_basic_offset_.at(index) == virtual_addr_offset) {
  106. in_count++;
  107. uint64_t in_offset = reinterpret_cast<uint64_t>(virtual_addr_list[idx]) + zero_copy_relative_offset_.at(index);
  108. int64_t real_data_size = ModelUtils::GetInputSize(op_desc).at(idx);
  109. data_info_.emplace_back(real_data_size, reinterpret_cast<void *>(static_cast<uintptr_t>(in_offset)));
  110. relative_offset_.emplace_back(zero_copy_relative_offset_.at(index));
  111. GELOGI("[ZCPY] virtual_addr: %p has been l2-fusion from %lu, need copy data_size is %ld.", basic_addr_,
  112. in_offset, real_data_size);
  113. }
  114. }
  115. }
  116. data_count_ = in_count;
  117. return SUCCESS;
  118. }
  119. void ZeroCopyOffset::IsL2Fusion(const vector<int64_t> &fusion_basic_addrs, const int64_t &tensor_offset,
  120. bool &fusion_flag) {
  121. for (size_t fusion_count = 0; fusion_count < fusion_basic_addrs.size(); ++fusion_count) {
  122. if (fusion_basic_addrs.at(fusion_count) == tensor_offset) {
  123. fusion_flag = true;
  124. break;
  125. }
  126. }
  127. }
  128. void ZeroCopyOffset::SetInputOutsideAddrs(const vector<int64_t> &output_offset_list, void *addr, const size_t &index,
  129. bool fusion_flag, std::set<const void *> &real_virtual_addrs) {
  130. GELOGI("[ZCPY] Start to SetInputOutsideAddrs for virtual_addr %p.", addr);
  131. uint32_t out_count = 0;
  132. if (!fusion_flag) {
  133. GELOGI("[ZCPY] not set l2-fusion for virtual_adr %p.", addr);
  134. out_count++;
  135. std::map<const void *, std::vector<void *>> addr_mapping;
  136. addr_mapping[addr] = {};
  137. outside_addrs_.emplace_back(addr_mapping);
  138. real_virtual_addrs.insert(addr);
  139. } else {
  140. GELOGI("[ZCPY] set l2-fusion for virtual_addr %p.", addr);
  141. int64_t output_offset = output_offset_list.at(index);
  142. for (size_t i = 0; i < zero_copy_basic_offset_.size(); ++i) {
  143. if (zero_copy_basic_offset_.at(i) == output_offset) {
  144. out_count++;
  145. void *virtual_addr =
  146. reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(addr) + zero_copy_relative_offset_.at(i));
  147. std::map<const void *, std::vector<void *>> addr_mapping;
  148. addr_mapping[virtual_addr] = {};
  149. outside_addrs_.emplace_back(addr_mapping);
  150. real_virtual_addrs.insert(virtual_addr);
  151. GELOGI("[ZCPY] virtual_addr %p has been fusion to virtual_addr %p.", addr, virtual_addr);
  152. }
  153. }
  154. }
  155. addr_count_ = out_count;
  156. }
  157. void ZeroCopyOffset::SetOutputOutsideAddrs(const int64_t &input_offset, const bool &fusion_flag, void *addr,
  158. std::vector<void *> &tensor_addrs) {
  159. GELOGI("[ZCPY] Start to SetOutputOutsideAddrs for virtual_addr %p.", addr);
  160. uint32_t out_count = 0;
  161. if (!fusion_flag) {
  162. GELOGI("[ZCPY] not set l2-fusion for virtual_addr %p.", addr);
  163. out_count++;
  164. std::map<const void *, std::vector<void *>> addr_mapping;
  165. addr_mapping[addr] = {};
  166. outside_addrs_.emplace_back(addr_mapping);
  167. tensor_addrs.emplace_back(addr);
  168. } else {
  169. GELOGI("[ZCPY] set l2-fusion for virtual_addr %p.", addr);
  170. for (size_t i = 0; i < zero_copy_basic_offset_.size(); ++i) {
  171. if (zero_copy_basic_offset_.at(i) == input_offset) {
  172. out_count++;
  173. void *virtual_addr =
  174. reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(addr) + zero_copy_relative_offset_.at(i));
  175. std::map<const void *, std::vector<void *>> addr_mapping;
  176. addr_mapping[virtual_addr] = {};
  177. outside_addrs_.emplace_back(addr_mapping);
  178. tensor_addrs.emplace_back(virtual_addr);
  179. GELOGI("[ZCPY] virtual_addr %p has been fusion to virtual_addr %p.", addr, virtual_addr);
  180. }
  181. }
  182. }
  183. addr_count_ = out_count;
  184. }
  185. bool ZeroCopyOffset::SetOutsideAddrsValue(ZeroCopyTask &zero_copy_task, void *outside_addr, void *args, size_t offset) {
  186. const auto addr_val = reinterpret_cast<uintptr_t>(outside_addr);
  187. bool set_batch_label_flag = false;
  188. for (uint32_t out_count = 0; out_count < GetAddrCount(); ++out_count) {
  189. auto &addrs_mapping_list = GetOutsideAddrs();
  190. auto args_addrs = addrs_mapping_list[out_count].find(outside_addr);
  191. if (args_addrs != addrs_mapping_list[out_count].end()) {
  192. GE_CHK_STATUS(zero_copy_task.SetTaskArgsOffset(addr_val, offset), "Input args invalid.");
  193. void *args_val = static_cast<uint8_t *>(args) + offset;
  194. args_addrs->second.push_back(args_val);
  195. GELOGI("[ZCPY] set copy input: virtual_addr: 0x%lx, task_addr: %p, args: %p, offset: %zu.", addr_val, args_val,
  196. args, offset);
  197. set_batch_label_flag = true;
  198. }
  199. }
  200. return set_batch_label_flag;
  201. }
  202. } // namespace ge

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