diff --git a/mindspore/lite/src/CMakeLists.txt b/mindspore/lite/src/CMakeLists.txt index b4cbd79109..f226dd9ac4 100644 --- a/mindspore/lite/src/CMakeLists.txt +++ b/mindspore/lite/src/CMakeLists.txt @@ -26,6 +26,7 @@ set(LITE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/runtime/runtime_api.cc ${CMAKE_CURRENT_SOURCE_DIR}/runtime/thread_pool.c ${CMAKE_CURRENT_SOURCE_DIR}/tensor.cc + ${CMAKE_CURRENT_SOURCE_DIR}/tensorlist.cc ${CMAKE_CURRENT_SOURCE_DIR}/executor.cc ${CMAKE_CURRENT_SOURCE_DIR}/inner_context.cc ${CMAKE_CURRENT_SOURCE_DIR}/model_common.cc diff --git a/mindspore/lite/src/ops/populate/tensorlistfromtensor_populate.cc b/mindspore/lite/src/ops/populate/tensorlistfromtensor_populate.cc index b37d3c92b0..dbc4a605e7 100644 --- a/mindspore/lite/src/ops/populate/tensorlistfromtensor_populate.cc +++ b/mindspore/lite/src/ops/populate/tensorlistfromtensor_populate.cc @@ -17,7 +17,7 @@ #include "nnacl/tensorlist_parameter.h" #include "src/ops/primitive_c.h" #include "src/ops/populate/populate_register.h" -#include "src/ops/tensor_list.h" +#include "src/ops/tensorlistfromtensor.h" namespace mindspore { namespace lite { @@ -31,8 +31,8 @@ OpParameter *PopulateTensorListFromTensorParameter(const mindspore::lite::Primit TensorList_param->op_parameter_.type_ = primitive->Type(); auto tensorList = reinterpret_cast(const_cast(primitive)); - TensorList_param->shape_type_ = tensorList->GetShapeType(); - TensorList_param->element_dtype_ = tensorList->GetElementDType(); + TensorList_param->shape_type_ = (TypeId)(tensorList->GetShapeType()); + TensorList_param->element_dtype_ = (TypeId)(tensorList->GetElementDType()); return reinterpret_cast(TensorList_param); } Registry TensorListFromTensorParameterRegistry(schema::PrimitiveType_TensorListFromTensor, diff --git a/mindspore/lite/src/ops/populate/tensorlistgetitem_populate.cc b/mindspore/lite/src/ops/populate/tensorlistgetitem_populate.cc index 6d75b5d990..4ca542724f 100644 --- a/mindspore/lite/src/ops/populate/tensorlistgetitem_populate.cc +++ b/mindspore/lite/src/ops/populate/tensorlistgetitem_populate.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "src/ops/tensor_list.h" +#include "src/ops/tensorlistgetitem.h" #include "src/ops/primitive_c.h" #include "src/ops/populate/populate_register.h" #include "nnacl/tensorlist_parameter.h" diff --git a/mindspore/lite/src/ops/populate/tensorlistreserve_populate.cc b/mindspore/lite/src/ops/populate/tensorlistreserve_populate.cc index 6ffce6d8de..8504f40d3f 100644 --- a/mindspore/lite/src/ops/populate/tensorlistreserve_populate.cc +++ b/mindspore/lite/src/ops/populate/tensorlistreserve_populate.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "src/ops/tensor_list.h" +#include "src/ops/tensorlistreserve.h" #include "src/ops/primitive_c.h" #include "src/ops/populate/populate_register.h" #include "nnacl/tensorlist_parameter.h" diff --git a/mindspore/lite/src/ops/populate/tensorlistsetlitem_populate.cc b/mindspore/lite/src/ops/populate/tensorlistsetlitem_populate.cc new file mode 100644 index 0000000000..163d0d9065 --- /dev/null +++ b/mindspore/lite/src/ops/populate/tensorlistsetlitem_populate.cc @@ -0,0 +1,41 @@ +/** + * Copyright 2019-2020 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "src/ops/tensorlistsetitem.h" +#include "src/ops/primitive_c.h" +#include "src/ops/populate/populate_register.h" +#include "nnacl/tensorlist_parameter.h" + +namespace mindspore { +namespace lite { +OpParameter *PopulateTensorListSetItemParameter(const mindspore::lite::PrimitiveC *primitive) { + TensorListParameter *setItem_param = reinterpret_cast(malloc(sizeof(TensorListParameter))); + if (setItem_param == nullptr) { + MS_LOG(ERROR) << "malloc TensorListParameter failed."; + return nullptr; + } + memset(setItem_param, 0, sizeof(TensorListParameter)); + setItem_param->op_parameter_.type_ = primitive->Type(); + auto setItem = + reinterpret_cast(const_cast(primitive)); + setItem_param->element_dtype_ = setItem->GetElementDType(); + return reinterpret_cast(setItem_param); +} +Registry TensorListSetItemParameterRegistry(schema::PrimitiveType_TensorListSetItem, + PopulateTensorListSetItemParameter); + +} // namespace lite +} // namespace mindspore diff --git a/mindspore/lite/src/ops/populate/tensorliststack_populate.cc b/mindspore/lite/src/ops/populate/tensorliststack_populate.cc index e0413e202d..88bab2207a 100644 --- a/mindspore/lite/src/ops/populate/tensorliststack_populate.cc +++ b/mindspore/lite/src/ops/populate/tensorliststack_populate.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "src/ops/tensor_list.h" +#include "src/ops/tensorliststack.h" #include "src/ops/primitive_c.h" #include "src/ops/populate/populate_register.h" #include "nnacl/tensorlist_parameter.h" diff --git a/mindspore/lite/src/ops/tensor_list.cc b/mindspore/lite/src/ops/tensor_list.cc deleted file mode 100644 index 061e3c3828..0000000000 --- a/mindspore/lite/src/ops/tensor_list.cc +++ /dev/null @@ -1,314 +0,0 @@ -/** - * Copyright 2020 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include -#include "src/ops/tensor_list.h" - -#ifndef PRIMITIVE_WRITEABLE -#include "src/ops/ops_register.h" -#endif - -using mindspore::schema::Format_NC; - -namespace mindspore { -namespace lite { - -int TensorListFromTensor::InferShape(std::vector inputs_, std::vector outputs_) { - // inputs0:tensor - // inputs1: element_shape - // outputs0: vector.size() dtype - // outputs1: element_shape - // outputs2-n: vector - auto input = inputs_.at(0); - MS_ASSERT(input != nullptr); - std::vector in_shape = input->shape(); - int dim0 = in_shape.at(0); - if (dim0 <= 0) { - MS_LOG(ERROR) << "inputs_[0] dim0:" << dim0 << " must greater than 0"; - return RET_ERROR; - } - std::vector out_shape(in_shape.begin() + 1, in_shape.end()); - int out_vec_size = outputs_.size() - 2; - if (out_vec_size != dim0) { - MS_LOG(ERROR) << "outputs_.size() - 2:" << out_vec_size << "must be equal to dim0:" << dim0; - return RET_ERROR; - } - for (int i = 0; i < dim0; ++i) { - auto output = outputs_.at(i + 2); - MS_ASSERT(output != nullptr); - output->set_data_type(input->data_type()); - output->set_shape(out_shape); - } - - auto output = outputs_.at(0); // vector.size(), tensorlist.dtype - MS_ASSERT(output != nullptr); - output->set_data_type(kNumberTypeInt); - output->set_shape(std::vector(1, 2)); // one element.value = 2 - - output = outputs_.at(1); // element_shape tensor - MS_ASSERT(output != nullptr); - output->set_data_type(inputs_.at(1)->data_type()); - output->set_format(inputs_.at(1)->format()); - output->set_shape(inputs_.at(1)->shape()); - - return RET_OK; -} - -bool TensorListGetItem::IsFullyDefined(const std::vector &shape) const { - for (size_t i = 0; i < shape.size(); ++i) { - if (shape.at(i) < 0) { - return false; - } - } - return true; -} - -int TensorListGetItem::InferShape(std::vector inputs_, std::vector outputs_) { - int in_vec_size = inputs_.size(); - auto input0 = inputs_.at(0); - MS_ASSERT(input0 != nullptr); - auto in0_ptr = reinterpret_cast(input0->data_c()); - if (in_vec_size != in0_ptr[0] + 4) { - MS_LOG(ERROR) << "inputs_.size():" << in_vec_size << " must be equal to:" << in0_ptr[0] + 4; - return RET_ERROR; - } - auto get_index = inputs_.at(in0_ptr[0] + 2); - MS_ASSERT(get_index != nullptr); - index_ = reinterpret_cast(get_index->data_c())[0]; - if (index_ < 0 || index_ > in0_ptr[0]) { - MS_LOG(ERROR) << "index_:" << index_ << "must in [0, " << in0_ptr[0] << "]"; - return RET_ERROR; - } - auto input_index = inputs_.at(index_ + 2); - MS_ASSERT(input_index != nullptr); - auto output = outputs_.front(); - MS_ASSERT(output != nullptr); - if (input_index->data_type() != kTypeUnknown) { - output->set_format(input_index->format()); - output->set_data_type(input_index->data_type()); - output->set_shape(input_index->shape()); - } else { - auto ele_shape_tensor = inputs_.at(in0_ptr[0] + 3); - MS_ASSERT(ele_shape_tensor != nullptr); - auto ele_shape_type = ele_shape_tensor->data_type(); - if (ele_shape_type != kNumberTypeInt) { - MS_LOG(ERROR) << "ele_shape_tensor.data_type():" << ele_shape_type - << " must be \"kNumberTypeInt\":" << kNumberTypeInt; - return RET_ERROR; - } - auto shape_ptr = reinterpret_cast(ele_shape_tensor->data_c()); - for (int i = 0; i < ele_shape_tensor->ElementsNum(); ++i) { - element_shape_.push_back(shape_ptr[i]); - } - if (!IsFullyDefined(element_shape_)) { - for (int i = 0; i < in0_ptr[0]; ++i) { - auto input = inputs_.at(i + 2); - if (input->data_type() != kTypeUnknown) { - std::vector tmp = input->shape(); - for (size_t j = 0; j < tmp.size(); ++j) { - element_shape_.at(j) = element_shape_.at(j) >= 0 ? element_shape_.at(j) : tmp.at(j); - } - } - } - } - if (!IsFullyDefined(element_shape_)) { - MS_LOG(ERROR) << "ele_shape_tensor Is Not FullyDefined!"; - return RET_ERROR; - } - element_dtype_ = GetElementDType(); - output->set_data_type(element_dtype_); - output->set_shape(element_shape_); - } - return RET_OK; -} -#ifdef PRIMITIVE_WRITEABLE -TypeId TensorListFromTensor::GetElementDType() const { - return (TypeId)(this->primitive_->value.AsTensorListFromTensor()->elementDType); -} - -TypeId TensorListFromTensor::GetShapeType() const { - return (TypeId)(this->primitive_->value.AsTensorListFromTensor()->shapeType); -} - -TypeId TensorListGetItem::GetElementDType() const { - return (TypeId)(this->primitive_->value.AsTensorListGetItem()->elementDType); -} -TypeId TensorListReserve::GetElementDType() const { - return (TypeId)(this->primitive_->value.AsTensorListReserve()->elementDType); -} - -TypeId TensorListStack::GetElementDType() const { - return (TypeId)(this->primitive_->value.AsTensorListStack()->elementDType); -} - -int TensorListStack::GetNumElements() const { return this->primitive_->value.AsTensorListStack()->numElements; } - -#else -TypeId TensorListFromTensor::GetElementDType() const { - return (TypeId)(this->primitive_->value_as_TensorListFromTensor()->elementDType()); -} - -TypeId TensorListFromTensor::GetShapeType() const { - return (TypeId)(this->primitive_->value_as_TensorListFromTensor()->shapeType()); -} - -TypeId TensorListGetItem::GetElementDType() const { - return (TypeId)(this->primitive_->value_as_TensorListGetItem()->elementDType()); -} -TypeId TensorListReserve::GetElementDType() const { - return (TypeId)(this->primitive_->value_as_TensorListReserve()->elementDType()); -} - -TypeId TensorListStack::GetElementDType() const { - return (TypeId)(this->primitive_->value_as_TensorListStack()->elementDType()); -} - -int TensorListStack::GetNumElements() const { return this->primitive_->value_as_TensorListStack()->numElements(); } -#endif - -int TensorListReserve::InferShape(std::vector inputs_, std::vector outputs_) { - // input0: element_shape_tensor - // input1: num_elements - auto input0 = inputs_.front(); - MS_ASSERT(input0 != nullptr); - auto ele_shape_type = input0->data_type(); - if (ele_shape_type != kNumberTypeInt) { - MS_LOG(ERROR) << "ele_shape_tensor.data_type():" << ele_shape_type - << " must be \"kNumberTypeInt\":" << kNumberTypeInt; - return RET_ERROR; - } - auto input1 = inputs_.at(1); - MS_ASSERT(input1 != nullptr); - auto num_ele_type = input1->data_type(); - if (num_ele_type != kNumberTypeInt) { - MS_LOG(ERROR) << "num_ele_tensor.data_type():" << num_ele_type << " must be \"kNumberTypeInt\":" << kNumberTypeInt; - return RET_ERROR; - } - int num_elements = reinterpret_cast(input1->data_c())[0]; - auto out_vec_size = outputs_.size(); - if (out_vec_size != (size_t)(num_elements + 2)) { - MS_LOG(ERROR) << "outputs_.size():" << out_vec_size << " must be equal to:" << num_elements + 2; - return RET_ERROR; - } - - for (int i = 0; i < num_elements; ++i) { - auto output = outputs_.at(i + 2); - MS_ASSERT(output != nullptr); - output->set_data_type(kTypeUnknown); - output->set_shape(std::vector(1, 0)); // shape = [0] - } - - auto output = outputs_.at(0); // vector.size(), tensorlist.dtype - MS_ASSERT(output != nullptr); - output->set_data_type(kNumberTypeInt); - output->set_shape(std::vector(1, 2)); // one element.value = 2 - - output = outputs_.at(1); // element_shape tensor - MS_ASSERT(output != nullptr); - output->set_data_type(input0->data_type()); - output->set_format(input0->format()); - output->set_shape(input0->shape()); - return RET_OK; -} - -bool TensorListStack::IsFullyDefined(const std::vector &shape) const { - for (size_t i = 0; i < shape.size(); ++i) { - if (shape.at(i) < 0) { - return false; - } - } - return true; -} - -int TensorListStack::InferShape(std::vector inputs_, std::vector outputs_) { - // input0: tensorlist - // input[inputs_.size() - 1]: element_shape - auto input0 = inputs_.front(); - MS_ASSERT(input0 != nullptr); - auto input0_ptr = reinterpret_cast(input0->data_c()); - int vec_in_size = inputs_.size(); - if (vec_in_size != input0_ptr[0] + 3) { - MS_LOG(ERROR) << "inputs_.size():" << vec_in_size << " must be equal:" << input0_ptr[0] + 3; - return RET_ERROR; - } - auto ele_shape = inputs_.at(input0_ptr[0] + 2); // element shape - MS_ASSERT(ele_shape != nullptr); - auto ele_shape_ptr = reinterpret_cast(ele_shape->data_c()); - for (int i = 0; ele_shape->ElementsNum(); ++i) { - output_shape_.push_back(ele_shape_ptr[i]); - } - std::vector tensorlist_shape; - MS_ASSERT(inputs_.at(1) != nullptr); - auto input1_ptr = reinterpret_cast(inputs_.at(1)->data_c()); - for (int i = 0; i < inputs_.at(1)->ElementsNum(); ++i) { - tensorlist_shape.push_back(input1_ptr[i]); - } - auto status = MergeShape(tensorlist_shape); - if (status == RET_ERROR) { - MS_LOG(ERROR) << "Merge tensorlist_shape is error!"; - return RET_ERROR; - } - if (!IsFullyDefined(output_shape_)) { - MS_LOG(ERROR) << "element_shape Is Not FullyDefined!"; - return RET_ERROR; - } - if (!IsFullyDefined(tensorlist_shape)) { - for (int i = 0; i < input0_ptr[0]; ++i) { // get tensorlist every tensor - auto tensor_tmp = inputs_.at(i + 2); - MS_ASSERT(tensor_tmp != nullptr); - if (tensor_tmp->data_type() != kTypeUnknown) { - status = MergeShape(tensor_tmp->shape()); - if (status == RET_ERROR) { - MS_LOG(ERROR) << "Merge inputs_[" << i + 2 << "] is error!"; - return RET_ERROR; - } - } - } - } - auto output = outputs_.front(); - MS_ASSERT(output != nullptr); - output->set_format(Format_NC); - output->set_data_type(static_cast(input0_ptr[1])); - output->set_shape(std::vector( - 1, input0_ptr[0] * std::accumulate(output_shape_.begin(), output_shape_.end(), 1LL, std::multiplies()))); - return RET_OK; -} - -int TensorListStack::MergeShape(const std::vector &shape) { - size_t dim0 = shape.size(); - size_t dim1 = output_shape_.size(); - if (dim1 >= unKnownRank_) { - output_shape_ = shape; - return RET_OK; - } - if (dim1 != dim0) { - MS_LOG(ERROR) << "shape.size():" << dim1 << " must be equal output_shape_.size():" << dim0; - return RET_ERROR; - } - for (size_t i = 0; i < dim0; ++i) { - int dim0_size = shape.at(i); - int dim1_size = output_shape_.at(i); - if (dim0_size >= 0 && dim1_size >= 0 && dim0_size != dim1_size) { - MS_LOG(ERROR) << "shape[" << i << "]:" << dim0_size << " is incompatible with output_shape_[" << i - << "]:" << dim1_size; - return RET_ERROR; - } - int tmp_size = dim1_size >= 0 ? dim1_size : dim0_size; - output_shape_.at(i) = tmp_size; - } - return RET_OK; -} -} // namespace lite -} // namespace mindspore diff --git a/mindspore/lite/src/ops/tensorlistfromtensor.cc b/mindspore/lite/src/ops/tensorlistfromtensor.cc new file mode 100644 index 0000000000..f3f70cf46a --- /dev/null +++ b/mindspore/lite/src/ops/tensorlistfromtensor.cc @@ -0,0 +1,141 @@ +/** + * Copyright 2020 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include "src/ops/tensorlistfromtensor.h" + +#ifndef PRIMITIVE_WRITEABLE +#include "src/ops/ops_register.h" +#endif + +namespace mindspore { +namespace lite { +#ifdef PRIMITIVE_WRITEABLE +int TensorListFromTensor::GetElementDType() const { + return this->primitive_->value.AsTensorListFromTensor()->elementDType; +} + +int TensorListFromTensor::GetShapeType() const { return this->primitive_->value.AsTensorListFromTensor()->shapeType; } + +void TensorListFromTensor::SetElementDType(int type) { + this->primitive_->value.AsTensorListFromTensor()->elementDType = type; +} + +void TensorListFromTensor::SetShapeType(int type) { + this->primitive_->value.AsTensorListFromTensor()->shapeType = type; +} + +int TensorListFromTensor::UnPackAttr(const Primitive &prim, const std::vector &inputs) { + if (this->primitive_ == nullptr) { + this->primitive_ = new (std::nothrow) schema::PrimitiveT; + if (this->primitive_ == nullptr) { + MS_LOG(ERROR) << "new primitiveT failed"; + return RET_ERROR; + } + this->primitive_->value.type = schema::PrimitiveType_TensorListFromTensor; + } + if (this->primitive_->value.type != schema::PrimitiveType_TensorListFromTensor) { + MS_LOG(ERROR) << "Primitive type is error :" << this->primitive_->value.type; + delete this->primitive_; + this->primitive_ = nullptr; + return RET_ERROR; + } + if (this->primitive_->value.value == nullptr) { + auto attr = new (std::nothrow) schema::TensorListFromTensorT(); + if (attr == nullptr) { + delete this->primitive_; + this->primitive_ = nullptr; + MS_LOG(ERROR) << "new TensorListFromTensorT value failed"; + return RET_ERROR; + } + if (prim.GetAttr("elementDType") == nullptr) { + delete this->primitive_; + this->primitive_ = nullptr; + delete attr; + MS_LOG(ERROR) << "TensorListFromTensorT's attr elementDType is not set"; + return RET_ERROR; + } else { + attr->elementDType = CastToInt(prim.GetAttr("elementDType")).front(); + } + if (prim.GetAttr("shapeType") == nullptr) { + delete this->primitive_; + this->primitive_ = nullptr; + delete attr; + MS_LOG(ERROR) << "TensorListFromTensorT's attr shapeType is not set"; + return RET_ERROR; + } else { + attr->shapeType = CastToInt(prim.GetAttr("shapeType")).front(); + } + this->primitive_->value.value = attr; + } + return RET_OK; +} +#else +int TensorListFromTensor::GetElementDType() const { + return this->primitive_->value_as_TensorListFromTensor()->elementDType(); +} + +int TensorListFromTensor::GetShapeType() const { + return this->primitive_->value_as_TensorListFromTensor()->shapeType(); +} + +int TensorListFromTensor::UnPackToFlatBuilder(const schema::Primitive *primitive, flatbuffers::FlatBufferBuilder *fbb) { + MS_ASSERT(nullptr != primitive); + MS_ASSERT(nullptr != fbb); + auto attr = primitive->value_as_TensorListFromTensor(); + if (attr == nullptr) { + MS_LOG(ERROR) << "value_as_TensorListFromTensor return nullptr"; + return RET_ERROR; + } + auto val_offset = schema::CreateTensorListFromTensor(*fbb, attr->elementDType(), attr->shapeType()); + auto prim_offset = schema::CreatePrimitive(*fbb, schema::PrimitiveType_TensorListFromTensor, val_offset.o); + fbb->Finish(prim_offset); + return RET_OK; +} + +PrimitiveC *TensorListFromTensorCreator(const schema::Primitive *primitive) { + return PrimitiveC::NewPrimitiveC(primitive); +} +Registry TensorListFromTensorRegistry(schema::PrimitiveType_TensorListFromTensor, TensorListFromTensorCreator); +#endif + +int TensorListFromTensor::InferShape(std::vector inputs_, std::vector outputs_) { + auto input0 = inputs_[0]; + MS_ASSERT(input0 != nullptr); + std::vector input0_shape = input0->shape(); + if (input0_shape.size() < 1) { + MS_LOG(ERROR) << "input0_shape.size():" << input0_shape.size() << " must be greater than 0!"; + return RET_ERROR; + } + int dim0 = input0_shape[0]; + if (dim0 < 0) { + MS_LOG(ERROR) << "inputs_[0] dim0:" << dim0 << " must greater than or equal to 0"; + return RET_ERROR; + } + auto input1 = inputs_[1]; + MS_ASSERT(input1 != nullptr); + auto ele_shape_ptr = reinterpret_cast(input1->data_c()); + auto output = reinterpret_cast(outputs_[0]); + MS_ASSERT(output != nullptr); + // output->set_tensors_data_type(input0->data_type()); + std::vector > tensor_shape(dim0, std::vector(input0_shape.begin() + 1, input0_shape.end())); + output->set_element_shape(std::vector(ele_shape_ptr, ele_shape_ptr + input1->ElementsNum())); + output->set_shape(std::vector(1, dim0)); + output->set_data_type(kObjectTypeTensorType); + output->MallocTensorListData(input0->data_type(), tensor_shape); + return RET_OK; +} +} // namespace lite +} // namespace mindspore diff --git a/mindspore/lite/src/ops/tensorlistfromtensor.h b/mindspore/lite/src/ops/tensorlistfromtensor.h new file mode 100644 index 0000000000..6c7de6209c --- /dev/null +++ b/mindspore/lite/src/ops/tensorlistfromtensor.h @@ -0,0 +1,44 @@ +/** + * Copyright 2020 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include "src/ops/primitive_c.h" +#include "src/tensorlist.h" + +#ifndef LITE_MINDSPORE_LITE_C_OPS_TENSORLISTFROMTENSOR_H_ +#define LITE_MINDSPORE_LITE_C_OPS_TENSORLISTFROMTENSOR_H_ +namespace mindspore { +namespace lite { +class TensorListFromTensor : public PrimitiveC { + public: + TensorListFromTensor() = default; + ~TensorListFromTensor() = default; +#ifdef PRIMITIVE_WRITEABLE + MS_DECLARE_PARENT(TensorListFromTensor, PrimitiveC); + void SetElementDType(int type); + void SetShapeType(int type); + explicit TensorListFromTensor(schema::PrimitiveT *primitive) : PrimitiveC(primitive) {} + int UnPackAttr(const Primitive &prim, const std::vector &inputs) override; +#else + int UnPackToFlatBuilder(const schema::Primitive *primitive, flatbuffers::FlatBufferBuilder *fbb) override; +#endif + int GetElementDType() const; + int GetShapeType() const; + int InferShape(std::vector inputs_, std::vector outputs_) override; +}; +} // namespace lite +} // namespace mindspore + +#endif // LITE_MINDSPORE_LITE_C_OPS_TENSORLISTFROMTENSOR_H_ diff --git a/mindspore/lite/src/ops/tensorlistgetitem.cc b/mindspore/lite/src/ops/tensorlistgetitem.cc new file mode 100644 index 0000000000..129b38bf4d --- /dev/null +++ b/mindspore/lite/src/ops/tensorlistgetitem.cc @@ -0,0 +1,171 @@ +/** + * Copyright 2020 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include "src/ops/tensorlistgetitem.h" + +#ifndef PRIMITIVE_WRITEABLE +#include "src/ops/ops_register.h" +#endif + +namespace mindspore { +namespace lite { +#ifdef PRIMITIVE_WRITEABLE +TypeId TensorListGetItem::GetElementDType() const { + return (TypeId)(this->primitive_->value.AsTensorListGetItem()->elementDType); +} + +void TensorListGetItem::SetElementDType(int type) { + this->primitive_->value.AsTensorListGetItem()->elementDType = type; +} + +int TensorListGetItem::UnPackAttr(const Primitive &prim, const std::vector &inputs) { + if (this->primitive_ == nullptr) { + this->primitive_ = new (std::nothrow) schema::PrimitiveT; + if (this->primitive_ == nullptr) { + MS_LOG(ERROR) << "new primitiveT failed"; + return RET_ERROR; + } + this->primitive_->value.type = schema::PrimitiveType_TensorListGetItem; + } + if (this->primitive_->value.type != schema::PrimitiveType_TensorListGetItem) { + MS_LOG(ERROR) << "Primitive type is error :" << this->primitive_->value.type; + delete this->primitive_; + this->primitive_ = nullptr; + return RET_ERROR; + } + if (this->primitive_->value.value == nullptr) { + auto attr = new (std::nothrow) schema::TensorListGetItemT(); + if (attr == nullptr) { + delete this->primitive_; + this->primitive_ = nullptr; + MS_LOG(ERROR) << "new TensorListGetItemT value failed"; + return RET_ERROR; + } + if (prim.GetAttr("elementDType") == nullptr) { + delete this->primitive_; + this->primitive_ = nullptr; + delete attr; + MS_LOG(ERROR) << "TensorListGetItem's attr elementDType is not set"; + return RET_ERROR; + } else { + attr->elementDType = CastToInt(prim.GetAttr("elementDType")).front(); + } + this->primitive_->value.value = attr; + } + return RET_OK; +} +#else +TypeId TensorListGetItem::GetElementDType() const { + return (TypeId)(this->primitive_->value_as_TensorListGetItem()->elementDType()); +} + +int TensorListGetItem::UnPackToFlatBuilder(const schema::Primitive *primitive, flatbuffers::FlatBufferBuilder *fbb) { + MS_ASSERT(nullptr != primitive); + MS_ASSERT(nullptr != fbb); + auto attr = primitive->value_as_TensorListGetItem(); + if (attr == nullptr) { + MS_LOG(ERROR) << "value_as_TensorListGetItem return nullptr"; + return RET_ERROR; + } + auto val_offset = schema::CreateTensorListGetItem(*fbb, attr->elementDType()); + auto prim_offset = schema::CreatePrimitive(*fbb, schema::PrimitiveType_TensorListGetItem, val_offset.o); + fbb->Finish(prim_offset); + return RET_OK; +} + +PrimitiveC *TensorListGetItemCreator(const schema::Primitive *primitive) { + return PrimitiveC::NewPrimitiveC(primitive); +} +Registry TensorListGetItemRegistry(schema::PrimitiveType_TensorListGetItem, TensorListGetItemCreator); +#endif +bool TensorListGetItem::IsFullyDefined(const std::vector &shape) const { + for (size_t i = 0; i < shape.size(); ++i) { + if (shape[i] < 0) { + return false; + } + } + return true; +} + +int TensorListGetItem::MergeShape(const std::vector &tmp) { + if (element_shape_.size() != tmp.size()) { + MS_LOG(ERROR) << "element_shape_.size():" << element_shape_.size() << " must be equal to tmp.size():" << tmp.size(); + return RET_ERROR; + } + for (size_t j = 0; j < tmp.size(); ++j) { + if (element_shape_[j] >= 0 && tmp[j] >= 0 && element_shape_[j] != tmp[j]) { + MS_LOG(ERROR) << "element_shape_[" << j << "]:" << element_shape_[j] << " must be equal to tmp[" << j + << "]:" << tmp[j]; + return RET_ERROR; + } + element_shape_[j] = element_shape_[j] >= 0 ? element_shape_[j] : tmp[j]; + } + return RET_OK; +} + +int TensorListGetItem::InferShape(std::vector inputs_, std::vector outputs_) { + auto input0 = reinterpret_cast(inputs_[0]); + auto get_index = inputs_[1]; + MS_ASSERT(get_index != nullptr); + if (get_index->ElementsNum() != 1) { + MS_LOG(ERROR) << "get_index->ElementsNum():" << get_index->ElementsNum() << " must be equal to 1!"; + return RET_ERROR; + } + index_ = reinterpret_cast(get_index->data_c())[0]; + if (index_ < 0 || index_ > (input0->ElementsNum() - 1)) { + MS_LOG(ERROR) << "index_:" << index_ << "must in [0, " << input0->ElementsNum() - 1 << "]"; + return RET_ERROR; + } + auto tensor_index = input0->GetTensorIndex(index_); + MS_ASSERT(tensor_index != nullptr); + auto output = outputs_.front(); + MS_ASSERT(output != nullptr); + if (tensor_index->data_type() != kTypeUnknown) { + output->set_data_type(tensor_index->data_type()); + output->set_shape(tensor_index->shape()); + } else { + auto input2 = inputs_[2]; + auto ele_shape_data = reinterpret_cast(input2->data_c()); + for (int i = 0; i < input2->ElementsNum(); ++i) { + element_shape_.push_back(ele_shape_data[i]); + } + auto status = MergeShape(input0->element_shape()); + if (status != RET_OK) { + return RET_ERROR; + } + if (!IsFullyDefined(element_shape_)) { + for (int i = 0; i < input0->ElementsNum(); ++i) { + auto input = input0->GetTensorIndex(i); + MS_ASSERT(input != nullptr); + if (input->data_type() != kTypeUnknown) { + status = MergeShape(input->shape()); + if (status != RET_OK) { + return RET_ERROR; + } + } + } + } + if (!IsFullyDefined(element_shape_)) { + MS_LOG(ERROR) << "element_shape_ is not fullyDefined!"; + return RET_ERROR; + } + output->set_data_type(GetElementDType()); + output->set_shape(element_shape_); + } + return RET_OK; +} +} // namespace lite +} // namespace mindspore diff --git a/mindspore/lite/src/ops/tensorlistgetitem.h b/mindspore/lite/src/ops/tensorlistgetitem.h new file mode 100644 index 0000000000..93f8eea307 --- /dev/null +++ b/mindspore/lite/src/ops/tensorlistgetitem.h @@ -0,0 +1,49 @@ +/** + * Copyright 2020 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include "src/ops/primitive_c.h" +#include "src/tensorlist.h" +#include "ir/dtype/type_id.h" + +#ifndef LITE_MINDSPORE_LITE_C_OPS_TENSORLISTGETITEM_H_ +#define LITE_MINDSPORE_LITE_C_OPS_TENSORLISTGETITEM_H_ +namespace mindspore { +namespace lite { +class TensorListGetItem : public PrimitiveC { + public: + TensorListGetItem() = default; + ~TensorListGetItem() = default; +#ifdef PRIMITIVE_WRITEABLE + MS_DECLARE_PARENT(TensorListGetItem, PrimitiveC); + void SetElementDType(int type); + explicit TensorListGetItem(schema::PrimitiveT *primitive) : PrimitiveC(primitive) {} + int UnPackAttr(const Primitive &prim, const std::vector &inputs) override; +#else + int UnPackToFlatBuilder(const schema::Primitive *primitive, flatbuffers::FlatBufferBuilder *fbb) override; +#endif + TypeId GetElementDType() const; + int MergeShape(const std::vector &tmp); + bool IsFullyDefined(const std::vector &shape) const; + int InferShape(std::vector inputs_, std::vector outputs_) override; + + private: + int index_ = -1; + std::vector element_shape_; +}; +} // namespace lite +} // namespace mindspore + +#endif // LITE_MINDSPORE_LITE_C_OPS_TENSORLISTGETITEM_H_ diff --git a/mindspore/lite/src/ops/tensorlistreserve.cc b/mindspore/lite/src/ops/tensorlistreserve.cc new file mode 100644 index 0000000000..63b5ff44e9 --- /dev/null +++ b/mindspore/lite/src/ops/tensorlistreserve.cc @@ -0,0 +1,131 @@ +/** + * Copyright 2020 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include "src/ops/tensorlistreserve.h" + +#ifndef PRIMITIVE_WRITEABLE +#include "src/ops/ops_register.h" +#endif + +namespace mindspore { +namespace lite { +#ifdef PRIMITIVE_WRITEABLE +TypeId TensorListReserve::GetElementDType() const { + return (TypeId)(this->primitive_->value.AsTensorListReserve()->elementDType); +} + +void TensorListReserve::SetElementDType(int type) { + this->primitive_->value.AsTensorListReserve()->elementDType = type; +} + +int TensorListReserve::UnPackAttr(const Primitive &prim, const std::vector &inputs) { + if (this->primitive_ == nullptr) { + this->primitive_ = new (std::nothrow) schema::PrimitiveT; + if (this->primitive_ == nullptr) { + MS_LOG(ERROR) << "new primitiveT failed"; + return RET_ERROR; + } + this->primitive_->value.type = schema::PrimitiveType_TensorListReserve; + } + if (this->primitive_->value.type != schema::PrimitiveType_TensorListReserve) { + MS_LOG(ERROR) << "Primitive type is error :" << this->primitive_->value.type; + delete this->primitive_; + this->primitive_ = nullptr; + return RET_ERROR; + } + if (this->primitive_->value.value == nullptr) { + auto attr = new (std::nothrow) schema::TensorListReserveT(); + if (attr == nullptr) { + delete this->primitive_; + this->primitive_ = nullptr; + MS_LOG(ERROR) << "new TensorListReserveT value failed"; + return RET_ERROR; + } + if (prim.GetAttr("elementDType") == nullptr) { + delete this->primitive_; + this->primitive_ = nullptr; + delete attr; + MS_LOG(ERROR) << "TensorListReserve's attr elementDType is not set"; + return RET_ERROR; + } else { + attr->elementDType = CastToInt(prim.GetAttr("elementDType")).front(); + } + this->primitive_->value.value = attr; + } + return RET_OK; +} + +#else +TypeId TensorListReserve::GetElementDType() const { + return (TypeId)(this->primitive_->value_as_TensorListReserve()->elementDType()); +} + +int TensorListReserve::UnPackToFlatBuilder(const schema::Primitive *primitive, flatbuffers::FlatBufferBuilder *fbb) { + MS_ASSERT(primitive != nullptr); + MS_ASSERT(fbb != nullptr); + auto attr = primitive->value_as_TensorListReserve(); + if (attr == nullptr) { + MS_LOG(ERROR) << "value_as_TensorListReserve return nullptr"; + return RET_ERROR; + } + auto val_offset = schema::CreateTensorListReserve(*fbb, attr->elementDType()); + auto prim_offset = schema::CreatePrimitive(*fbb, schema::PrimitiveType_TensorListReserve, val_offset.o); + fbb->Finish(prim_offset); + return RET_OK; +} + +PrimitiveC *TensorListReserveCreator(const schema::Primitive *primitive) { + return PrimitiveC::NewPrimitiveC(primitive); +} +Registry TensorListReserveRegistry(schema::PrimitiveType_TensorListReserve, TensorListReserveCreator); +#endif + +int TensorListReserve::InferShape(std::vector inputs_, std::vector outputs_) { + // input0: element_shape_tensor + // input1: num_elements + auto input0 = inputs_.front(); + MS_ASSERT(input0 != nullptr); + auto ele_shape_type = input0->data_type(); + if (ele_shape_type != kNumberTypeInt) { + MS_LOG(ERROR) << "ele_shape_tensor.data_type():" << ele_shape_type + << " must be \"kNumberTypeInt\":" << kNumberTypeInt; + return RET_ERROR; + } + auto ele_shape_ptr = reinterpret_cast(input0->data_c()); + + auto input1 = inputs_[1]; + MS_ASSERT(input1 != nullptr); + auto num_ele_type = input1->data_type(); + if (num_ele_type != kNumberTypeInt) { + MS_LOG(ERROR) << "num_ele_tensor.data_type():" << num_ele_type << " must be \"kNumberTypeInt\":" << kNumberTypeInt; + return RET_ERROR; + } + if (input1->ElementsNum() != 1) { + MS_LOG(ERROR) << "input1->ElementsNum() must be equal to 1"; + return RET_ERROR; + } + int num_elements = reinterpret_cast(input1->data_c())[0]; + + auto output = reinterpret_cast(outputs_[0]); + output->set_data_type(kObjectTypeTensorType); + std::vector > tmp_shape(num_elements, std::vector()); + output->set_element_shape(std::vector(ele_shape_ptr, ele_shape_ptr + input0->ElementsNum())); + output->set_shape(std::vector(1, num_elements)); + output->MallocTensorListData(kTypeUnknown, tmp_shape); + return RET_OK; +} +} // namespace lite +} // namespace mindspore diff --git a/mindspore/lite/src/ops/tensorlistreserve.h b/mindspore/lite/src/ops/tensorlistreserve.h new file mode 100644 index 0000000000..126b9aa8da --- /dev/null +++ b/mindspore/lite/src/ops/tensorlistreserve.h @@ -0,0 +1,43 @@ +/** + * Copyright 2020 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include "src/ops/primitive_c.h" +#include "src/tensorlist.h" +#include "ir/dtype/type_id.h" + +#ifndef LITE_MINDSPORE_LITE_C_OPS_TENSORLISTRESERVE_H_ +#define LITE_MINDSPORE_LITE_C_OPS_TENSORLISTRESERVE_H_ +namespace mindspore { +namespace lite { +class TensorListReserve : public PrimitiveC { + public: + TensorListReserve() = default; + ~TensorListReserve() = default; +#ifdef PRIMITIVE_WRITEABLE + MS_DECLARE_PARENT(TensorListReserve, PrimitiveC); + void SetElementDType(int type); + explicit TensorListReserve(schema::PrimitiveT *primitive) : PrimitiveC(primitive) {} + int UnPackAttr(const Primitive &prim, const std::vector &inputs) override; +#else + int UnPackToFlatBuilder(const schema::Primitive *primitive, flatbuffers::FlatBufferBuilder *fbb) override; +#endif + TypeId GetElementDType() const; + int InferShape(std::vector inputs_, std::vector outputs_) override; +}; +} // namespace lite +} // namespace mindspore + +#endif // LITE_MINDSPORE_LITE_C_OPS_TENSORLISTRESERVE_H_ diff --git a/mindspore/lite/src/ops/tensorlistsetitem.cc b/mindspore/lite/src/ops/tensorlistsetitem.cc new file mode 100644 index 0000000000..24f492b9df --- /dev/null +++ b/mindspore/lite/src/ops/tensorlistsetitem.cc @@ -0,0 +1,140 @@ +/** + * Copyright 2020 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include "src/ops/tensorlistsetitem.h" + +#ifndef PRIMITIVE_WRITEABLE +#include "src/ops/ops_register.h" +#endif + +namespace mindspore { +namespace lite { +#ifdef PRIMITIVE_WRITEABLE +TypeId TensorListSetItem::GetElementDType() const { + return (TypeId)(this->primitive_->value.AsTensorListSetItem()->elementDType); +} + +void TensorListSetItem::SetElementDType(int type) { + this->primitive_->value.AsTensorListSetItem()->elementDType = type; +} + +int TensorListSetItem::UnPackAttr(const Primitive &prim, const std::vector &inputs) { + if (this->primitive_ == nullptr) { + this->primitive_ = new (std::nothrow) schema::PrimitiveT; + if (this->primitive_ == nullptr) { + MS_LOG(ERROR) << "new primitiveT failed"; + return RET_ERROR; + } + this->primitive_->value.type = schema::PrimitiveType_TensorListSetItem; + } + if (this->primitive_->value.type != schema::PrimitiveType_TensorListSetItem) { + MS_LOG(ERROR) << "Primitive type is error :" << this->primitive_->value.type; + delete this->primitive_; + this->primitive_ = nullptr; + return RET_ERROR; + } + if (this->primitive_->value.value == nullptr) { + auto attr = new (std::nothrow) schema::TensorListSetItemT(); + if (attr == nullptr) { + delete this->primitive_; + this->primitive_ = nullptr; + MS_LOG(ERROR) << "new TensorListSetItemT value failed"; + return RET_ERROR; + } + if (prim.GetAttr("elementDType") == nullptr) { + delete this->primitive_; + this->primitive_ = nullptr; + delete attr; + MS_LOG(ERROR) << "TensorListSetItem's attr elementDType is not set"; + return RET_ERROR; + } else { + attr->elementDType = CastToInt(prim.GetAttr("elementDType")).front(); + } + this->primitive_->value.value = attr; + } + return RET_OK; +} +#else +TypeId TensorListSetItem::GetElementDType() const { + return (TypeId)(this->primitive_->value_as_TensorListSetItem()->elementDType()); +} + +int TensorListSetItem::UnPackToFlatBuilder(const schema::Primitive *primitive, flatbuffers::FlatBufferBuilder *fbb) { + MS_ASSERT(nullptr != primitive); + MS_ASSERT(nullptr != fbb); + auto attr = primitive->value_as_TensorListSetItem(); + if (attr == nullptr) { + MS_LOG(ERROR) << "value_as_TensorListSetItem return nullptr"; + return RET_ERROR; + } + auto val_offset = schema::CreateTensorListSetItem(*fbb, attr->elementDType()); + auto prim_offset = schema::CreatePrimitive(*fbb, schema::PrimitiveType_TensorListSetItem, val_offset.o); + fbb->Finish(prim_offset); + return RET_OK; +} + +PrimitiveC *TensorListSetItemCreator(const schema::Primitive *primitive) { + return PrimitiveC::NewPrimitiveC(primitive); +} +Registry TensorListSetItemRegistry(schema::PrimitiveType_TensorListSetItem, TensorListSetItemCreator); +#endif + +int TensorListSetItem::InferShape(std::vector inputs_, std::vector outputs_) { + auto input0 = reinterpret_cast(inputs_[0]); + MS_ASSERT(input0 != nullptr); + auto get_index = inputs_[1]; + MS_ASSERT(get_index != nullptr); + if (get_index->data_type() != kNumberTypeInt) { + MS_LOG(ERROR) << "inputs_[1]->data_type():" << get_index->data_type() + << " must be equal to \"kNumberTypeInt\":" << kNumberTypeInt; + return RET_ERROR; + } + if (get_index->ElementsNum() != 1) { + MS_LOG(ERROR) << "inputs_[1].ElementsNum():" << get_index->ElementsNum() << " must be equal to 1!"; + return RET_ERROR; + } + int index = reinterpret_cast(get_index->data_c())[0]; + if (index < 0 || index > (input0->ElementsNum() - 1)) { + MS_LOG(ERROR) << "index_:" << index << "must in [0, " << input0->ElementsNum() - 1 << "]"; + return RET_ERROR; + } + auto value_tensor = inputs_[2]; + MS_ASSERT(value_tensor != nullptr); + auto output0 = reinterpret_cast(outputs_[0]); + MS_ASSERT(output0 != nullptr); + output0->set_element_shape(input0->element_shape()); + output0->set_max_elements_num(input0->max_elements_num()); + output0->set_shape(input0->shape()); + output0->set_data_type(input0->data_type()); + std::vector > out_shape; + for (int i = 0; i < input0->ElementsNum(); ++i) { + auto src_ptr = input0->GetTensorIndex(i); + if (src_ptr == nullptr) { + MS_LOG(ERROR) << "input0->tensors_[" << i << "] is nullptr!"; + return RET_ERROR; + } + if (src_ptr->data_type() != kTypeUnknown) { + out_shape.push_back(src_ptr->shape()); + } else { + out_shape.push_back(std::vector()); + } + } + out_shape[index] = value_tensor->shape(); + output0->MallocTensorListData(input0->tensors_data_type(), out_shape); + return RET_OK; +} +} // namespace lite +} // namespace mindspore diff --git a/mindspore/lite/src/ops/tensorlistsetitem.h b/mindspore/lite/src/ops/tensorlistsetitem.h new file mode 100644 index 0000000000..7df2e06e75 --- /dev/null +++ b/mindspore/lite/src/ops/tensorlistsetitem.h @@ -0,0 +1,43 @@ +/** + * Copyright 2020 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include "src/ops/primitive_c.h" +#include "src/tensorlist.h" +#include "ir/dtype/type_id.h" + +#ifndef LITE_MINDSPORE_LITE_C_OPS_TENSORLISTSETITEM_H_ +#define LITE_MINDSPORE_LITE_C_OPS_TENSORLISTSETITEM_H_ +namespace mindspore { +namespace lite { +class TensorListSetItem : public PrimitiveC { + public: + TensorListSetItem() = default; + ~TensorListSetItem() = default; +#ifdef PRIMITIVE_WRITEABLE + MS_DECLARE_PARENT(TensorListSetItem, PrimitiveC); + void SetElementDType(int type); + explicit TensorListSetItem(schema::PrimitiveT *primitive) : PrimitiveC(primitive) {} + int UnPackAttr(const Primitive &prim, const std::vector &inputs) override; +#else + int UnPackToFlatBuilder(const schema::Primitive *primitive, flatbuffers::FlatBufferBuilder *fbb) override; +#endif + TypeId GetElementDType() const; + int InferShape(std::vector inputs_, std::vector outputs_) override; +}; +} // namespace lite +} // namespace mindspore + +#endif // LITE_MINDSPORE_LITE_C_OPS_TENSORLISTSETITEM_H_ diff --git a/mindspore/lite/src/ops/tensorliststack.cc b/mindspore/lite/src/ops/tensorliststack.cc new file mode 100644 index 0000000000..db6a3e91e8 --- /dev/null +++ b/mindspore/lite/src/ops/tensorliststack.cc @@ -0,0 +1,188 @@ +/** + * Copyright 2020 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include "src/ops/tensorliststack.h" + +#ifndef PRIMITIVE_WRITEABLE +#include "src/ops/ops_register.h" +#endif + +namespace mindspore { +namespace lite { +#ifdef PRIMITIVE_WRITEABLE +TypeId TensorListStack::GetElementDType() const { + return (TypeId)(this->primitive_->value.AsTensorListStack()->elementDType); +} + +int TensorListStack::GetNumElements() const { return this->primitive_->value.AsTensorListStack()->numElements; } + +void TensorListStack::SetElementDType(int type) { this->primitive_->value.AsTensorListStack()->elementDType = type; } + +void TensorListStack::SetNumElements(int num_elements) { + this->primitive_->value.AsTensorListStack()->numElements = num_elements; +} + +int TensorListStack::UnPackAttr(const Primitive &prim, const std::vector &inputs) { + if (this->primitive_ == nullptr) { + this->primitive_ = new (std::nothrow) schema::PrimitiveT; + if (this->primitive_ == nullptr) { + MS_LOG(ERROR) << "new primitiveT failed"; + return RET_ERROR; + } + this->primitive_->value.type = schema::PrimitiveType_TensorListStack; + } + if (this->primitive_->value.type != schema::PrimitiveType_TensorListStack) { + MS_LOG(ERROR) << "Primitive type is error :" << this->primitive_->value.type; + delete this->primitive_; + this->primitive_ = nullptr; + return RET_ERROR; + } + if (this->primitive_->value.value == nullptr) { + auto attr = new (std::nothrow) schema::TensorListStackT(); + if (attr == nullptr) { + delete this->primitive_; + this->primitive_ = nullptr; + MS_LOG(ERROR) << "new TensorListStackT value failed"; + return RET_ERROR; + } + if (prim.GetAttr("elementDType") == nullptr) { + delete this->primitive_; + this->primitive_ = nullptr; + delete attr; + MS_LOG(ERROR) << "TensorListStack's attr elementDType is not set"; + return RET_ERROR; + } else { + attr->elementDType = CastToInt(prim.GetAttr("elementDType")).front(); + } + if (prim.GetAttr("numElements") == nullptr) { + delete this->primitive_; + this->primitive_ = nullptr; + delete attr; + MS_LOG(ERROR) << "TensorListStack's attr numElements is not set"; + return RET_ERROR; + } else { + attr->numElements = CastToInt(prim.GetAttr("numElements")).front(); + } + this->primitive_->value.value = attr; + } + return RET_OK; +} +#else +TypeId TensorListStack::GetElementDType() const { + return (TypeId)(this->primitive_->value_as_TensorListStack()->elementDType()); +} + +int TensorListStack::GetNumElements() const { return this->primitive_->value_as_TensorListStack()->numElements(); } + +int TensorListStack::UnPackToFlatBuilder(const schema::Primitive *primitive, flatbuffers::FlatBufferBuilder *fbb) { + MS_ASSERT(nullptr != primitive); + MS_ASSERT(nullptr != fbb); + auto attr = primitive->value_as_TensorListStack(); + if (attr == nullptr) { + MS_LOG(ERROR) << "value_as_TensorListStack return nullptr"; + return RET_ERROR; + } + auto val_offset = schema::CreateTensorListStack(*fbb, attr->elementDType(), attr->numElements()); + auto prim_offset = schema::CreatePrimitive(*fbb, schema::PrimitiveType_TensorListStack, val_offset.o); + fbb->Finish(prim_offset); + return RET_OK; +} + +PrimitiveC *TensorListStackCreator(const schema::Primitive *primitive) { + return PrimitiveC::NewPrimitiveC(primitive); +} +Registry TensorListStackRegistry(schema::PrimitiveType_TensorListStack, TensorListStackCreator); +#endif + +bool TensorListStack::IsFullyDefined(const std::vector &shape) const { + for (size_t i = 0; i < shape.size(); ++i) { + if (shape[i] < 0) { + return false; + } + } + return true; +} + +int TensorListStack::InferShape(std::vector inputs_, std::vector outputs_) { + auto input0 = reinterpret_cast(inputs_.front()); + MS_ASSERT(input0 != nullptr); + if (input0->ElementsNum() == 0) { + MS_LOG(ERROR) << "Try to stack a empty tensorlist!"; + return RET_ERROR; + } + auto ele_shape = inputs_[1]; // element shape + MS_ASSERT(ele_shape != nullptr); + auto ele_shape_ptr = reinterpret_cast(ele_shape->data_c()); + for (int i = 0; ele_shape->ElementsNum(); ++i) { + output_shape_.push_back(ele_shape_ptr[i]); + } + + auto status = MergeShape(input0->element_shape()); + if (status == RET_ERROR) { + MS_LOG(ERROR) << "Merge element_shape is error!"; + return RET_ERROR; + } + if (!IsFullyDefined(output_shape_)) { + MS_LOG(ERROR) << "output_shape_ Is Not FullyDefined!"; + return RET_ERROR; + } + if (!IsFullyDefined(input0->element_shape())) { + for (int i = 0; i < input0->ElementsNum(); ++i) { + auto tensor_ele = input0->GetTensorIndex(i); + MS_ASSERT(tensor_ele != nullptr); + if (tensor_ele->data_type() != kTypeUnknown) { + status = MergeShape(tensor_ele->shape()); + if (status == RET_ERROR) { + MS_LOG(ERROR) << "Merge input0->tensors_[" << i << "] is error!"; + return RET_ERROR; + } + } + } + } + auto output = outputs_.front(); + MS_ASSERT(output != nullptr); + output->set_data_type(input0->tensors_data_type()); + output->set_shape(std::vector( + 1, + input0->ElementsNum() * std::accumulate(output_shape_.begin(), output_shape_.end(), 1LL, std::multiplies()))); + return RET_OK; +} + +int TensorListStack::MergeShape(const std::vector &shape) { + size_t dim0 = shape.size(); + size_t dim1 = output_shape_.size(); + if (dim1 >= unKnownRank_) { + output_shape_ = shape; + return RET_OK; + } + if (dim1 != dim0) { + MS_LOG(ERROR) << "shape.size():" << dim1 << " must be equal output_shape_.size():" << dim0; + return RET_ERROR; + } + for (size_t i = 0; i < dim0; ++i) { + int dim0_size = shape[i]; + int dim1_size = output_shape_[i]; + if (dim0_size >= 0 && dim1_size >= 0 && dim0_size != dim1_size) { + MS_LOG(ERROR) << "shape[" << i << "]:" << dim0_size << " is incompatible with output_shape_[" << i + << "]:" << dim1_size; + return RET_ERROR; + } + output_shape_[i] = dim1_size >= 0 ? dim1_size : dim0_size; + } + return RET_OK; +} +} // namespace lite +} // namespace mindspore diff --git a/mindspore/lite/src/ops/tensor_list.h b/mindspore/lite/src/ops/tensorliststack.h similarity index 52% rename from mindspore/lite/src/ops/tensor_list.h rename to mindspore/lite/src/ops/tensorliststack.h index 623df82a41..b83db1d2c7 100644 --- a/mindspore/lite/src/ops/tensor_list.h +++ b/mindspore/lite/src/ops/tensorliststack.h @@ -16,49 +16,27 @@ #include #include #include "src/ops/primitive_c.h" +#include "src/tensorlist.h" #include "ir/dtype/type_id.h" -using mindspore::schema::Format; -using mindspore::schema::Format_NC; - -#ifndef LITE_MINDSPORE_LITE_C_OPS_TENSORLISTFROMTENSOR_H_ -#define LITE_MINDSPORE_LITE_C_OPS_TENSORLISTFROMTENSOR_H_ +#ifndef LITE_MINDSPORE_LITE_C_OPS_TENSORLISTSTACK_H_ +#define LITE_MINDSPORE_LITE_C_OPS_TENSORLISTSTACK_H_ namespace mindspore { namespace lite { - -class TensorListFromTensor : public PrimitiveC { - public: - TypeId GetElementDType() const; - TypeId GetShapeType() const; - TensorListFromTensor() = default; - bool IsCompatibleShape(std::vector inputs_); - int InferShape(std::vector inputs_, std::vector outputs_) override; -}; - -class TensorListReserve : public PrimitiveC { - public: - TensorListReserve() = default; - TypeId GetElementDType() const; - int InferShape(std::vector inputs_, std::vector outputs_) override; -}; - -class TensorListGetItem : public PrimitiveC { - public: - TensorListGetItem() = default; - TypeId GetElementDType() const; - bool IsFullyDefined(const std::vector &shape) const; - int InferShape(std::vector inputs_, std::vector outputs_) override; - - private: - int index_ = -1; - TypeId element_dtype_ = kTypeUnknown; - std::vector element_shape_; -}; - class TensorListStack : public PrimitiveC { public: // tensor:input, element_dtype, num_elements(default=-1:reprent any tensor dim0), element_shape TensorListStack() = default; + ~TensorListStack() = default; +#ifdef PRIMITIVE_WRITEABLE + MS_DECLARE_PARENT(TensorListStack, PrimitiveC); + void SetElementDType(int type); + void SetNumElements(int num_elements); + explicit TensorListStack(schema::PrimitiveT *primitive) : PrimitiveC(primitive) {} + int UnPackAttr(const Primitive &prim, const std::vector &inputs) override; +#else + int UnPackToFlatBuilder(const schema::Primitive *primitive, flatbuffers::FlatBufferBuilder *fbb) override; +#endif TypeId GetElementDType() const; int GetNumElements() const; bool IsFullyDefined(const std::vector &shape) const; @@ -72,4 +50,4 @@ class TensorListStack : public PrimitiveC { } // namespace lite } // namespace mindspore -#endif // LITE_MINDSPORE_LITE_C_OPS_TENSORLISTFROMTENSOR_H_ +#endif // LITE_MINDSPORE_LITE_C_OPS_TENSORLISTSTACK_H_ diff --git a/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListFromTensor.cc b/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListFromTensor.cc index d8edd62c1f..0ab87f0699 100644 --- a/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListFromTensor.cc +++ b/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListFromTensor.cc @@ -27,63 +27,67 @@ using mindspore::schema::PrimitiveType_TensorListFromTensor; namespace mindspore::kernel { -bool TensorListFromTensorCPUKernel::IsCompatibleShape() { +int TensorListFromTensorCPUKernel::IsCompatibleShape() { if (input1_->data_type() != kNumberTypeInt) { // element_shape MS_LOG(ERROR) << "in_tensors_[1] data type is must be \"kNumberTypeInt\", but now is:" << input1_->data_type(); - return false; + return RET_ERROR; } int in1_ele_num = input1_->ElementsNum(); std::vector tensor_shape = input0_->shape(); if (static_cast(tensor_shape.size() - 1) != in1_ele_num) { - MS_LOG(ERROR) << "in_tensors_[0].shape() - 1:" << tensor_shape.size() - 1 + MS_LOG(ERROR) << "in_tensors_[0].shape().size() - 1:" << tensor_shape.size() - 1 << " must be equal in_tensors_[1].ElementsNum():" << in1_ele_num; - return false; + return RET_ERROR; } int *elements_shape = reinterpret_cast(input1_->data_c()); // element shape in tensor data for (int i = 0; i < in1_ele_num; ++i) { - const int dim0 = tensor_shape.at(i + 1); - const int dim1 = *(elements_shape + i); + int dim0 = tensor_shape[i + 1]; + int dim1 = elements_shape[i]; if (dim0 >= 0 && dim1 >= 0 && dim0 != dim1) { MS_LOG(ERROR) << "input0_->shape()[" << i + 1 << "]:" << dim0 << " is not equal input1_->data_c()[" << i << "]:" << dim1; - return false; + return RET_ERROR; } } - return true; + return RET_OK; } int TensorListFromTensorCPUKernel::Init() { - input0_ = in_tensors_.at(0); // row tensor - input1_ = in_tensors_.at(1); // element_shape tensor - output0_ = out_tensors_.at(0); - output1_ = out_tensors_.at(1); + input0_ = in_tensors_[0]; // row tensor + input1_ = in_tensors_[1]; // element_shape tensor + output0_ = out_tensors_[0]; return IsCompatibleShape(); } int TensorListFromTensorCPUKernel::ReSize() { return RET_OK; } int TensorListFromTensorCPUKernel::Run() { - int dim0 = input0_->shape().at(0); - size_t devision_dim0 = input0_->ElementsNum() / dim0; - auto out0_ptr = reinterpret_cast(output0_->MutableData()); - *out0_ptr = dim0; - *(out0_ptr + 1) = input0_->data_type(); - auto status = output1_->CopyTensorData(*input1_); - if (status == RET_ERROR) { - MS_LOG(ERROR) << "copy tensor data failed!"; + if (input0_->shape().size() == 0) { + MS_LOG(ERROR) << "input0_->shape().size():" << input0_->shape().size() << " must be greater than 0"; + } + int dim0 = input0_->shape()[0]; + if (dim0 <= 0) { + MS_LOG(ERROR) << "input0_->shape()[0]:" << dim0 << " must be greater than 0!"; return RET_ERROR; } - if (dim0 != static_cast(out_tensors_.size() - 2)) { - MS_LOG(ERROR) << "out_tensors_.size() - 2:[" << out_tensors_.size() - 2 - << "] must be equal in_tensors_[0].shape()[0]:[" << dim0 << "]"; + auto output0 = reinterpret_cast(output0_); + if (dim0 != output0->ElementsNum()) { + MS_LOG(ERROR) << "output0_->ElementsNum():" << output0->ElementsNum() << " must be equal to dim0:" << dim0; return RET_ERROR; } - auto in_ptr = reinterpret_cast(input0_); - size_t index = 0; + int devision_dim0 = input0_->ElementsNum() / dim0; + auto in_ptr = reinterpret_cast(input0_->data_c()); + // copy data from input0(tensor) to output(tensorlist) vector<*tensor> for (int i = 0; i < dim0; ++i) { - auto out_ptr = reinterpret_cast(out_tensors_.at(i + 2)->MutableData()); - memcpy(out_ptr, in_ptr + index, devision_dim0 * sizeof(float)); - index += devision_dim0; + auto out_ptr = output0->GetTensorIndex(i); + MS_ASSERT(out_ptr != nullptr); + if (out_ptr->ElementsNum() != devision_dim0) { + MS_LOG(ERROR) << "tensors_[" << i << "].ElementsNum():" << out_ptr->ElementsNum() + << " must be euqal to devision_dim0:" << devision_dim0; + return RET_ERROR; + } + memcpy(reinterpret_cast(out_ptr->MutableData()), in_ptr, devision_dim0 * sizeof(float)); + in_ptr += devision_dim0; } return RET_OK; } diff --git a/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListFromTensor.h b/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListFromTensor.h index dcd1c6f68a..4e3a5ece13 100644 --- a/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListFromTensor.h +++ b/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListFromTensor.h @@ -19,18 +19,12 @@ #include #include "src/lite_kernel.h" +#include "src/tensorlist.h" #include "schema/model_generated.h" namespace mindspore::kernel { class TensorListFromTensorCPUKernel : public LiteKernel { public: - /* - * input0:tensor - * input1:element_shape - * output0:tensorlist.size() and dty pe - * output2~n:tensor - * output1:element_shape(tensorlist shape) - */ TensorListFromTensorCPUKernel(OpParameter *parameter, const std::vector &inputs, const std::vector &outputs, const lite::InnerContext *ctx, const mindspore::lite::PrimitiveC *primitive) @@ -40,12 +34,11 @@ class TensorListFromTensorCPUKernel : public LiteKernel { int Init() override; int ReSize() override; int Run() override; - bool IsCompatibleShape(); + int IsCompatibleShape(); private: std::vector output_shape_; lite::Tensor *output0_ = nullptr; - lite::Tensor *output1_ = nullptr; lite::Tensor *input0_ = nullptr; lite::Tensor *input1_ = nullptr; }; diff --git a/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListGetItem.cc b/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListGetItem.cc index d9a8cb86c7..82e1225bda 100644 --- a/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListGetItem.cc +++ b/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListGetItem.cc @@ -29,37 +29,43 @@ using mindspore::schema::PrimitiveType_TensorListGetItem; namespace mindspore::kernel { int TensorListGetItemCPUKernel::Init() { - auto input0 = reinterpret_cast(in_tensors_.at(0)->data_c()); - size_t dim0 = *input0; - int in_dtype = *(input0 + 1); - if (dtype_ != in_dtype) { - MS_LOG(ERROR) << "op dtype:" << dtype_ << " is not equal in_tensors dtype:" << in_dtype; + auto input0 = reinterpret_cast(in_tensors_[0]); + if (dtype_ != input0->tensors_data_type()) { + MS_LOG(ERROR) << "op dtype:" << dtype_ << " is not equal in_tensors[0] dtype:" << input0->tensors_data_type(); return RET_ERROR; } - index_ = *(reinterpret_cast(in_tensors_.at(dim0 + 2)->data_c())); - if (index_ < 0) { - MS_LOG(ERROR) << "index tensor:[" << index_ << "] must be greater than or equal to 0"; + if (in_tensors_[1]->ElementsNum() != 1) { + MS_LOG(ERROR) << "in_tensors_[1]->ElementsNum():" << in_tensors_[1]->ElementsNum() << " must be equal to 1!"; return RET_ERROR; } - if (index_ > dim0) { - MS_LOG(ERROR) << "index tensor:[" << index_ << "] must be less than dim0:" << dim0; + index_ = reinterpret_cast(in_tensors_[1]->data_c())[0]; + int dim0 = input0->ElementsNum() - 1; + if (index_ < 0 || index_ > dim0) { + MS_LOG(ERROR) << "index tensor:[" << index_ << "] must be in [0, " << dim0 << "]!"; return RET_ERROR; } - index_ += 2; return RET_OK; } int TensorListGetItemCPUKernel::Run() { - if (in_tensors_.at(index_)->data_type() != kTypeUnknown) { - auto status = out_tensors_.at(0)->CopyTensorData(*in_tensors_.at(index_)); // tensorlist shape + auto input0 = reinterpret_cast(in_tensors_[0]); + auto src_ptr = input0->GetTensorIndex(index_); + MS_ASSERT(src_ptr != nullptr); + if (src_ptr->data_type() != kTypeUnknown) { + if (src_ptr->ElementsNum() != out_tensors_[0]->ElementsNum()) { + MS_LOG(ERROR) << "src_ptr->ElementsNum():" << src_ptr->ElementsNum() + << " must be equal to out_tensors_[0]->ElementsNum():" << out_tensors_[0]->ElementsNum(); + return RET_ERROR; + } + auto status = out_tensors_[0]->CopyTensorData(*src_ptr); if (status == RET_ERROR) { MS_LOG(ERROR) << "copy tensor data failed!"; return RET_ERROR; } } else { // reset 0 and dtype = dtype_ - auto out_ptr = reinterpret_cast(out_tensors_.at(0)->MutableData()); - memset(out_ptr, 0, lite::DataTypeSize(dtype_) * out_tensors_.at(0)->ElementsNum()); + // TODO(DT_VARIANT): dtype = DT_VARIANT is not handle + memset(out_tensors_[0]->MutableData(), 0, out_tensors_[0]->Size()); } return RET_OK; } diff --git a/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListGetItem.h b/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListGetItem.h index 976a9359b5..0140acee0c 100644 --- a/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListGetItem.h +++ b/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListGetItem.h @@ -19,6 +19,7 @@ #include #include "src/lite_kernel.h" +#include "src/tensorlist.h" #include "schema/model_generated.h" #include "nnacl/tensorlist_parameter.h" @@ -37,7 +38,7 @@ class TensorListGetItemCPUKernel : public LiteKernel { int Run() override; private: - size_t index_ = 0; + int index_ = 0; TypeId dtype_ = kTypeUnknown; }; } // namespace mindspore::kernel diff --git a/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListReserve.cc b/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListReserve.cc index c27038c6a5..2c958b7650 100644 --- a/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListReserve.cc +++ b/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListReserve.cc @@ -30,18 +30,8 @@ namespace mindspore::kernel { int TensorListReserveCPUKernel::Init() { return RET_OK; } int TensorListReserveCPUKernel::Run() { - auto out0_ptr = reinterpret_cast(out_tensors_.at(0)->MutableData()); // tensorlist size() and dtype - out0_ptr[0] = reinterpret_cast(in_tensors_.at(0)->data_c())[0]; // num_elements - out0_ptr[1] = element_dtype_; - auto status = out_tensors_.at(1)->CopyTensorData(*in_tensors_.at(1)); // elements_shape - if (status == RET_ERROR) { - MS_LOG(ERROR) << "copy tensor data failed!"; - return RET_ERROR; - } - if (static_cast(out_tensors_.size() - 2) != out0_ptr[0]) { - MS_LOG(ERROR) << "out_tensors_.size() - 2:" << out_tensors_.size() - 2 - << " must be equal num_elements:" << out0_ptr[0]; - } + auto output = reinterpret_cast(out_tensors_[0]); + output->set_tensors_data_type(element_dtype_); return RET_OK; } diff --git a/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListReserve.h b/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListReserve.h index a501290288..846475ccd4 100644 --- a/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListReserve.h +++ b/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListReserve.h @@ -19,6 +19,7 @@ #include #include "src/lite_kernel.h" +#include "src/tensorlist.h" #include "schema/model_generated.h" #include "nnacl/tensorlist_parameter.h" @@ -37,7 +38,7 @@ class TensorListReserveCPUKernel : public LiteKernel { int Run() override; private: - int element_dtype_ = 0; + TypeId element_dtype_ = kTypeUnknown; }; } // namespace mindspore::kernel diff --git a/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListSetItem.cc b/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListSetItem.cc new file mode 100644 index 0000000000..a842cf2b74 --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListSetItem.cc @@ -0,0 +1,122 @@ +/** + * Copyright 2020 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "include/errorcode.h" +#include "include/ms_tensor.h" +#include "src/kernel_registry.h" +#include "src/runtime/kernel/arm/fp32/TensorListSetItem.h" +#include "src/runtime/runtime_api.h" + +using mindspore::kernel::KERNEL_ARCH::kCPU; +using mindspore::lite::KernelRegistrar; +using mindspore::lite::RET_ERROR; +using mindspore::lite::RET_NULL_PTR; +using mindspore::lite::RET_OK; +using mindspore::schema::PrimitiveType_TensorListSetItem; + +namespace mindspore::kernel { + +int TensorListSetItemCPUKernel::Init() { + input0_ = reinterpret_cast(in_tensors_[0]); + if (dtype_ != input0_->data_type()) { + MS_LOG(ERROR) << "op dtype:" << dtype_ << " is not equal in_tensors[0] dtype:" << input0_->data_type(); + return RET_ERROR; + } + int dim0 = input0_->ElementsNum() - 1; + if (in_tensors_[1]->data_type() != kNumberTypeInt) { + MS_LOG(ERROR) << "in_tensors_[1]->data_type():" << in_tensors_[1]->data_type() + << " must be equal to \"kNumberTypeInt\":" << kNumberTypeInt; + return RET_ERROR; + } + if (in_tensors_[1]->ElementsNum() != 1) { + MS_LOG(ERROR) << "in_tensors_[1]->ElementsNum():" << in_tensors_[1]->ElementsNum() << " must be equal to 1!"; + return RET_ERROR; + } + index_ = reinterpret_cast(in_tensors_[1]->data_c())[0]; + if (index_ < 0 || index_ > dim0) { + MS_LOG(ERROR) << "index tensor:[" << index_ << "] must be in [0, " << dim0 << "]!"; + return RET_ERROR; + } + input2_ = in_tensors_[2]; + MS_ASSERT(input2_ != nullptr); + if (!input0_->IsCompatibleShape(input2_->shape())) { + return RET_ERROR; + } + return RET_OK; +} + +int TensorListSetItemCPUKernel::Run() { + output0_ = reinterpret_cast(out_tensors_[0]); + MS_ASSERT(output0_ != nullptr); + // copy each tensor in tensors_ + for (int i = 0; i < output0_->ElementsNum(); ++i) { + auto dst = output0_->GetTensorIndex(i); + MS_ASSERT(dst != nullptr); + auto src = input0_->GetTensorIndex(i); + if (i == index_) { + // copy input2_ data buff + src = input2_; + } + MS_ASSERT(src != nullptr); + if (src->data_type() != kTypeUnknown) { + if (src->Size() != dst->Size()) { + MS_LOG(ERROR) << "src->Size():" << src->Size() << " must be equal to dst->Size():" << dst->Size(); + return RET_ERROR; + } + auto ret = dst->CopyTensorData(*src); + if (ret != RET_OK) { + MS_LOG(ERROR) << "CopyTensorData[" << i << "] is failed!"; + return RET_ERROR; + } + } + } + return RET_OK; +} + +int TensorListSetItemCPUKernel::ReSize() { return RET_OK; } + +kernel::LiteKernel *CpuTensorListSetItemFp32KernelCreator(const std::vector &inputs, + const std::vector &outputs, + OpParameter *op_parameter, const lite::InnerContext *ctx, + const kernel::KernelKey &desc, + const mindspore::lite::PrimitiveC *primitive) { + if (op_parameter == nullptr) { + MS_LOG(ERROR) << "Input op_parameter is nullptr!"; + return nullptr; + } + if (ctx == nullptr) { + MS_LOG(ERROR) << "Input context is nullptr!"; + free(op_parameter); + return nullptr; + } + MS_ASSERT(desc.type == schema::PrimitiveType_TensorListSetItem); + auto *kernel = new (std::nothrow) TensorListSetItemCPUKernel(op_parameter, inputs, outputs, ctx, primitive); + if (kernel == nullptr) { + MS_LOG(ERROR) << "new TensorListSetItemCPUKernel fail!"; + free(op_parameter); + return nullptr; + } + auto ret = kernel->Init(); + if (ret != RET_OK) { + MS_LOG(ERROR) << "Init kernel failed! name: " << op_parameter->name_ << ", type: " + << schema::EnumNamePrimitiveType(static_cast(op_parameter->type_)); + delete kernel; + return nullptr; + } + return kernel; +} + +REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_TensorListSetItem, CpuTensorListSetItemFp32KernelCreator) +} // namespace mindspore::kernel diff --git a/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListSetItem.h b/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListSetItem.h new file mode 100644 index 0000000000..ece6a52f1d --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListSetItem.h @@ -0,0 +1,49 @@ +/** + * Copyright 2020 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_TENSORLISTSETITEM_H_ +#define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_TENSORLISTSETITEM_H_ + +#include +#include "src/lite_kernel.h" +#include "src/tensorlist.h" +#include "schema/model_generated.h" +#include "nnacl/tensorlist_parameter.h" + +namespace mindspore::kernel { +class TensorListSetItemCPUKernel : public LiteKernel { + public: + TensorListSetItemCPUKernel(OpParameter *parameter, const std::vector &inputs, + const std::vector &outputs, const lite::InnerContext *ctx, + const mindspore::lite::PrimitiveC *primitive) + : LiteKernel(parameter, inputs, outputs, ctx, primitive), + dtype_(reinterpret_cast(parameter)->element_dtype_) {} + ~TensorListSetItemCPUKernel() = default; + + int Init() override; + int ReSize() override; + int Run() override; + + private: + lite::TensorList *input0_ = nullptr; + lite::Tensor *input2_ = nullptr; + lite::TensorList *output0_ = nullptr; + int index_ = 0; + TypeId dtype_ = kTypeUnknown; +}; +} // namespace mindspore::kernel + +#endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_TENSORLISTSETITEM_H_ diff --git a/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListStack.cc b/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListStack.cc index 9ee603a656..742473e811 100644 --- a/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListStack.cc +++ b/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListStack.cc @@ -13,6 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#include #include #include "include/errorcode.h" #include "ir/dtype/type_id.h" @@ -29,58 +31,139 @@ using mindspore::schema::PrimitiveType_TensorListStack; namespace mindspore::kernel { int TensorListStackCPUKernel::CheckParam() { - auto in0_dtype = in_tensors_.at(0)->data_type(); - if (in0_dtype != kNumberTypeInt) { - MS_LOG(ERROR) << "in_tensors_[0]->data_type():" << in0_dtype - << " must be equal \"kNumberTypeInt\":" << kNumberTypeInt; - } - auto in0_ptr = reinterpret_cast(in_tensors_.at(0)->data_c()); - if (in0_ptr[1] != dtype_) { - MS_LOG(ERROR) << "in_tensors_[0].data_type:[" << in0_ptr[1] << "] must be equal " + if (input0_->tensors_data_type() != dtype_) { + MS_LOG(ERROR) << "in_tensors_[0].tensors_data_type:[" << input0_->tensors_data_type() << "] must be equal " << "param.data_type:[" << dtype_ << "]"; return RET_ERROR; } - if (num_element_ != -1 && in0_ptr[0] != num_element_) { - MS_LOG(ERROR) << "in_tensors_[0].dim0:[" << in0_ptr[0] << "] must be equal " + if (num_element_ != -1 && input0_->ElementsNum() != num_element_) { + MS_LOG(ERROR) << "in_tensors_[0].ElementsNum():[" << input0_->ElementsNum() << "] must be equal " << "param.elements_num:[" << num_element_ << "]"; return RET_ERROR; } - num_element_ = in0_ptr[0]; + num_element_ = input0_->ElementsNum(); return RET_OK; } int TensorListStackCPUKernel::Init() { - output0_ = out_tensors_.at(0); - if (output0_->format() != schema::Format_NC) { // shape().size() = 2 - MS_LOG(ERROR) << "out_tensor_[0] format must be \"Format:NC\", but now is:" << output0_->format(); + input0_ = reinterpret_cast(in_tensors_[0]); + MS_ASSERT(input0_ != nullptr); + output0_ = out_tensors_[0]; + MS_ASSERT(output0_ != nullptr); + if (output0_->shape().size() != 2) { + MS_LOG(ERROR) << "out_tensors_[0].shape().size():" << output0_->shape().size() << " must be equal to 2!"; return RET_ERROR; } - int dim0 = output0_->shape().at(0); + int dim0 = output0_->shape()[0]; if (dim0 != 1) { // dim0 must be 1 - MS_LOG(ERROR) << "out_tensor_[0] dim0 must be 1, but now is:" << dim0; + MS_LOG(ERROR) << "out_tensors_[0].shape()[0] must be 1, but now is:" << dim0; return RET_ERROR; } return CheckParam(); } +bool TensorListStackCPUKernel::IsFullyDefined(const std::vector &shape) const { + for (size_t i = 0; i < shape.size(); ++i) { + if (shape[i] < 0) { + return false; + } + } + return true; +} + +int TensorListStackCPUKernel::MergeElementShape() { + MS_ASSERT(in_tensors_[1]); + if (in_tensors_[1]->data_type() != kNumberTypeInt) { + MS_LOG(ERROR) << "in_tensors_[1]->data_type():" << in_tensors_[1]->data_type() + << " must be \"kNumberTypeInt\":" << kNumberTypeInt; + return RET_ERROR; + } + auto ele_shape_data = reinterpret_cast(in_tensors_[1]->data_c()); + for (int i = 0; i < in_tensors_[1]->ElementsNum(); ++i) { + output_shape_.push_back(ele_shape_data[i]); + } + auto status = MergeSubShape(input0_->element_shape()); + if (status == RET_ERROR) { + MS_LOG(ERROR) << "Merge element_shape is error!"; + return RET_ERROR; + } + + if (!IsFullyDefined(output_shape_)) { + MS_LOG(ERROR) << "output_shape_ Is Not FullyDefined!"; + return RET_ERROR; + } + if (!IsFullyDefined(input0_->element_shape())) { + for (int i = 0; i < input0_->ElementsNum(); ++i) { // get tensorlist every tensor + auto tensor_ele = input0_->GetTensorIndex(i); + MS_ASSERT(tensor_ele != nullptr); + if (tensor_ele->data_type() != kTypeUnknown) { + status = MergeSubShape(tensor_ele->shape()); + if (status == RET_ERROR) { + MS_LOG(ERROR) << "Merge tensors_[" << i << "] is error!"; + return RET_ERROR; + } + } + } + } + TypeUnknownSize = std::accumulate(output_shape_.begin(), output_shape_.end(), 1LL, std::multiplies()); + return RET_OK; +} + +int TensorListStackCPUKernel::MergeSubShape(const std::vector &shape) { + size_t dim0 = shape.size(); + size_t dim1 = output_shape_.size(); + if (dim1 != dim0) { + MS_LOG(ERROR) << "shape.size():" << dim1 << " must be equal output_shape_.size():" << dim0; + return RET_ERROR; + } + for (size_t i = 0; i < dim0; ++i) { + int dim0_size = shape[i]; + int dim1_size = output_shape_[i]; + if (dim0_size >= 0 && dim1_size >= 0 && dim0_size != dim1_size) { + MS_LOG(ERROR) << "shape[" << i << "]:" << dim0_size << " is incompatible with output_shape_[" << i + << "]:" << dim1_size; + return RET_ERROR; + } + output_shape_[i] = dim1_size >= 0 ? dim1_size : dim0_size; + } + return RET_OK; +} + int TensorListStackCPUKernel::Run() { + if (output0_->ElementsNum() == 0) { + return RET_OK; + } size_t in_ele_num = 0; for (int i = 0; i < num_element_; ++i) { - in_ele_num += in_tensors_.at(i + 2)->ElementsNum(); + auto tensor = input0_->GetTensorIndex(i); + MS_ASSERT(tensor != nullptr); + if (tensor->data_type() == kTypeUnknown) { + if (TypeUnknownSize == 0) { + TypeUnknownSize = MergeElementShape(); + } + in_ele_num += TypeUnknownSize; + } else { + in_ele_num += std::accumulate(tensor->shape().begin(), tensor->shape().end(), 1LL, std::multiplies()); + } } - size_t out_ele_num = out_tensors_.at(0)->ElementsNum(); + size_t out_ele_num = output0_->ElementsNum(); if (in_ele_num > out_ele_num) { - MS_LOG(ERROR) << "out_tensors_[0]->ElementsNum():" << out_ele_num << "must greater than or equal to in_ele_num" - << in_ele_num; + MS_LOG(ERROR) << "out_tensors_[0]->ElementsNum():" << out_ele_num + << "must be greater than or equal to in_ele_num:" << in_ele_num; return RET_ERROR; } - size_t index = 0; - auto out_ptr = reinterpret_cast(out_tensors_.at(0)->MutableData()); + auto out_ptr = reinterpret_cast(output0_->MutableData()); for (int i = 0; i < num_element_; ++i) { - auto in_ptr = reinterpret_cast(in_tensors_.at(i + 2)->data_c()); - size_t in_size = in_tensors_.at(i + 2)->ElementsNum(); - memcpy(out_ptr + index, in_ptr, in_size * sizeof(float)); - index += in_size; + auto in_ptr = input0_->GetTensorIndex(i); + MS_ASSERT(in_ptr != nullptr); + if (in_ptr->data_type() != kTypeUnknown) { + int in_size = in_ptr->ElementsNum(); + memcpy(out_ptr, in_ptr->data_c(), in_size * sizeof(float)); + out_ptr += in_size; + } else { + memset(out_ptr, 0, TypeUnknownSize * sizeof(float)); + out_ptr += TypeUnknownSize; + } } return RET_OK; } diff --git a/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListStack.h b/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListStack.h index 09da76ea6e..08fa4e21cb 100644 --- a/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListStack.h +++ b/mindspore/lite/src/runtime/kernel/arm/fp32/TensorListStack.h @@ -18,7 +18,9 @@ #define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_TENSORLISTSTACK_H_ #include + #include "src/lite_kernel.h" +#include "src/tensorlist.h" #include "schema/model_generated.h" #include "nnacl/tensorlist_parameter.h" @@ -37,11 +39,17 @@ class TensorListStackCPUKernel : public LiteKernel { int ReSize() override; int Run() override; int CheckParam(); + int MergeElementShape(); + int MergeSubShape(const std::vector &shape); + bool IsFullyDefined(const std::vector &shape) const; private: + size_t TypeUnknownSize = 0; int num_element_ = -1; TypeId dtype_ = kTypeUnknown; + lite::TensorList *input0_ = nullptr; lite::Tensor *output0_ = nullptr; + std::vector output_shape_; }; } // namespace mindspore::kernel diff --git a/mindspore/lite/src/tensor.h b/mindspore/lite/src/tensor.h index b0cdd42f29..b97bd3c9d7 100644 --- a/mindspore/lite/src/tensor.h +++ b/mindspore/lite/src/tensor.h @@ -92,15 +92,15 @@ class Tensor : public mindspore::tensor::MSTensor { mindspore::lite::Allocator *allocator() const { return this->allocator_; } - int MallocData(const mindspore::lite::Allocator *allocator = nullptr); + virtual int MallocData(const mindspore::lite::Allocator *allocator = nullptr); - int FreeData(); + virtual int FreeData(); void *MutableData() override; - void *data_c() const { return data_; } + virtual void *data_c() const { return data_; } - void set_data(void *data) { this->data_ = data; } + virtual void set_data(void *data) { this->data_ = data; } Category category() { return this->category_; } @@ -189,6 +189,8 @@ inline size_t DataTypeSize(const TypeId type) { return sizeof(bool); case kObjectTypeString: return sizeof(char); + case kObjectTypeTensorType: + return 0; default: MS_LOG(ERROR) << "Not support the type: " << type; return 0; diff --git a/mindspore/lite/src/tensorlist.cc b/mindspore/lite/src/tensorlist.cc new file mode 100644 index 0000000000..e1c8a968e9 --- /dev/null +++ b/mindspore/lite/src/tensorlist.cc @@ -0,0 +1,245 @@ +/** + * Copyright 2020 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "include/ms_tensor.h" + +#include "src/common/log_adapter.h" +#include "schema/model_generated.h" +#include "src/tensor.h" +#include "src/tensorlist.h" + +namespace mindspore { +namespace lite { + +TensorList::TensorList(std::vector shape, std::vector element_shape) + : Tensor(kObjectTypeTensorType, shape), element_shape_(element_shape) {} + +TensorList::~TensorList() { + if (!this->tensors_.empty()) { + this->FreeData(); + this->FreeTensorListData(); + } +} + +TensorList &TensorList::operator=(const TensorList &src) { + if (&src == this) { + return *this; + } + auto ret = CopyTensorList(src, true); + if (ret == RET_ERROR) { + MS_LOG(ERROR) << "CopyTensorList error!"; + MS_ASSERT(false); + } + return *this; +} + +int TensorList::CopyTensorList(const TensorList &src, bool copy_data) { + this->data_type_ = src.data_type_; + this->tensors_data_type_ = src.tensors_data_type_; + this->shape_ = src.shape_; + this->element_shape_ = src.element_shape_; + this->max_elements_num_ = src.max_elements_num_; + if (copy_data) { + auto ret = CopyTensorData(src); + if (ret != RET_OK) { + MS_LOG(ERROR) << "CopyTensorData error"; + return RET_ERROR; + } + } else { + // each tensor in tensors_ will share the same memory space. + this->tensors_ = src.tensors_; + } + return RET_OK; +} + +int TensorList::CopyTensorData(const TensorList &src) { + for (int i = 0; i < this->ElementsNum(); ++i) { + if (src.tensors_[i] == nullptr) { + MS_LOG(ERROR) << "src tensors_[" << i << "] is nullptr!"; + return RET_ERROR; + } + auto dst_tensor = new (std::nothrow) Tensor; + if (dst_tensor == nullptr) { + MS_LOG(ERROR) << "CopyTensorData: new tensor[" << i << "] is failed!"; + return RET_ERROR; + } + *reinterpret_cast(dst_tensor) = *src.tensors_[i]; + this->tensors_.push_back(dst_tensor); + } + return RET_OK; +} + +int TensorList::MallocTensorListData(TypeId dtype, const std::vector > &tensor_shape) { + // This function will create a new tensors_ + // Your must to set shape(param2: tensor_shape) and data_type_(tensors_data_type_ = param1: dtype) of each tensor in + // tensors_. After that, you need to call function:MallocData to malloc data buf of each tensor in tensors_. + if (!this->tensors_.empty()) { + // If tensors_ is not empty then clear this tensors_ and rebuild a new tensors_. + auto ret = FreeTensorListData(); + if (ret != RET_OK) { + return RET_ERROR; + } + } + if (this->shape().size() != 1) { + MS_LOG(ERROR) << "tensorlist shape:" << this->shape().size() << " must be one-dimensional"; + return RET_ERROR; + } + if (static_cast(this->ElementsNum()) != tensor_shape.size()) { + MS_LOG(ERROR) << "tensorlist ElementsNum():" << this->ElementsNum() + << " must be equal to param2:tensor_shape.size():" << tensor_shape.size(); + return RET_ERROR; + } + this->tensors_data_type_ = dtype; + for (int i = 0; i < this->ElementsNum(); ++i) { + auto tensor_ptr = new (std::nothrow) Tensor(dtype, tensor_shape[i]); + if (tensor_ptr == nullptr) { + MS_LOG(ERROR) << "new tensors_[" << i << "] is failed!"; + return RET_ERROR; + } + this->tensors_.push_back(tensor_ptr); + } + return RET_OK; +} + +int TensorList::MallocData(const mindspore::lite::Allocator *allocator) { + // malloc data buf of each tensor in tensors_ + for (int i = 0; i < this->ElementsNum(); ++i) { + auto tensor_ptr = this->tensors_[i]; + if (tensor_ptr == nullptr) { + MS_LOG(ERROR) << "tensors_[" << i << "] is nullptr!"; + return RET_ERROR; + } + // if data_type() is kTypeUnknown then data buf will not to be malloc + if (tensor_ptr->data_type() != kTypeUnknown) { + auto ret = tensor_ptr->MallocData(this->allocator_); + if (ret != RET_OK) { + MS_LOG(ERROR) << "tensorlist malloc tensors_[:" << i << "] is failed!"; + return RET_ERROR; + } + } + } + return RET_OK; +} + +int TensorList::FreeData() { + // free data buf of each tensor in tensors_ + if (this->tensors_.empty()) { + return RET_OK; + } + for (int i = 0; i < this->ElementsNum(); ++i) { + if (this->tensors_[i] != nullptr) { + this->tensors_[i]->FreeData(); + } + } + return RET_OK; +} + +int TensorList::FreeTensorListData() { + // del each tensor in tensors_ and clear tensors_ + if (this->tensors_.empty()) { + return RET_OK; + } + for (int i = 0; i < this->ElementsNum(); ++i) { + if (this->tensors_[i] != nullptr) { + delete this->tensors_[i]; + this->tensors_[i] = nullptr; + } + } + tensors_.clear(); + return RET_OK; +} + +int TensorList::SetTensorIndex(int index, Tensor *src_tensor) { + // your can use this fun to modify tensor[index] value + if (src_tensor->data_type() != this->tensors_data_type_) { + MS_LOG(ERROR) << "src_tensor->data_type():" << src_tensor->data_type() + << " must be equal to tensors_data_type_:" << this->tensors_data_type_; + return RET_ERROR; + } + if (index < 0 || index > (this->ElementsNum() - 1)) { + MS_LOG(ERROR) << "index:" << index << " must in [0, " << this->ElementsNum() - 1 << "]!"; + return RET_ERROR; + } + auto dst_tensor = this->tensors_[index]; + if (dst_tensor != nullptr) { // free original tensor data + delete dst_tensor; + } + this->tensors_[index] = new (std::nothrow) Tensor; + if (this->tensors_[index] == nullptr) { + MS_LOG(ERROR) << "SetTensorIndex: new tensor is failed!"; + return RET_ERROR; + } + *this->tensors_[index] = *src_tensor; + return RET_OK; +} + +int TensorList::CheckTensorListParam() { + for (int i = 0; i < this->ElementsNum(); ++i) { + // each tensor in tensorlist must be not nullptr + if (this->tensors_[i] == nullptr) { + MS_LOG(ERROR) << "CheckTensorListParam: tensors_[" << i << "] is nullptr"; + return RET_ERROR; + } + if (this->tensors_[i]->data_type() != this->tensors_data_type_) { + MS_LOG(ERROR) << "CheckTensorListParam: tensors_[i] data_type:" << this->tensors_[i]->data_type() + << " is not equal to tensors_data_type_:" << this->tensors_data_type_; + return RET_ERROR; + } + } + return RET_OK; +} + +Tensor *TensorList::GetTensorIndex(int index) { + // return tensor[index] ptr. With this function, you can modify tensors_[index] at will. + if (index < 0 || index > (this->ElementsNum() - 1)) { + MS_LOG(ERROR) << "index:" << index << " must in [0, " << this->ElementsNum() - 1 << "]!"; + return nullptr; + } + return this->tensors_[index]; +} + +bool TensorList::IsCompatibleShape(const std::vector &shape) { + if (shape.size() != this->element_shape_.size()) { + return false; + } + for (size_t i = 0; i < shape.size(); ++i) { + if (this->element_shape_[i] >= 0 && shape[i] >= 0 && this->element_shape_[i] != shape[i]) { + return false; + } + } + return true; +} + +bool TensorList::IsCompatibleShape(const Tensor *src) { + // shape is store in Tensor. + if (static_cast(src->ElementsNum()) != this->element_shape_.size()) { + return false; + } + if (src->data_type() != kNumberTypeInt) { + MS_LOG(ERROR) << "src tensor data_type:" << src->data_type() + << " must be equal to \"kNumberTypeInt\":" << kNumberTypeInt; + return false; + } + auto src_ptr = reinterpret_cast(src->data_c()); + for (size_t i = 0; i < this->element_shape_.size(); ++i) { + if (this->element_shape_[i] >= 0 && src_ptr[i] >= 0 && this->element_shape_[i] != src_ptr[i]) { + return false; + } + } + return true; +} +} // namespace lite +} // namespace mindspore diff --git a/mindspore/lite/src/tensorlist.h b/mindspore/lite/src/tensorlist.h new file mode 100644 index 0000000000..f810ff6613 --- /dev/null +++ b/mindspore/lite/src/tensorlist.h @@ -0,0 +1,129 @@ +/** + * Copyright 2020 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MINDSPORE_LITE_SRC_TENSORLIST_H_ +#define MINDSPORE_LITE_SRC_TENSORLIST_H_ + +#include +#include +#include "include/ms_tensor.h" +#include "include/errorcode.h" +#include "src/common/log_adapter.h" +#include "schema/model_generated.h" +#include "src/tensor.h" + +namespace mindspore { +namespace lite { +/** + * Tensorlist is a container of vector, in which each element is a tensor object. + * Member objects: + * 1.tensors_: tensors_ is a vector, where each element is a pointer to tensor type. + * 2.shape_: represents the size of the tensors_ and shape_.size() must be equal to 1. + * 3.element_shape_: element_shape_ represents the shape of each tensor in tensors_. + * Some dimensions can be negative, which means that the corresponding dimensions of each tensor in tensors_ can be + * different. + * 4.data_type_: indicates that the tensorlist is a tensor of type kObjectTypeTensorType, so it can only be + * "kObjectTypeTensorType" + * 5.tensors_data_type_: data_type_ of each tensor in tensors_ + * Usage: + * std::vector shape = (1, 2); // tensors_ only has two tensor + * std::vector element_shape = {-1, 99}; + * // dim0 is arbitrary and dim1 is must to be 99 of each tensor.shape() in tensors_ + * TensorList *tl = new TensorList(shape, element_shape); + * std::vector > tensor_shape = std::vector > (2, + * (std::vector {5, 99}, + * std::vector {1, 99})); + * // tensor_shape[0] and tensor_shape[1] is not equal in dim0, but dim1 is must be equal to 99. + * t1->MallocTensorListData(kNumberTypeFloat, tensor_shape); + * t1->MallocData(); + * t1->... + * ... + * t1->FreeData(); + * t1->FreeTensorListData(); + * + * See the code for other constructors. + */ +class TensorList : public Tensor { + public: + TensorList() = default; + + ~TensorList() override; + + // **Note**: This is a shallow copy, src and dst tensorlist share one memory space of each tensor in tensors_ + // If your want to not share one memory space please use "operator=" + TensorList(const TensorList &other) + : Tensor(other.data_type_, other.shape()), + tensors_(other.tensors_), + tensors_data_type_(other.tensors_data_type_), + element_shape_(other.element_shape_), + max_elements_num_(other.max_elements_num_) {} + + // tensorlist deep copy memory + TensorList &operator=(const TensorList &tl); + + TensorList(std::vector shape, std::vector element_shape); + + void set_element_shape(const std::vector &shape) { element_shape_ = shape; } + + std::vector &element_shape() { return element_shape_; } + + void set_max_elements_num(int ele_num) { max_elements_num_ = ele_num; } + + int max_elements_num() const { return max_elements_num_; } + + int MallocTensorListData(TypeId dtype, const std::vector > &tensor_shape); + + int MallocData(const mindspore::lite::Allocator *allocator = nullptr) override; + + int FreeTensorListData(); + + int FreeData() override; + + int CopyTensorList(const TensorList &src, bool copy_data); + + int CopyTensorData(const TensorList &src); + + int SetTensorIndex(int index, Tensor *); + + Tensor *GetTensorIndex(int index); + + void set_tensors_data_type(TypeId type) { tensors_data_type_ = type; } + + TypeId tensors_data_type() const { return tensors_data_type_; } + + std::vector &tensors() { return tensors_; } + + int CheckTensorListParam(); + + bool IsCompatibleShape(const std::vector &shape); + + bool IsCompatibleShape(const Tensor *src); + + protected: + // The following functions must be masked. + void set_data(void *data) override { return; } + void *data_c() const override { return nullptr; } + void *MutableData() override { return nullptr; } + size_t Size() const override { return 0; } + std::vector tensors_; + TypeId tensors_data_type_; + std::vector element_shape_; + int max_elements_num_ = -1; +}; +} // namespace lite +} // namespace mindspore + +#endif // MINDSPORE_LITE_SRC_TENSORLIST_H_ diff --git a/mindspore/lite/test/CMakeLists.txt b/mindspore/lite/test/CMakeLists.txt index 4472c49d0a..0f070bd21e 100644 --- a/mindspore/lite/test/CMakeLists.txt +++ b/mindspore/lite/test/CMakeLists.txt @@ -122,6 +122,7 @@ set(TEST_LITE_SRC ${LITE_DIR}/src/runtime/thread_pool.c ${LITE_DIR}/src/runtime/parallel_executor.cc ${LITE_DIR}/src/tensor.cc + ${LITE_DIR}/src/tensorlist.cc ${LITE_DIR}/src/executor.cc ${LITE_DIR}/src/inner_context.cc ${LITE_DIR}/src/kernel_registry.cc diff --git a/mindspore/lite/tools/converter/CMakeLists.txt b/mindspore/lite/tools/converter/CMakeLists.txt index 6ba901da03..279c5c9719 100644 --- a/mindspore/lite/tools/converter/CMakeLists.txt +++ b/mindspore/lite/tools/converter/CMakeLists.txt @@ -79,6 +79,7 @@ set(LITE_SRC ${SRC_DIR}/runtime/thread_pool.c ${SRC_DIR}/inner_context.cc ${SRC_DIR}/tensor.cc + ${SRC_DIR}/tensorlist.cc ${SRC_DIR}/kernel_registry.cc ${SRC_DIR}/lite_kernel.cc ${SRC_DIR}/scheduler.cc