From 2e5e1c644d62b2271ab57fb2528a083a03f3691f Mon Sep 17 00:00:00 2001 From: Zhenglong Li Date: Thu, 4 Mar 2021 21:03:20 +0800 Subject: [PATCH] Fix API class parse() issue in execute() during runtime, besides, we add some method for DeviceTensor class in order to adapt next period --- .../ccsrc/minddata/dataset/api/execute.cc | 112 +++++++++++------- .../ccsrc/minddata/dataset/core/de_tensor.cc | 29 ++++- .../minddata/dataset/core/device_tensor.cc | 71 ++++++++--- .../minddata/dataset/core/device_tensor.h | 10 ++ .../ccsrc/minddata/dataset/include/execute.h | 4 + 5 files changed, 159 insertions(+), 67 deletions(-) diff --git a/mindspore/ccsrc/minddata/dataset/api/execute.cc b/mindspore/ccsrc/minddata/dataset/api/execute.cc index bee2e24fa2..c4fb4c8c67 100644 --- a/mindspore/ccsrc/minddata/dataset/api/execute.cc +++ b/mindspore/ccsrc/minddata/dataset/api/execute.cc @@ -41,6 +41,7 @@ namespace dataset { using json = nlohmann::json; struct Execute::ExtraInfo { std::multimap> aipp_cfg_; + bool init_with_shared_ptr_ = true; // Initial execute object with shared_ptr as default }; // FIXME - Temporarily overload Execute to support both TensorOperation and TensorTransform @@ -61,15 +62,10 @@ Execute::Execute(std::shared_ptr op, MapTargetDevice deviceType } Execute::Execute(std::shared_ptr op, MapTargetDevice deviceType) { - // Convert op from TensorTransform to TensorOperation - std::shared_ptr operation; + // Initialize the op and other context + transforms_.emplace_back(op); + info_ = std::make_shared(); - if (deviceType == MapTargetDevice::kCpu) { - operation = op->Parse(); - } else { - operation = op->Parse(deviceType); - } - ops_.emplace_back(std::move(operation)); device_type_ = deviceType; #ifdef ENABLE_ACL if (device_type_ == MapTargetDevice::kAscend310) { @@ -84,9 +80,12 @@ Execute::Execute(std::shared_ptr op, MapTargetDevice deviceType } Execute::Execute(std::reference_wrapper op, MapTargetDevice deviceType) { - // Convert op from TensorTransform to TensorOperation + // Initialize the transforms_ and other context std::shared_ptr operation = op.get().Parse(); ops_.emplace_back(std::move(operation)); + + info_ = std::make_shared(); + info_->init_with_shared_ptr_ = false; device_type_ = deviceType; #ifdef ENABLE_ACL if (device_type_ == MapTargetDevice::kAscend310) { @@ -102,15 +101,11 @@ Execute::Execute(std::reference_wrapper op, MapTargetDevice dev // Execute function for the example case: auto decode(new vision::Decode()); Execute::Execute(TensorTransform *op, MapTargetDevice deviceType) { - // Convert op from TensorTransform to TensorOperation - std::shared_ptr operation; + // Initialize the transforms_ and other context + std::shared_ptr smart_ptr_op(op); + transforms_.emplace_back(smart_ptr_op); + info_ = std::make_shared(); - if (deviceType == MapTargetDevice::kCpu) { - operation = op->Parse(); - } else { - operation = op->Parse(deviceType); - } - ops_.emplace_back(std::move(operation)); device_type_ = deviceType; #ifdef ENABLE_ACL if (device_type_ == MapTargetDevice::kAscend310) { @@ -140,18 +135,10 @@ Execute::Execute(std::vector> ops, MapTargetDev } Execute::Execute(std::vector> ops, MapTargetDevice deviceType) { - // Convert ops from TensorTransform to TensorOperation + // Initialize the transforms_ and other context + transforms_ = ops; + info_ = std::make_shared(); - if (deviceType == MapTargetDevice::kCpu) { - (void)std::transform(ops.begin(), ops.end(), std::back_inserter(ops_), - [](std::shared_ptr operation) -> std::shared_ptr { - return operation->Parse(); - }); - } else { - for (auto &op : ops) { - ops_.emplace_back(op->Parse(deviceType)); - } - } device_type_ = deviceType; #ifdef ENABLE_ACL if (device_type_ == MapTargetDevice::kAscend310) { @@ -166,8 +153,7 @@ Execute::Execute(std::vector> ops, MapTargetDev } Execute::Execute(const std::vector> ops, MapTargetDevice deviceType) { - // Convert ops from TensorTransform to TensorOperation - info_ = std::make_shared(); + // Initialize the transforms_ and other context if (deviceType == MapTargetDevice::kCpu) { (void)std::transform( ops.begin(), ops.end(), std::back_inserter(ops_), @@ -177,6 +163,9 @@ Execute::Execute(const std::vector> ops, ops_.emplace_back(op.get().Parse(deviceType)); } } + + info_ = std::make_shared(); + info_->init_with_shared_ptr_ = false; device_type_ = deviceType; #ifdef ENABLE_ACL if (device_type_ == MapTargetDevice::kAscend310) { @@ -192,17 +181,13 @@ Execute::Execute(const std::vector> ops, // Execute function for the example vector case: auto decode(new vision::Decode()); Execute::Execute(std::vector ops, MapTargetDevice deviceType) { - // Convert ops from TensorTransform to TensorOperation - info_ = std::make_shared(); - if (deviceType == MapTargetDevice::kCpu) { - (void)std::transform( - ops.begin(), ops.end(), std::back_inserter(ops_), - [](TensorTransform *operation) -> std::shared_ptr { return operation->Parse(); }); - } else { - for (auto &op : ops) { - ops_.emplace_back(op->Parse(deviceType)); - } + // Initialize the transforms_ and other context + for (auto &op : ops) { + std::shared_ptr smart_ptr_op(op); + transforms_.emplace_back(smart_ptr_op); } + + info_ = std::make_shared(); device_type_ = deviceType; #ifdef ENABLE_ACL if (device_type_ == MapTargetDevice::kAscend310) { @@ -231,8 +216,14 @@ Execute::~Execute() { Status Execute::operator()(const mindspore::MSTensor &input, mindspore::MSTensor *output) { // Validate input tensor CHECK_FAIL_RETURN_UNEXPECTED(input.DataSize() > 0, "Input Tensor has no data"); - CHECK_FAIL_RETURN_UNEXPECTED(!ops_.empty(), "Input TensorOperation should be provided"); CHECK_FAIL_RETURN_UNEXPECTED(validate_device_(), "Device Type should be 'Ascend310' or 'CPU'"); + + // Parse TensorTransform transforms_ into TensorOperation ops_ + if (info_->init_with_shared_ptr_) { + RETURN_IF_NOT_OK(ParseTransforms_()); + } + CHECK_FAIL_RETURN_UNEXPECTED(!ops_.empty(), "Input TensorOperation should be provided"); + // Validate and build runtime ops std::vector> transforms; // record the transformations @@ -310,9 +301,14 @@ Status Execute::operator()(const std::vector &input_tensor_list, std:: for (auto &tensor : input_tensor_list) { CHECK_FAIL_RETURN_UNEXPECTED(tensor.DataSize() > 0, "Input Tensor has no data"); } - CHECK_FAIL_RETURN_UNEXPECTED(!ops_.empty(), "Input TensorOperation should be provided"); CHECK_FAIL_RETURN_UNEXPECTED(validate_device_(), "Device Type should be 'Ascend310' or 'CPU'"); + // Parse TensorTransform transforms_ into TensorOperation ops_ + if (info_->init_with_shared_ptr_) { + RETURN_IF_NOT_OK(ParseTransforms_()); + } + CHECK_FAIL_RETURN_UNEXPECTED(!ops_.empty(), "Input TensorOperation should be provided"); + std::map env_list = { {MapTargetDevice::kCpu, "kCpu"}, {MapTargetDevice::kGpu, "kGpu"}, {MapTargetDevice::kAscend310, "kAscend310"}}; @@ -491,6 +487,9 @@ Status AippInfoCollection(std::map *aipp_options, cons std::string Execute::AippCfgGenerator() { std::string config_location = "./aipp.cfg"; #ifdef ENABLE_ACL + if (info_->init_with_shared_ptr_) { + ParseTransforms_(); + } std::vector paras; // Record the parameters value of each Ascend operators for (int32_t i = 0; i < ops_.size(); i++) { // Validate operator ir @@ -499,10 +498,7 @@ std::string Execute::AippCfgGenerator() { MS_LOG(ERROR) << "Input TensorOperation[" + std::to_string(i) + "] is null"; return ""; } - if (ops_[i]->ValidateParams() != Status::OK()) { - MS_LOG(ERROR) << "Input TensorOperation[" + std::to_string(i) + "] has wrong parameters"; - return ""; - } + // Define map between operator name and parameter name ops_[i]->to_json(&ir_info); std::multimap op_list = {{vision::kDvppCropJpegOperation, "size"}, @@ -587,6 +583,30 @@ std::string Execute::AippCfgGenerator() { return config_location; } +bool IsEmptyPtr(std::shared_ptr api_ptr) { return api_ptr == nullptr; } + +Status Execute::ParseTransforms_() { + auto iter = std::find_if(transforms_.begin(), transforms_.end(), IsEmptyPtr); + if (iter != transforms_.end()) { + std::string err_msg = "Your input TensorTransforms contain at least one nullptr, please check your input"; + MS_LOG(ERROR) << err_msg; + RETURN_STATUS_UNEXPECTED(err_msg); + } + + if (device_type_ == MapTargetDevice::kCpu) { + (void)std::transform(transforms_.begin(), transforms_.end(), std::back_inserter(ops_), + [](std::shared_ptr operation) -> std::shared_ptr { + return operation->Parse(); + }); + } else { + for (auto &transform_ : transforms_) { + ops_.emplace_back(transform_->Parse(device_type_)); + } + } + + return Status::OK(); +} + Status Execute::validate_device_() { if (device_type_ != MapTargetDevice::kCpu && device_type_ != MapTargetDevice::kAscend310) { std::string err_msg = "Your input device is not supported. (Option: CPU or Ascend310)"; diff --git a/mindspore/ccsrc/minddata/dataset/core/de_tensor.cc b/mindspore/ccsrc/minddata/dataset/core/de_tensor.cc index 68df7109bd..8ac6fd5f77 100644 --- a/mindspore/ccsrc/minddata/dataset/core/de_tensor.cc +++ b/mindspore/ccsrc/minddata/dataset/core/de_tensor.cc @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2020-2021 Huawei Technologies Co., Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -61,6 +61,12 @@ DETensor::DETensor(std::shared_ptr device_tensor_impl, bo const std::string &DETensor::Name() const { return name_; } enum mindspore::DataType DETensor::DataType() const { +#ifndef ENABLE_ANDROID + if (is_device_) { + ASSERT_NULL(device_tensor_impl_); + return static_cast(DETypeToMSType(device_tensor_impl_->DeviceDataType())); + } +#endif ASSERT_NULL(tensor_impl_); return static_cast(DETypeToMSType(tensor_impl_->type())); } @@ -81,19 +87,34 @@ const std::vector &DETensor::Shape() const { return shape_; } std::shared_ptr DETensor::Data() const { #ifndef ENABLE_ANDROID if (is_device_) { - return std::shared_ptr(device_tensor_impl_->GetDeviceBuffer(), [](const void *) {}); + MS_LOG(ERROR) << "Data() always return the data on the host."; + return nullptr; } #endif return std::shared_ptr(tensor_impl_->GetBuffer(), [](const void *) {}); } void *DETensor::MutableData() { +#ifndef ENABLE_ANDROID + if (is_device_) { + ASSERT_NULL(device_tensor_impl_); + return static_cast(device_tensor_impl_->GetDeviceMutableBuffer()); + } +#endif ASSERT_NULL(tensor_impl_); - return tensor_impl_->GetMutableBuffer(); + return static_cast(tensor_impl_->GetMutableBuffer()); } bool DETensor::IsDevice() const { return is_device_; } -std::shared_ptr DETensor::Clone() const { return std::make_shared(tensor_impl_); } +std::shared_ptr DETensor::Clone() const { +#ifndef ENABLE_ANDROID + if (is_device_) { + ASSERT_NULL(device_tensor_impl_); + return std::make_shared(device_tensor_impl_, is_device_); + } +#endif + return std::make_shared(tensor_impl_); +} } // namespace dataset } // namespace mindspore diff --git a/mindspore/ccsrc/minddata/dataset/core/device_tensor.cc b/mindspore/ccsrc/minddata/dataset/core/device_tensor.cc index b8f504247c..fc048eb219 100644 --- a/mindspore/ccsrc/minddata/dataset/core/device_tensor.cc +++ b/mindspore/ccsrc/minddata/dataset/core/device_tensor.cc @@ -20,27 +20,11 @@ namespace mindspore { namespace dataset { -Status DeviceTensor::SetYuvStrideShape_(const uint32_t &width, const uint32_t &widthStride, const uint32_t &height, - const uint32_t &heightStride) { - YUV_shape_ = {width, widthStride, height, heightStride}; - return Status::OK(); -} - -std::vector DeviceTensor::GetYuvStrideShape() { return YUV_shape_; } - -Status DeviceTensor::SetAttributes(uint8_t *data_ptr, const uint32_t &dataSize, const uint32_t &width, - const uint32_t &widthStride, const uint32_t &height, const uint32_t &heightStride) { - device_data_ = data_ptr; - CHECK_FAIL_RETURN_UNEXPECTED(device_data_ != nullptr, "Fail to get the device data."); - SetSize_(dataSize); - SetYuvStrideShape_(width, widthStride, height, heightStride); - return Status::OK(); -} - DeviceTensor::DeviceTensor(const TensorShape &shape, const DataType &type) : Tensor(shape, type) { // grab the mem pool from global context and create the allocator for char data area std::shared_ptr global_pool = GlobalContext::Instance()->mem_pool(); data_allocator_ = std::make_unique>(global_pool); + device_data_type_ = type; } Status DeviceTensor::CreateEmpty(const TensorShape &shape, const DataType &type, std::shared_ptr *out) { @@ -64,10 +48,63 @@ Status DeviceTensor::CreateEmpty(const TensorShape &shape, const DataType &type, return Status::OK(); } +Status DeviceTensor::CreateFromDeviceMemory(const TensorShape &shape, const DataType &type, uint8_t *data_ptr, + const uint32_t &dataSize, const std::vector &attributes, + std::shared_ptr *out) { + CHECK_FAIL_RETURN_UNEXPECTED(shape.known(), "Invalid shape."); + CHECK_FAIL_RETURN_UNEXPECTED(type != DataType::DE_UNKNOWN, "Invalid data type."); + CHECK_FAIL_RETURN_UNEXPECTED(data_ptr != nullptr, "Data pointer is NULL"); + CHECK_FAIL_RETURN_UNEXPECTED(dataSize > 0, "Invalid data size"); + + const DeviceTensorAlloc *alloc = GlobalContext::Instance()->device_tensor_allocator(); + *out = std::allocate_shared(*alloc, shape, type); + + // if it's a string tensor and it has no elements, Just initialize the shape and type. + if (!type.IsNumeric() && shape.NumOfElements() == 0) { + return Status::OK(); + } + + CHECK_FAIL_RETURN_UNEXPECTED(type.IsNumeric(), "Number of elements is not 0. The type should be numeric."); + + int64_t byte_size = (*out)->SizeInBytes(); + + // Don't allocate if we have a tensor with no elements. + if (byte_size != 0) { + RETURN_IF_NOT_OK((*out)->AllocateBuffer(byte_size)); + } + + CHECK_FAIL_RETURN_UNEXPECTED( + (*out)->SetAttributes(data_ptr, dataSize, attributes[0], attributes[1], attributes[2], attributes[3]), + "Fail to set attributes for DeviceTensor"); + + return Status::OK(); +} + uint8_t *DeviceTensor::GetDeviceBuffer() { return device_data_; } +uint8_t *DeviceTensor::GetDeviceMutableBuffer() { return device_data_; } + +DataType DeviceTensor::DeviceDataType() const { return device_data_type_; } + uint32_t DeviceTensor::DeviceDataSize() { return size_; } +Status DeviceTensor::SetYuvStrideShape_(const uint32_t &width, const uint32_t &widthStride, const uint32_t &height, + const uint32_t &heightStride) { + YUV_shape_ = {width, widthStride, height, heightStride}; + return Status::OK(); +} + +std::vector DeviceTensor::GetYuvStrideShape() { return YUV_shape_; } + +Status DeviceTensor::SetAttributes(uint8_t *data_ptr, const uint32_t &dataSize, const uint32_t &width, + const uint32_t &widthStride, const uint32_t &height, const uint32_t &heightStride) { + device_data_ = data_ptr; + CHECK_FAIL_RETURN_UNEXPECTED(device_data_ != nullptr, "Fail to get the device data."); + SetSize_(dataSize); + SetYuvStrideShape_(width, widthStride, height, heightStride); + return Status::OK(); +} + Status DeviceTensor::SetSize_(const uint32_t &new_size) { size_ = new_size; return Status::OK(); diff --git a/mindspore/ccsrc/minddata/dataset/core/device_tensor.h b/mindspore/ccsrc/minddata/dataset/core/device_tensor.h index 8b9fe6c94e..9490f578e0 100644 --- a/mindspore/ccsrc/minddata/dataset/core/device_tensor.h +++ b/mindspore/ccsrc/minddata/dataset/core/device_tensor.h @@ -39,12 +39,20 @@ class DeviceTensor : public Tensor { static Status CreateEmpty(const TensorShape &shape, const DataType &type, std::shared_ptr *out); + static Status CreateFromDeviceMemory(const TensorShape &shape, const DataType &type, uint8_t *data_ptr, + const uint32_t &dataSize, const std::vector &attributes, + std::shared_ptr *out); + uint8_t *GetDeviceBuffer(); + uint8_t *GetDeviceMutableBuffer(); + std::vector GetYuvStrideShape(); uint32_t DeviceDataSize(); + DataType DeviceDataType() const; + bool HasDeviceData() { return device_data_ != nullptr; } private: @@ -58,6 +66,8 @@ class DeviceTensor : public Tensor { uint8_t *device_data_; uint32_t size_; + + DataType device_data_type_; }; } // namespace dataset diff --git a/mindspore/ccsrc/minddata/dataset/include/execute.h b/mindspore/ccsrc/minddata/dataset/include/execute.h index d96b5db04a..d1d64d9059 100644 --- a/mindspore/ccsrc/minddata/dataset/include/execute.h +++ b/mindspore/ccsrc/minddata/dataset/include/execute.h @@ -67,8 +67,12 @@ class Execute { std::string AippCfgGenerator(); private: + Status ParseTransforms_(); + Status validate_device_(); + std::vector> transforms_; + std::vector> ops_; MapTargetDevice device_type_;