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.

execute.cc 12 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /**
  2. * Copyright 2020-2021 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 "minddata/dataset/include/execute.h"
  17. #include "minddata/dataset/core/de_tensor.h"
  18. #include "minddata/dataset/core/device_tensor.h"
  19. #include "minddata/dataset/core/tensor_row.h"
  20. #include "minddata/dataset/include/tensor.h"
  21. #include "minddata/dataset/include/type_id.h"
  22. #include "minddata/dataset/kernels/tensor_op.h"
  23. #ifndef ENABLE_ANDROID
  24. #include "utils/log_adapter.h"
  25. #else
  26. #include "mindspore/lite/src/common/log_adapter.h"
  27. #endif
  28. #ifdef ENABLE_ACL
  29. #include "acl/acl.h"
  30. #include "minddata/dataset/kernels/image/dvpp/utils/ResourceManager.h"
  31. #include "minddata/dataset/kernels/image/dvpp/utils/ErrorCode.h"
  32. #include "minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.h"
  33. #include "minddata/dataset/kernels/image/dvpp/utils/CommonDataType.h"
  34. #include "minddata/dataset/kernels/image/dvpp/utils/DvppCommon.h"
  35. #endif
  36. namespace mindspore {
  37. namespace dataset {
  38. #ifdef ENABLE_ACL
  39. class AscendResource {
  40. public:
  41. AscendResource();
  42. ~AscendResource() = default;
  43. Status InitChipResource();
  44. Status FinalizeChipResource();
  45. Status Sink(const mindspore::MSTensor &host_input, std::shared_ptr<DeviceTensor> *device_input);
  46. Status Pop(std::shared_ptr<DeviceTensor> device_output, std::shared_ptr<Tensor> *host_output);
  47. Status DeviceDataRelease();
  48. std::shared_ptr<MDAclProcess> processor_;
  49. std::shared_ptr<ResourceManager> ascend_resource_;
  50. };
  51. AscendResource::AscendResource() { InitChipResource(); }
  52. Status AscendResource::InitChipResource() {
  53. ResourceInfo resource;
  54. resource.aclConfigPath = "";
  55. resource.deviceIds.insert(mindspore::GlobalContext::GetGlobalDeviceID());
  56. ascend_resource_ = ResourceManager::GetInstance();
  57. APP_ERROR ret = ascend_resource_->InitResource(resource);
  58. if (ret != APP_ERR_OK) {
  59. ascend_resource_->Release();
  60. std::string err_msg = "Error in Init D-chip:" + std::to_string(ret);
  61. MS_LOG(ERROR) << err_msg;
  62. RETURN_STATUS_UNEXPECTED(err_msg);
  63. }
  64. int device_id = *(resource.deviceIds.begin());
  65. aclrtContext context = ascend_resource_->GetContext(device_id);
  66. processor_ = std::make_shared<MDAclProcess>(context, false);
  67. ret = processor_->InitResource();
  68. if (ret != APP_ERR_OK) {
  69. ascend_resource_->Release();
  70. std::string err_msg = "Error in Init resource:" + std::to_string(ret);
  71. MS_LOG(ERROR) << err_msg;
  72. RETURN_STATUS_UNEXPECTED(err_msg);
  73. }
  74. MS_LOG(INFO) << "Ascend resource all initialized!";
  75. return Status::OK();
  76. }
  77. Status AscendResource::FinalizeChipResource() {
  78. processor_->Release();
  79. return Status::OK();
  80. }
  81. Status AscendResource::Sink(const mindspore::MSTensor &host_input, std::shared_ptr<DeviceTensor> *device_input) {
  82. std::shared_ptr<mindspore::dataset::Tensor> de_input;
  83. Status rc = dataset::Tensor::CreateFromMemory(dataset::TensorShape(host_input.Shape()),
  84. MSTypeToDEType(static_cast<TypeId>(host_input.DataType())),
  85. (const uchar *)(host_input.Data().get()), &de_input);
  86. RETURN_IF_NOT_OK(rc);
  87. APP_ERROR ret = processor_->H2D_Sink(de_input, *device_input);
  88. if (ret != APP_ERR_OK) {
  89. ascend_resource_->Release();
  90. std::string err_msg = "Error in data sink process:" + std::to_string(ret);
  91. MS_LOG(ERROR) << err_msg;
  92. RETURN_STATUS_UNEXPECTED(err_msg);
  93. }
  94. MS_LOG(INFO) << "Process data sink successfully";
  95. return Status::OK();
  96. }
  97. Status AscendResource::Pop(std::shared_ptr<DeviceTensor> device_output, std::shared_ptr<Tensor> *host_output) {
  98. APP_ERROR ret = processor_->D2H_Pop(device_output, *host_output);
  99. if (ret != APP_ERR_OK) {
  100. ascend_resource_->Release();
  101. std::string err_msg = "Error in data pop processing:" + std::to_string(ret);
  102. MS_LOG(ERROR) << err_msg;
  103. RETURN_STATUS_UNEXPECTED(err_msg);
  104. }
  105. return Status::OK();
  106. }
  107. Status AscendResource::DeviceDataRelease() {
  108. APP_ERROR ret = processor_->device_memory_release();
  109. if (ret != APP_ERR_OK) {
  110. ascend_resource_->Release();
  111. std::string err_msg = "Error in device data release:" + std::to_string(ret);
  112. MS_LOG(ERROR) << err_msg;
  113. RETURN_STATUS_UNEXPECTED(err_msg);
  114. }
  115. return Status::OK();
  116. }
  117. #endif
  118. Execute::Execute(std::shared_ptr<TensorOperation> op, std::string deviceType) {
  119. ops_.emplace_back(std::move(op));
  120. device_type_ = deviceType;
  121. MS_LOG(INFO) << "Running Device: " << device_type_;
  122. #ifdef ENABLE_ACL
  123. if (device_type_ == "Ascend310") {
  124. D_resource_ = std::make_shared<AscendResource>();
  125. }
  126. #endif
  127. }
  128. Execute::Execute(std::vector<std::shared_ptr<TensorOperation>> ops, std::string deviceType)
  129. : ops_(std::move(ops)), device_type_(deviceType) {
  130. MS_LOG(INFO) << "Running Device: " << device_type_;
  131. #ifdef ENABLE_ACL
  132. if (device_type_ == "Ascend310") {
  133. D_resource_ = std::make_shared<AscendResource>();
  134. }
  135. #endif
  136. }
  137. Execute::~Execute() {
  138. #ifdef ENABLE_ACL
  139. if (device_type_ == "Ascend310") {
  140. D_resource_->FinalizeChipResource();
  141. }
  142. #endif
  143. }
  144. Status Execute::operator()(const mindspore::MSTensor &input, mindspore::MSTensor *output) {
  145. // Validate input tensor
  146. CHECK_FAIL_RETURN_UNEXPECTED(input.DataSize() > 0, "Input Tensor has no data");
  147. CHECK_FAIL_RETURN_UNEXPECTED(!ops_.empty(), "Input TensorOperation should be provided");
  148. CHECK_FAIL_RETURN_UNEXPECTED(validate_device_(), "Device Type should be 'Ascend310' or 'CPU'");
  149. // Validate and build runtime ops
  150. std::vector<std::shared_ptr<TensorOp>> transforms; // record the transformations
  151. for (int32_t i = 0; i < ops_.size(); i++) {
  152. CHECK_FAIL_RETURN_UNEXPECTED(ops_[i] != nullptr, "Input TensorOperation[" + std::to_string(i) + "] is null");
  153. RETURN_IF_NOT_OK(ops_[i]->ValidateParams());
  154. transforms.emplace_back(ops_[i]->Build());
  155. }
  156. if (device_type_ == "CPU") {
  157. // Convert mindspore::Tensor to dataset::Tensor
  158. std::shared_ptr<dataset::Tensor> de_tensor;
  159. Status rc = dataset::Tensor::CreateFromMemory(dataset::TensorShape(input.Shape()),
  160. MSTypeToDEType(static_cast<TypeId>(input.DataType())),
  161. (const uchar *)(input.Data().get()), input.DataSize(), &de_tensor);
  162. if (rc.IsError()) {
  163. MS_LOG(ERROR) << rc;
  164. return rc;
  165. }
  166. // Apply transforms on tensor
  167. for (auto &t : transforms) {
  168. std::shared_ptr<dataset::Tensor> de_output;
  169. Status rc_ = t->Compute(de_tensor, &de_output);
  170. if (rc_.IsError()) {
  171. MS_LOG(ERROR) << rc_;
  172. return rc_;
  173. }
  174. // For next transform
  175. de_tensor = std::move(de_output);
  176. }
  177. // Convert dataset::Tensor to mindspore::Tensor
  178. CHECK_FAIL_RETURN_UNEXPECTED(de_tensor->HasData(), "Apply transform failed, output tensor has no data");
  179. *output = mindspore::MSTensor(std::make_shared<DETensor>(de_tensor));
  180. } else { // Ascend310 case, where we must set Ascend resource on each operators
  181. #ifdef ENABLE_ACL
  182. std::shared_ptr<mindspore::dataset::DeviceTensor> device_input;
  183. RETURN_IF_NOT_OK(D_resource_->Sink(input, &device_input));
  184. for (auto &t : transforms) {
  185. std::shared_ptr<DeviceTensor> device_output;
  186. RETURN_IF_NOT_OK(t->SetAscendResource(D_resource_->processor_));
  187. RETURN_IF_NOT_OK(t->Compute(device_input, &device_output));
  188. // For next transform
  189. device_input = std::move(device_output);
  190. }
  191. CHECK_FAIL_RETURN_UNEXPECTED(device_input->HasDeviceData(), "Apply transform failed, output tensor has no data");
  192. *output = mindspore::MSTensor(std::make_shared<DETensor>(device_input, true));
  193. #endif
  194. }
  195. return Status::OK();
  196. }
  197. Status Execute::operator()(const std::vector<MSTensor> &input_tensor_list, std::vector<MSTensor> *output_tensor_list) {
  198. // Validate input tensor
  199. CHECK_FAIL_RETURN_UNEXPECTED(!input_tensor_list.empty(), "Input Tensor is not valid");
  200. for (auto &tensor : input_tensor_list) {
  201. CHECK_FAIL_RETURN_UNEXPECTED(tensor.DataSize() > 0, "Input Tensor has no data");
  202. }
  203. CHECK_FAIL_RETURN_UNEXPECTED(!ops_.empty(), "Input TensorOperation should be provided");
  204. CHECK_FAIL_RETURN_UNEXPECTED(validate_device_(), "Device Type should be 'Ascend310' or 'CPU'");
  205. // Validate and build runtime ops
  206. std::vector<std::shared_ptr<TensorOp>> transforms;
  207. for (int32_t i = 0; i < ops_.size(); i++) {
  208. CHECK_FAIL_RETURN_UNEXPECTED(ops_[i] != nullptr, "Input TensorOperation[" + std::to_string(i) + "] is null");
  209. RETURN_IF_NOT_OK(ops_[i]->ValidateParams());
  210. transforms.emplace_back(ops_[i]->Build());
  211. }
  212. if (device_type_ == "CPU") { // Case CPU
  213. TensorRow de_tensor_list;
  214. for (auto &tensor : input_tensor_list) {
  215. std::shared_ptr<dataset::Tensor> de_tensor;
  216. Status rc = dataset::Tensor::CreateFromMemory(
  217. dataset::TensorShape(tensor.Shape()), MSTypeToDEType(static_cast<TypeId>(tensor.DataType())),
  218. (const uchar *)(tensor.Data().get()), tensor.DataSize(), &de_tensor);
  219. if (rc.IsError()) {
  220. MS_LOG(ERROR) << rc;
  221. RETURN_IF_NOT_OK(rc);
  222. }
  223. de_tensor_list.emplace_back(std::move(de_tensor));
  224. }
  225. // Apply transforms on tensor
  226. for (auto &t : transforms) {
  227. TensorRow de_output_list;
  228. RETURN_IF_NOT_OK(t->Compute(de_tensor_list, &de_output_list));
  229. // For next transform
  230. de_tensor_list = std::move(de_output_list);
  231. }
  232. for (auto &tensor : de_tensor_list) {
  233. CHECK_FAIL_RETURN_UNEXPECTED(tensor->HasData(), "Apply transform failed, output tensor has no data");
  234. auto ms_tensor = mindspore::MSTensor(std::make_shared<DETensor>(tensor));
  235. output_tensor_list->emplace_back(ms_tensor);
  236. }
  237. CHECK_FAIL_RETURN_UNEXPECTED(!output_tensor_list->empty(), "Output Tensor is not valid");
  238. } else { // Case Ascend310
  239. #ifdef ENABLE_ACL
  240. for (auto &input_tensor : input_tensor_list) {
  241. std::shared_ptr<dataset::DeviceTensor> device_input;
  242. RETURN_IF_NOT_OK(D_resource_->Sink(input_tensor, &device_input));
  243. for (auto &t : transforms) {
  244. std::shared_ptr<DeviceTensor> device_output;
  245. RETURN_IF_NOT_OK(t->SetAscendResource(D_resource_->processor_));
  246. RETURN_IF_NOT_OK(t->Compute(device_input, &device_output));
  247. // For next transform
  248. device_input = std::move(device_output);
  249. }
  250. CHECK_FAIL_RETURN_UNEXPECTED(device_input->HasDeviceData(), "Apply transform failed, output tensor has no data");
  251. // Due to the limitation of Ascend310 memory, we have to pop every data onto host memory
  252. // So the speed of this method is slower than solo mode
  253. std::shared_ptr<mindspore::dataset::Tensor> host_output;
  254. RETURN_IF_NOT_OK(D_resource_->Pop(device_input, &host_output));
  255. auto ms_tensor = mindspore::MSTensor(std::make_shared<DETensor>(host_output));
  256. output_tensor_list->emplace_back(ms_tensor);
  257. RETURN_IF_NOT_OK(D_resource_->DeviceDataRelease());
  258. }
  259. CHECK_FAIL_RETURN_UNEXPECTED(!output_tensor_list->empty(), "Output Tensor vector is empty");
  260. #endif
  261. }
  262. return Status::OK();
  263. }
  264. Status Execute::validate_device_() {
  265. if (device_type_ != "CPU" && device_type_ != "Ascend310") {
  266. std::string err_msg = device_type_ + " is not supported. (Option: CPU or Ascend310)";
  267. MS_LOG(ERROR) << err_msg;
  268. RETURN_STATUS_UNEXPECTED(err_msg);
  269. }
  270. return Status::OK();
  271. }
  272. #ifdef ENABLE_ACL
  273. Status Execute::DeviceMemoryRelease() {
  274. Status rc = D_resource_->DeviceDataRelease();
  275. if (rc.IsError()) {
  276. D_resource_->ascend_resource_->Release();
  277. std::string err_msg = "Error in device data release";
  278. MS_LOG(ERROR) << err_msg;
  279. RETURN_STATUS_UNEXPECTED(err_msg);
  280. }
  281. return Status::OK();
  282. }
  283. #endif
  284. } // namespace dataset
  285. } // namespace mindspore