!45751 [lite]optimize inferShape

Merge pull request !45751 from 徐安越/r1.8_1
This commit is contained in:
i-robot 2022-11-22 06:11:52 +00:00 committed by Gitee
commit 4b98342ca1
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
33 changed files with 540 additions and 486 deletions

View File

@ -41,7 +41,7 @@ int TensorListGetItemInferShape(const TensorC *const *inputs, size_t inputs_size
if (index < 0 || index > ((int)(input0->element_num_ - 1))) {
return NNACL_ERR;
}
TensorC *tensor_index = &input0->tensors_[index];
TensorC *tensor_index = input0->tensors_[index];
NNACL_CHECK_NULL_RETURN_ERR(tensor_index);
if (tensor_index->data_type_ != kTypeUnknown) {
@ -49,7 +49,7 @@ int TensorListGetItemInferShape(const TensorC *const *inputs, size_t inputs_size
} else {
output->data_type_ = input0->tensors_data_type_;
}
output->format_ = input0->tensors_[index].format_;
output->format_ = input0->tensors_[index]->format_;
if (!InferFlag(inputs, inputs_size)) {
return NNACL_INFER_INVALID;
@ -75,7 +75,7 @@ int TensorListGetItemInferShape(const TensorC *const *inputs, size_t inputs_size
}
if (!TensorListIsFullyDefined(element_shape, element_shape_size)) {
for (size_t i = 0; i < input0->element_num_; ++i) {
TensorC *input = &input0->tensors_[i];
TensorC *input = input0->tensors_[i];
NNACL_CHECK_NULL_RETURN_ERR(input);
if (input->data_type_ != kTypeUnknown) {
status = TensorListMergeShape(element_shape, &element_shape_size, input->shape_, input->shape_size_);

View File

@ -90,7 +90,7 @@ int TensorListSetItemInferShape(const TensorC *const *inputs, size_t inputs_size
} else {
output0->element_num_ = input0->element_num_;
for (size_t i = 0; i < input0->element_num_; ++i) {
TensorC *src_ptr = &input0->tensors_[i];
TensorC *src_ptr = input0->tensors_[i];
if (src_ptr == NULL) {
free(out_shape.shape_);
free(out_shape.shape_size_);

View File

@ -72,7 +72,7 @@ int TensorListStackInferShape(const TensorC *const *inputs, size_t inputs_size,
}
if (!TensorListIsFullyDefined(input0->element_shape_, input0->element_shape_size_)) {
for (size_t i = 0; i < input0->element_num_; ++i) {
TensorC *tensor_ele = &input0->tensors_[i];
TensorC *tensor_ele = input0->tensors_[i];
if (tensor_ele->data_type_ != kTypeUnknown) {
status = TensorListMergeShape(output_shape, &output_shape_size, tensor_ele->shape_, tensor_ele->shape_size_);
if (status == NNACL_ERR) {

View File

@ -73,6 +73,12 @@ int SetShape(const TensorC *const *inputs, size_t inputs_size, TensorC **outputs
int b_shape[MAX_SHAPE_SIZE] = {0};
size_t b_shape_size = 0;
ShapeSet(b_shape, &b_shape_size, input1->shape_, input1->shape_size_);
int *shape_align = a_shape_size > b_shape_size ? b_shape : a_shape;
size_t *shape_size_align = a_shape_size > b_shape_size ? &b_shape_size : &a_shape_size;
int diff = abs((int)a_shape_size - (int)b_shape_size);
for (int i = 0; i < diff; ++i) {
ShapeInsert(shape_align, shape_size_align, 0, 1);
}
int bias_shape[MAX_AXIS_SIZE] = {0};
size_t bias_shape_size = 0;
if (inputs_size == kInputSize2) {
@ -83,7 +89,6 @@ int SetShape(const TensorC *const *inputs, size_t inputs_size, TensorC **outputs
if (a_shape_size == COMM_SHAPE_SIZE && a_shape[THIRD_INPUT] == 1 && a_shape[FOURTH_INPUT] == 1) {
a_shape_size = 2;
SetShapeArray(input0, a_shape, a_shape_size);
}
bool del_start = false;
@ -93,12 +98,10 @@ int SetShape(const TensorC *const *inputs, size_t inputs_size, TensorC **outputs
if (insert_ret != NNACL_OK) {
return NNACL_ERR;
}
SetShapeArray(input0, a_shape, a_shape_size);
del_start = true;
}
if (b_shape_size == 1) {
ShapePush(b_shape, &b_shape_size, 1);
SetShapeArray(input1, b_shape, b_shape_size);
del_end = true;
}
int ret = CheckMatmulInputShape(a_shape, a_shape_size, b_shape, b_shape_size, bias_shape, bias_shape_size, param);
@ -138,11 +141,6 @@ int MatmulInferShape(const TensorC *const *inputs, size_t inputs_size, TensorC *
TensorC *input1 = (TensorC *)inputs[1];
TensorC *output = outputs[0];
int diff = abs((int)input0->shape_size_ - (int)input1->shape_size_);
TensorC *in = input0->shape_size_ > input1->shape_size_ ? input1 : input0;
for (int i = 0; i < diff; ++i) {
ShapeInsert(in->shape_, &in->shape_size_, 0, 1);
}
TensorC *input = input1->data_ == NULL ? input1 : input0; // transfer the input which comes from the other node.
SetDataTypeFormat(output, input);
if (parameter->quant_type_ == QuantType_QUANT_DYNAMIC || parameter->quant_type_ == QuantType_QUANT_WEIGHT) {

View File

@ -28,6 +28,8 @@ int ShapeFusionInferShape(const TensorC *const *inputs, size_t inputs_size, Tens
size_t input_len = in_tensor->shape_size_ + 1;
for (size_t out_idx = 0; out_idx < outputs_size; out_idx++) {
TensorC *out_tensor = outputs[out_idx];
int origin_out_size = out_tensor->data_ == NULL ? 0 : (out_tensor->shape_size_ == 0 ? 1 : out_tensor->shape_[0]);
MS_CHECK_TRUE_RET(origin_out_size >= 0, NNACL_INPUT_TENSOR_ERROR);
out_tensor->data_type_ = kNumberTypeInt32;
out_tensor->format_ = in_tensor->format_;
if (!InferFlag(inputs, inputs_size)) {
@ -44,6 +46,11 @@ int ShapeFusionInferShape(const TensorC *const *inputs, size_t inputs_size, Tens
out_tensor->shape_[0] = (int)(matrix_tensor->shape_[0]);
}
int out_size = out_tensor->shape_size_ == 0 ? 1 : out_tensor->shape_[0];
MS_CHECK_TRUE_RET(out_size >= 0, NNACL_INPUT_TENSOR_ERROR);
if (out_size != origin_out_size && out_tensor->data_ != NULL) {
free(out_tensor->data_);
out_tensor->data_ = NULL;
}
size_t matrix_data_size = input_len * out_size * sizeof(float);
float *matrix_data = (float *)(malloc(matrix_data_size));
NNACL_CHECK_NULL_RETURN_ERR(matrix_data);
@ -59,7 +66,10 @@ int ShapeFusionInferShape(const TensorC *const *inputs, size_t inputs_size, Tens
free(matrix_data);
return NNACL_ERR;
}
int *data = (int *)(malloc(out_size * sizeof(int)));
if (out_tensor->data_ == NULL) {
out_tensor->data_ = malloc(out_size * sizeof(int));
}
int *data = (int *)out_tensor->data_;
if (data == NULL) {
free(matrix_data);
return NNACL_ERR;
@ -71,7 +81,6 @@ int ShapeFusionInferShape(const TensorC *const *inputs, size_t inputs_size, Tens
}
data[i] += matrix_data[i * input_len + input_len - 1];
}
outputs[out_idx]->data_ = (void *)data;
free(matrix_data);
}
return NNACL_OK;

View File

@ -20,13 +20,11 @@
typedef enum TensorCFormat { NCHW, NHWC, NC4HW4, NUM_OF_FORMAT } TensorCFormat;
typedef struct TensorC {
bool is_ready_;
int data_type_;
int format_;
void *data_;
size_t shape_size_;
int shape_[MAX_SHAPE_SIZE];
char *name_;
} TensorC;
#endif // MINDSPORE_NNACL_TENSOR_C_H_

View File

@ -0,0 +1,40 @@
/**
* Copyright 2022 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_NNACL_TENSORLIST_C_H_
#define MINDSPORE_NNACL_TENSORLIST_C_H_
#include "nnacl/tensor_c.h"
typedef struct vvector {
int **shape_; // value of shapes
int *shape_size_; // size of shape
size_t size_; // number of shapes
} vvector;
typedef struct TensorListC {
int data_type_;
int format_;
int shape_value_;
int tensors_data_type_; // element_data_type_, keep same as c++
int max_elements_num_;
TensorC **tensors_;
size_t element_num_;
size_t element_shape_size_;
int element_shape_[MAX_SHAPE_SIZE];
} TensorListC;
#endif // MINDSPORE_NNACL_TENSORLIST_C_H_

View File

@ -28,16 +28,21 @@ int MallocTensorListData(TensorListC *tensor_list, TypeIdC dtype, const vvector
return NNACL_ERR;
}
tensor_list->tensors_data_type_ = dtype;
tensor_list->tensors_ = (TensorC *)malloc(tensor_list->element_num_ * sizeof(TensorC)); // free in infer_manager
if (tensor_list->tensors_ == NULL) {
void *addr = malloc(tensor_list->element_num_ * sizeof(void *) +
tensor_list->element_num_ * sizeof(TensorC)); // free in infer_manager
if (addr == NULL) {
free(tensor_list->tensors_);
return NNACL_NULL_PTR;
}
memset(tensor_list->tensors_, 0, tensor_list->element_num_ * sizeof(TensorC));
memset(addr, 0, tensor_list->element_num_ * sizeof(void *) + tensor_list->element_num_ * sizeof(TensorC));
tensor_list->tensors_ = (TensorC **)addr;
TensorC *tensors = (TensorC *)(tensor_list->tensors_ + tensor_list->element_num_);
for (size_t i = 0; i < tensor_list->element_num_; ++i) {
tensor_list->tensors_[i].format_ = Format_NHWC;
tensor_list->tensors_[i].data_type_ = dtype;
ShapeSet(tensor_list->tensors_[i].shape_, &(tensor_list->tensors_[i].shape_size_), tensor_shape->shape_[i],
(size_t)tensor_shape->shape_size_[i]);
TensorC *tensor = tensors + i;
tensor_list->tensors_[i] = tensor;
tensor->format_ = Format_NHWC;
tensor->data_type_ = dtype;
ShapeSet(tensor->shape_, &(tensor->shape_size_), tensor_shape->shape_[i], (size_t)tensor_shape->shape_size_[i]);
}
return NNACL_OK;
}

View File

@ -14,38 +14,19 @@
* limitations under the License.
*/
#ifndef MINDSPORE_NNACL_TENSORLISTC_UTILS_H_
#define MINDSPORE_NNACL_TENSORLISTC_UTILS_H_
#ifndef MINDSPORE_NNACL_TENSORLIST_C_UTILS_H_
#define MINDSPORE_NNACL_TENSORLIST_C_UTILS_H_
#include <stddef.h>
#include "nnacl/errorcode.h"
#include "nnacl/op_base.h"
#include "nnacl/tensor_c.h"
#include "nnacl/tensorlist_c.h"
#include "nnacl/infer/common_infer.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct vvector {
int **shape_; // value of shapes
int *shape_size_; // size of shape
size_t size_; // number of shapes
} vvector;
typedef struct TensorListC {
bool is_ready_;
int data_type_;
int format_;
int shape_value_;
int tensors_data_type_; // element_data_type_, keep same as c++
int max_elements_num_;
int element_shape_[8];
size_t element_num_;
size_t element_shape_size_;
TensorC *tensors_;
} TensorListC;
int MallocTensorListData(TensorListC *tensor_list, TypeIdC dtype, const vvector *tensor_shape);
int TensorListMergeShape(int *element_shape, size_t *element_shape_size, const int *tmp, size_t tmp_size);
bool TensorListIsFullyDefined(const int *shape, size_t shape_size);
@ -55,4 +36,4 @@ bool InferFlagTensorList(TensorC *tensor_list);
}
#endif
#endif // MINDSPORE_NNACL_TENSORLISTC_UTILS_H_
#endif // MINDSPORE_NNACL_TENSORLIST_C_UTILS_H_

View File

@ -107,6 +107,7 @@ if(MSLITE_MINDDATA_IMPLEMENT STREQUAL "full")
include_directories("${MINDDATA_DIR}/kernels/image")
include_directories("${MINDDATA_DIR}/liteapi")
include_directories("${TOP_DIR}")
include_directories("${TOP_DIR}/mindspore/ccsrc/plugin/device/cpu/kernel")
set(MINDDATA_FULL_SRC
${TOP_DIR}/mindspore/lite/src/runtime/cxx_api/types.cc

View File

@ -26,30 +26,7 @@
#endif
namespace mindspore {
namespace lite {
int OutputTensor2TensorC(const std::vector<lite::Tensor *> &tensors, std::vector<TensorC *> *tensors_c,
std::shared_ptr<Allocator> allocator) {
MS_ASSERT(tensors_c != nullptr);
for (size_t i = 0; i < tensors.size(); ++i) {
TensorC *tensor_c = nullptr;
if (allocator != nullptr && !IS_RUNTIME_ALLOCATOR(allocator)) {
tensor_c = static_cast<TensorC *>(allocator->Malloc(sizeof(TensorC)));
} else {
tensor_c = static_cast<TensorC *>(malloc(sizeof(TensorC)));
}
if (tensor_c == nullptr) {
MS_LOG(ERROR) << "malloc tensor fail!";
return RET_ERROR;
}
tensor_c->data_type_ = kNumberTypeFloat32;
tensor_c->format_ = tensors[i]->format();
tensor_c->data_ = nullptr;
tensor_c->shape_size_ = 0;
tensors_c->push_back(tensor_c);
}
return RET_OK;
}
void FreeAllTensorC(std::vector<TensorC *> *tensors_in, std::shared_ptr<Allocator> allocator) {
void FreeInTensorC(std::vector<TensorC *> *tensors_in, const std::shared_ptr<Allocator> &allocator) {
if (tensors_in == nullptr) {
return;
}
@ -58,24 +35,46 @@ void FreeAllTensorC(std::vector<TensorC *> *tensors_in, std::shared_ptr<Allocato
continue;
}
if (i->data_type_ == kObjectTypeTensorType) {
TensorListC *tensorListC = reinterpret_cast<TensorListC *>(i);
FreeTensorListC(tensorListC, allocator);
tensorListC = nullptr;
} else {
if (allocator != nullptr && !IS_RUNTIME_ALLOCATOR(allocator)) {
allocator->Free(i);
} else {
free(i);
auto *tensorListC = reinterpret_cast<TensorListC *>(i);
if (tensorListC->tensors_ != nullptr) {
if (allocator != nullptr && !IS_RUNTIME_ALLOCATOR(allocator)) {
allocator->Free(tensorListC->tensors_);
} else {
free(tensorListC->tensors_);
}
tensorListC->tensors_ = nullptr;
}
i = nullptr;
}
}
tensors_in->clear();
}
void FreeOutTensorC(std::vector<TensorC *> *tensors_out, const std::shared_ptr<Allocator> &allocator) {
if (tensors_out == nullptr) {
return;
}
for (auto &i : *tensors_out) {
if (i == nullptr) {
continue;
}
if (i->data_type_ == kObjectTypeTensorType) {
auto *tensorListC = reinterpret_cast<TensorListC *>(i);
if (tensorListC->tensors_ != nullptr) {
for (size_t j = 0; j < tensorListC->element_num_; ++j) {
if (tensorListC->tensors_[j] != nullptr && tensorListC->tensors_[j]->data_ != nullptr) {
free(tensorListC->tensors_[j]->data_);
}
}
free((tensorListC->tensors_));
tensorListC->tensors_ = nullptr;
}
}
}
tensors_out->clear();
}
int Tensor2TensorC(const Tensor *src, TensorC *dst) {
MS_CHECK_TRUE_RET(src != nullptr && dst != nullptr, RET_ERROR);
dst->is_ready_ = src->IsReady();
dst->format_ = static_cast<int>(src->format());
dst->data_ = src->data();
dst->data_type_ = src->data_type();
@ -90,7 +89,7 @@ int Tensor2TensorC(const Tensor *src, TensorC *dst) {
return RET_OK;
}
int TensorC2Tensor(const TensorC *src, Tensor *dst, std::shared_ptr<Allocator> allocator) {
int TensorC2Tensor(TensorC *src, Tensor *dst, std::shared_ptr<Allocator> allocator) {
MS_CHECK_TRUE_RET(src != nullptr && dst != nullptr, RET_ERROR);
dst->set_format(static_cast<mindspore::Format>(src->format_));
dst->set_data_type(static_cast<TypeId>(src->data_type_)); // get data during the runtime period
@ -98,95 +97,68 @@ int TensorC2Tensor(const TensorC *src, Tensor *dst, std::shared_ptr<Allocator> a
if (src->data_ != nullptr) {
auto data = dst->MutableData();
MS_CHECK_TRUE_RET(data != nullptr, RET_ERROR);
memcpy(data, src->data_, dst->Size());
dst->set_category(CONST_TENSOR);
if (allocator != nullptr && !IS_RUNTIME_ALLOCATOR(allocator)) {
allocator->Free(src->data_);
} else {
free(src->data_);
if (data == src->data_) { // tensor
dst->set_own_data(true);
dst->set_category(CONST_TENSOR);
return RET_OK;
}
memcpy(data, src->data_, dst->Size()); // tensor_list
dst->set_category(CONST_TENSOR);
}
return RET_OK;
}
int GenerateOutTensorC(const OpParameter *const parameter, const std::vector<lite::Tensor *> &outputs,
std::vector<TensorC *> *out_tensor_c, std::shared_ptr<Allocator> allocator) {
std::vector<TensorC *> *out_tensor_c) {
MS_CHECK_TRUE_RET(out_tensor_c != nullptr && parameter != nullptr, RET_ERROR);
if (parameter->type_ == mindspore::schema::PrimitiveType_TensorListFromTensor ||
parameter->type_ == mindspore::schema::PrimitiveType_TensorListReserve ||
parameter->type_ == mindspore::schema::PrimitiveType_TensorListSetItem) {
#ifndef CONTROLFLOW_TENSORLIST_CLIP
// TensorListC ->TensorC
MS_CHECK_TRUE_RET(!outputs.empty() && outputs.front()->data_type() == TypeId::kObjectTypeTensorType, RET_ERROR);
TensorListC *tensor_list_c = nullptr;
if (allocator != nullptr && !IS_RUNTIME_ALLOCATOR(allocator)) {
tensor_list_c = reinterpret_cast<TensorListC *>(allocator->Malloc(sizeof(TensorListC)));
} else {
tensor_list_c = reinterpret_cast<TensorListC *>(malloc(sizeof(TensorListC)));
}
if (tensor_list_c == nullptr) {
return RET_ERROR;
}
memset(tensor_list_c, 0, sizeof(TensorListC));
auto output = static_cast<TensorList *>(outputs[0]);
TensorListC *tensor_list_c = output->ConvertToTensorListC();
tensor_list_c->element_num_ = 0;
out_tensor_c->push_back(reinterpret_cast<TensorC *const>(tensor_list_c));
return RET_OK;
#else
return RET_NOT_SUPPORT;
#endif
} else {
return OutputTensor2TensorC(outputs, out_tensor_c, allocator);
(void)std::transform(outputs.begin(), outputs.end(), std::back_inserter(*out_tensor_c),
[](lite::Tensor *output) { return output->ConvertToTensorC(); });
}
return RET_OK;
}
int GenerateInTensorC(const std::vector<lite::Tensor *> &inputs, std::vector<TensorC *> *in_tensor_c,
std::shared_ptr<Allocator> allocator) {
const std::shared_ptr<Allocator> &allocator) {
MS_CHECK_TRUE_RET(in_tensor_c != nullptr, RET_ERROR);
int ret = RET_OK;
for (auto input : inputs) {
if (input->data_type() == kObjectTypeTensorType) {
#ifndef CONTROLFLOW_TENSORLIST_CLIP
// Tensor ->TensorList -> TensorListC -> TensorC
auto *tensor_list = reinterpret_cast<TensorList *>(input);
TensorListC *tensor_list_c = nullptr;
if (allocator != nullptr && !IS_RUNTIME_ALLOCATOR(allocator)) {
tensor_list_c = reinterpret_cast<TensorListC *>(allocator->Malloc(sizeof(TensorListC)));
} else {
tensor_list_c = reinterpret_cast<TensorListC *>(malloc(sizeof(TensorListC)));
}
if (tensor_list_c == nullptr) {
ret = RET_NULL_PTR;
break;
}
memset(tensor_list_c, 0, sizeof(TensorListC));
ret = TensorList2TensorListC(tensor_list, tensor_list_c, allocator);
if (ret != RET_OK) {
TensorListC *tensor_list_c = tensor_list->ConvertToTensorListC();
auto tensors = tensor_list->tensors();
if (!tensors.empty()) {
if (allocator != nullptr && !IS_RUNTIME_ALLOCATOR(allocator)) {
allocator->Free(tensor_list_c->tensors_);
allocator->Free(tensor_list_c);
tensor_list_c->tensors_ = reinterpret_cast<TensorC **>(allocator->Malloc(tensors.size() * sizeof(void *)));
} else {
free(tensor_list_c->tensors_);
free(tensor_list_c);
tensor_list_c->tensors_ = reinterpret_cast<TensorC **>(malloc(tensors.size() * sizeof(void *)));
}
for (size_t i = 0; i < tensors.size(); ++i) {
tensor_list_c->tensors_[i] = tensors[i]->ConvertToTensorC();
}
return NNACL_ERR;
}
in_tensor_c->push_back(reinterpret_cast<TensorC *>(tensor_list_c));
#else
return RET_NOT_SUPPORT;
#endif
} else {
// Tensor -> TensorC
TensorC *tensor_c = nullptr;
if (allocator != nullptr && !IS_RUNTIME_ALLOCATOR(allocator)) {
tensor_c = reinterpret_cast<TensorC *>(allocator->Malloc(sizeof(TensorC)));
} else {
tensor_c = reinterpret_cast<TensorC *>(malloc(sizeof(TensorC)));
}
if (tensor_c == nullptr) {
ret = RET_NULL_PTR;
break;
}
ret = Tensor2TensorC(input, tensor_c);
if (ret != RET_OK) {
MS_LOG(ERROR) << "Tensor to TensorC failed.";
if (allocator != nullptr && !IS_RUNTIME_ALLOCATOR(allocator)) {
allocator->Free(tensor_c);
} else {
free(tensor_c);
}
return ret;
}
TensorC *tensor_c = input->ConvertToTensorC();
in_tensor_c->emplace_back(tensor_c);
}
}
@ -283,7 +255,11 @@ void MoveCommonTensorData(Tensor *dst_tensor, Tensor *src_tensor) {
dst_tensor->set_data(src_tensor->MutableData()); /* using MutableData to sync GPU data */
}
dst_tensor->set_own_data(src_tensor->own_data());
if (src_tensor->data() == dst_tensor->data() && src_tensor->IsConst()) {
dst_tensor->set_own_data(false);
} else {
dst_tensor->set_own_data(src_tensor->own_data());
}
src_tensor->DecRefCount();
}
@ -445,10 +421,14 @@ void MoveTensorListTensorData(TensorList *dst_tensorlist, TensorList *src_tensor
auto &src_tensor = src_tensorlist->tensors()[i];
auto &dst_tensor = dst_tensorlist->tensors()[i];
dst_tensor->set_own_data(src_tensor->own_data());
if (src_tensor->data() != nullptr) {
dst_tensor->set_data(src_tensor->MutableData()); /* using MutableData to sync GPU data */
}
if (src_tensor->data() == dst_tensor->data() && src_tensor->IsConst()) {
dst_tensor->set_own_data(false);
} else {
dst_tensor->set_own_data(src_tensor->own_data());
}
dst_tensor->set_shape(src_tensor->shape());
}
@ -467,80 +447,20 @@ void SetTensorListTensorData(TensorList *dst_tensor_list, TensorList *src_tensor
dst_tensor_list->set_element_shape(src_tensor_list->element_shape());
}
void FreeTensorListC(TensorListC *tensorlist_c, std::shared_ptr<Allocator> allocator) {
MS_ASSERT(tensorlist_c != nullptr);
if (tensorlist_c->tensors_ != nullptr) {
if (allocator != nullptr && !IS_RUNTIME_ALLOCATOR(allocator)) {
allocator->Free(tensorlist_c->tensors_);
} else {
free(tensorlist_c->tensors_);
}
tensorlist_c->tensors_ = nullptr;
}
if (allocator != nullptr && !IS_RUNTIME_ALLOCATOR(allocator)) {
allocator->Free(tensorlist_c);
} else {
free(tensorlist_c);
}
}
int TensorList2TensorListC(TensorList *src, TensorListC *dst, std::shared_ptr<Allocator> allocator) {
MS_CHECK_TRUE_RET(src != nullptr && dst != nullptr, RET_ERROR);
dst->is_ready_ = src->IsReady();
dst->data_type_ = static_cast<TypeIdC>(src->data_type());
dst->format_ = static_cast<int>(src->format());
dst->shape_value_ = src->shape().empty() ? 0 : src->shape().front();
dst->element_num_ = src->shape().empty() ? 0 : src->tensors().size();
if ((dst->element_num_ != 0 && SIZE_MAX / dst->element_num_ < sizeof(TensorC)) ||
dst->element_num_ * sizeof(TensorC) > MAX_MALLOC_SIZE) {
MS_LOG(ERROR) << "data size error.";
return RET_ERROR;
}
if (allocator != nullptr && !IS_RUNTIME_ALLOCATOR(allocator)) {
dst->tensors_ = reinterpret_cast<TensorC *>(allocator->Malloc(dst->element_num_ * sizeof(TensorC)));
} else {
dst->tensors_ = reinterpret_cast<TensorC *>(malloc(dst->element_num_ * sizeof(TensorC)));
}
if (dst->tensors_ == nullptr) {
return RET_ERROR;
}
memset(dst->tensors_, 0, dst->element_num_ * sizeof(TensorC));
for (size_t i = 0; i < dst->element_num_; i++) {
auto ret = Tensor2TensorC(src->tensors().at(i), &dst->tensors_[i]);
if (ret != RET_OK) {
MS_LOG(ERROR) << "Tensor to TensorC failed.";
return ret;
}
}
dst->tensors_data_type_ = src->tensors_data_type();
dst->element_shape_size_ = src->element_shape().size();
for (size_t i = 0; i < dst->element_shape_size_; i++) {
dst->element_shape_[i] = src->element_shape().at(i);
}
dst->max_elements_num_ = src->max_elements_num();
return NNACL_OK;
}
int TensorListC2TensorList(const TensorListC *src, TensorList *dst) {
MS_CHECK_TRUE_RET(src != nullptr && dst != nullptr, RET_ERROR);
dst->set_data_type(static_cast<TypeId>(src->data_type_));
dst->set_format(static_cast<mindspore::Format>(src->format_));
dst->set_shape(std::vector<int>(1, src->element_num_));
dst->set_tensors_data_type(static_cast<TypeId>(src->tensors_data_type_));
// Set Tensors
for (size_t i = 0; i < src->element_num_; i++) {
auto ret = TensorC2Tensor(&src->tensors_[i], dst->GetTensor(static_cast<int>(i)));
auto ret = TensorC2Tensor(src->tensors_[i], dst->GetTensor(static_cast<int>(i)));
if (ret != RET_OK) {
MS_LOG(ERROR) << "TensorC2Tensor failed";
return ret;
}
}
dst->set_element_shape(std::vector<int>(src->element_shape_, src->element_shape_ + src->element_shape_size_));
dst->set_max_elements_num(src->max_elements_num_);
return RET_OK;
}
@ -562,7 +482,7 @@ TensorList *MallocTensorListDataAccordingToTensorListC(Tensor *tensor, TensorLis
auto tensor_shape = std::vector<std::vector<int>>(
tensor_list_c->element_num_, std::vector<int>(tensor_list_c->element_shape_,
tensor_list_c->element_shape_ + tensor_list_c->element_shape_size_));
tensor_list->MallocTensorListData(static_cast<TypeId>(tensor_list_c->data_type_), tensor_shape);
tensor_list->MallocTensorListData(static_cast<TypeId>(tensor_list_c->tensors_data_type_), tensor_shape);
return tensor_list;
}
@ -657,11 +577,6 @@ void FreeTensorListC(TensorListC *tensorlist_c, std::shared_ptr<Allocator> alloc
return;
}
int TensorList2TensorListC(TensorList *src, TensorListC *dst, std::shared_ptr<Allocator> allocator) {
MS_LOG(ERROR) << unsupport_controlflow_tensorlist_log;
return NNACL_ERR;
}
int TensorListC2TensorList(const TensorListC *src, TensorList *dst) {
MS_LOG(ERROR) << unsupport_controlflow_tensorlist_log;
return RET_ERROR;

View File

@ -29,18 +29,15 @@
namespace mindspore {
namespace lite {
int OutputTensor2TensorC(const std::vector<lite::Tensor *> &tensors, std::vector<TensorC *> *tensors_c,
std::shared_ptr<Allocator> allocator = nullptr);
void FreeAllTensorC(std::vector<TensorC *> *tensors_in, std::shared_ptr<Allocator> allocator = nullptr);
void FreeInTensorC(std::vector<TensorC *> *tensors_in, const std::shared_ptr<Allocator> &allocator = nullptr);
void FreeOutTensorC(std::vector<TensorC *> *tensors_in, const std::shared_ptr<Allocator> &allocator = nullptr);
int Tensor2TensorC(const Tensor *src, TensorC *dst);
int TensorC2Tensor(const TensorC *src, Tensor *dst, std::shared_ptr<Allocator> allocator = nullptr);
void FreeTensorListC(TensorListC *tensorlist_c, std::shared_ptr<Allocator> allocator = nullptr);
int TensorList2TensorListC(TensorList *src, TensorListC *dst, std::shared_ptr<Allocator> allocator = nullptr);
int TensorC2Tensor(TensorC *src, Tensor *dst, std::shared_ptr<Allocator> allocator = nullptr);
int TensorListC2TensorList(const TensorListC *src, TensorList *dst);
int GenerateInTensorC(const std::vector<lite::Tensor *> &inputs, std::vector<TensorC *> *in_tensor_c,
std::shared_ptr<Allocator> allocator = nullptr);
const std::shared_ptr<Allocator> &allocator = nullptr);
int GenerateOutTensorC(const OpParameter *const parameter, const std::vector<lite::Tensor *> &outputs,
std::vector<TensorC *> *out_tensor_c, std::shared_ptr<Allocator> allocator = nullptr);
std::vector<TensorC *> *out_tensor_c);
int CheckTensorsInvalid(const std::vector<Tensor *> &tensors);
int CheckGraphInputShapes(const std::vector<Tensor *> &inputs,
const std::unordered_map<Tensor *, std::vector<int>> &input_shape_map);

View File

@ -146,25 +146,25 @@ int KernelInferShape(const std::vector<lite::Tensor *> &inputs, const std::vecto
int ret = GenerateInTensorC(inputs, &in_tensors, allocator);
if (ret != RET_OK) {
FreeAllTensorC(&in_tensors, allocator);
FreeInTensorC(&in_tensors, allocator);
return RET_ERROR;
}
ret = GenerateOutTensorC(parameter, outputs, &out_tensors, allocator);
ret = GenerateOutTensorC(parameter, outputs, &out_tensors);
if (ret != RET_OK) {
FreeAllTensorC(&in_tensors, allocator);
FreeAllTensorC(&out_tensors, allocator);
FreeInTensorC(&in_tensors, allocator);
FreeOutTensorC(&out_tensors, allocator);
return RET_ERROR;
}
auto infer_shape_func = GetInferFunc(parameter->type_);
if (infer_shape_func == nullptr) {
MS_LOG(ERROR) << "Get infershape func failed! type:" << PrimitiveCurVersionTypeName(parameter->type_);
FreeAllTensorC(&in_tensors, allocator);
FreeAllTensorC(&out_tensors, allocator);
FreeInTensorC(&in_tensors, allocator);
FreeOutTensorC(&out_tensors, allocator);
return RET_ERROR;
}
ret = infer_shape_func(static_cast<TensorC **>(in_tensors.data()), in_tensors.size(), out_tensors.data(),
out_tensors.size(), parameter);
FreeAllTensorC(&in_tensors, allocator);
FreeInTensorC(&in_tensors, allocator);
for (size_t i = 0; i < out_tensors.size(); i++) {
if (out_tensors.at(i) == nullptr) {
continue;
@ -174,21 +174,19 @@ int KernelInferShape(const std::vector<lite::Tensor *> &inputs, const std::vecto
auto tensor_list = MallocTensorListDataAccordingToTensorListC(outputs.at(i), tensor_list_c);
if (tensor_list == nullptr) {
MS_LOG(ERROR) << "get as tensorlist failed";
FreeAllTensorC(&out_tensors, allocator);
FreeOutTensorC(&out_tensors, allocator);
return RET_ERROR;
}
auto tensor_ret = TensorListC2TensorList(tensor_list_c, tensor_list);
if (tensor_ret != RET_OK) {
MS_LOG(ERROR) << "TensorCList2TensorList failed";
FreeAllTensorC(&out_tensors, allocator);
FreeOutTensorC(&out_tensors, allocator);
return tensor_ret;
}
} else {
auto tensor_ret = TensorC2Tensor(out_tensors.at(i), outputs.at(i), allocator);
if (tensor_ret != RET_OK) {
MS_LOG(ERROR) << "TensorC2Tensor failed";
FreeAllTensorC(&out_tensors, allocator);
return tensor_ret;
if (out_tensors.at(i)->data_ != nullptr) {
outputs.at(i)->set_own_data(true);
outputs.at(i)->set_category(CONST_TENSOR);
}
}
@ -196,7 +194,7 @@ int KernelInferShape(const std::vector<lite::Tensor *> &inputs, const std::vecto
outputs.at(i)->set_shape({-1});
}
}
FreeAllTensorC(&out_tensors, allocator);
FreeOutTensorC(&out_tensors, allocator);
return CheckInfershapeResult(ret, inputs, outputs, parameter);
}

View File

@ -215,7 +215,11 @@ int ReduceBaseCPUKernel::CopyInputToOutput() {
out_tensor->FreeData();
out_tensor->ResetRefCount();
out_tensor->set_data(in_tensor->data());
out_tensor->set_own_data(in_tensor->own_data());
if (in_tensor->IsConst()) {
out_tensor->set_own_data(false);
} else {
out_tensor->set_own_data(in_tensor->own_data());
}
return RET_OK;
}
} // namespace mindspore::kernel

View File

@ -88,7 +88,11 @@ int ReshapeBaseCPUKernel::Run() {
out_tensor->FreeData();
out_tensor->ResetRefCount();
out_tensor->set_data(in_tensor->data());
out_tensor->set_own_data(in_tensor->own_data());
if (in_tensor->IsConst()) {
out_tensor->set_own_data(false);
} else {
out_tensor->set_own_data(in_tensor->own_data());
}
return RET_OK;
}

View File

@ -286,7 +286,11 @@ int StridedSliceCPUKernel::SoftCopyInputToOutput() {
output_tensor->FreeData();
output_tensor->ResetRefCount();
output_tensor->set_data(input_tensor->data());
output_tensor->set_own_data(input_tensor->own_data());
if (input_tensor->IsConst()) {
output_tensor->set_own_data(false);
} else {
output_tensor->set_own_data(input_tensor->own_data());
}
return RET_OK;
}

View File

@ -227,7 +227,11 @@ int TransposeBaseCPUKernel::CopyInputToOutput() {
out_tensor->FreeData();
out_tensor->ResetRefCount();
out_tensor->set_data(in_tensor->data());
out_tensor->set_own_data(in_tensor->own_data());
if (in_tensor->IsConst()) {
out_tensor->set_own_data(false);
} else {
out_tensor->set_own_data(in_tensor->own_data());
}
return RET_OK;
}

View File

@ -147,7 +147,7 @@ int ScatterNdUpdateCPUKernel::Run() {
auto in_tensor = in_tensors().front();
auto out_tensor = out_tensors().front();
if (in_tensor->allocator() == nullptr || in_tensor->allocator() != out_tensor->allocator() ||
in_tensor->own_data() == false || op_parameter_->is_train_session_) {
in_tensor->own_data() == false || in_tensor->IsConst() || op_parameter_->is_train_session_) {
memcpy(out_tensor->data(), in_tensor->data(), in_tensor->Size());
} else {
out_tensor->FreeData();

View File

@ -1388,7 +1388,7 @@ void LiteSession::RuntimeAllocatorInitSubgraph() {
for (auto kernel : kernel_list) {
/* malloc for output */
for (auto tensor : kernel->out_tensors()) {
if (tensor->allocator() != default_allocator) {
if (tensor->allocator() != default_allocator || tensor->IsConst()) {
continue;
}
tensor->set_allocator(runtime_allocator_);

View File

@ -266,7 +266,7 @@ int MindrtExecutor::TransferGraphOutput() {
}
if (src_tensor->allocator() != nullptr) {
dst_tensor->set_data(src_tensor->data());
dst_tensor->set_own_data(src_tensor->own_data());
dst_tensor->set_own_data(src_tensor->IsConst() ? false : src_tensor->own_data());
} else {
dst_tensor->set_data(src_tensor->data());
src_tensor->set_data(nullptr);

View File

@ -114,11 +114,28 @@ class ShapeFusionPass {
[&](uint32_t idx) { return this->src_tensors_->at(idx); });
#endif
}
void FreeOutputTensorDataOfFusedShape() {
#if !defined(RUNTIME_PASS_CLIP)
for (auto tensor : shape_fusion_outputs_) {
tensor->FreeData();
tensor->set_category(VAR);
void StoreStateAndReset() {
#ifndef RUNTIME_PASS_CLIP
std::vector<lite::Tensor *> shape_fusion_outputs = shape_fusion_outputs_;
shape_fusion_outputs_.clear();
for (auto output : shape_fusion_outputs) {
if (output->IsConst()) {
shape_fusion_outputs_.push_back(output);
datas_.push_back(output->data());
output->set_data(nullptr);
output->set_category(VAR);
}
}
#endif
}
void RestoreState() {
#ifndef RUNTIME_PASS_CLIP
size_t count = std::min(shape_fusion_outputs_.size(), datas_.size());
for (size_t i = 0; i < count; ++i) {
shape_fusion_outputs_[i]->set_data(datas_[i]);
shape_fusion_outputs_[i]->set_category(CONST_TENSOR);
}
#endif
}
@ -141,6 +158,7 @@ class ShapeFusionPass {
private:
std::map<uint32_t, ShapeFusionMatrix> shape_fusion_matrices_;
std::vector<lite::Tensor *> shape_fusion_outputs_;
std::vector<void *> datas_;
#endif
InnerContext *context_ = nullptr;
LiteModel *lite_model_ = nullptr;

View File

@ -238,6 +238,10 @@ int Scheduler::InitKernels(std::vector<kernel::KernelExec *> &&dst_kernels) {
for (auto node : subgraph_nodes) {
for (auto *tensor : node->out_tensors()) {
if (tensor->IsConst()) {
MS_CHECK_TRUE_MSG(node->op_parameter() != nullptr, RET_NULL_PTR, "node's op_parameter is invalid.");
if (node->op_parameter()->type_ == PrimType::PrimType_Inner_ShapeFusion) {
continue;
}
MS_LOG(ERROR) << "Illegitimate kernel output tensor : " << tensor->tensor_name();
continue;
}
@ -460,8 +464,7 @@ int Scheduler::Schedule(std::vector<kernel::KernelExec *> *dst_kernels) {
return ret;
}
}
shape_fusion_pass_->FreeOutputTensorDataOfFusedShape();
shape_fusion_pass_->StoreStateAndReset();
ret = InitDelegateKernels(dst_kernels);
if (ret != RET_OK) {
MS_LOG(ERROR) << "Repalce delegate kernels failed.";
@ -508,6 +511,7 @@ int Scheduler::Schedule(std::vector<kernel::KernelExec *> *dst_kernels) {
MS_LOG(ERROR) << "InitKernels failed.";
return ret;
}
shape_fusion_pass_->RestoreState();
if (IsPrintDebug()) {
MS_LOG(DEBUG) << "schedule kernels success.";
for (auto subgraph : *dst_kernels) {

View File

@ -45,14 +45,24 @@ static const size_t max_malloc_size_ = GetMaxMallocSize();
#endif
Tensor::Tensor(const TypeId data_type, std::vector<int> shape, const mindspore::Format &format, Category category)
: data_type_(data_type), shape_(std::move(shape)), format_(format), category_(category) {}
: category_(category) {
tensor_c_ = {data_type, static_cast<int>(format), nullptr, shape.size()};
if (shape.size() > MAX_SHAPE_SIZE) {
tensor_c_.shape_size_ = 0;
MS_LOG(WARNING) << "The shape-size has exceeded the limit 8, now is " << shape.size();
return;
}
for (size_t i = 0; i < shape.size(); ++i) {
tensor_c_.shape_[i] = shape[i];
}
}
int Tensor::CopyTensorData(const Tensor &src_tensor, Tensor *dst_tensor) {
if (dst_tensor == nullptr) {
MS_LOG(ERROR) << "dst_tensor is nullptr";
return RET_PARAM_INVALID;
}
if (src_tensor.data_ == nullptr) {
if (src_tensor.tensor_c_.data_ == nullptr) {
MS_LOG(INFO) << "data of src tensor is nullptr";
return RET_OK;
}
@ -66,7 +76,7 @@ int Tensor::CopyTensorData(const Tensor &src_tensor, Tensor *dst_tensor) {
return RET_ERROR;
}
dst_tensor->ResetRefCount();
memcpy(dst_tensor->data_, src_tensor.data_, data_size);
(void)memcpy(dst_tensor->tensor_c_.data_, src_tensor.tensor_c_.data_, data_size);
return RET_OK;
}
@ -76,10 +86,9 @@ Tensor *Tensor::CopyTensor(const Tensor &src_tensor, bool copy_data, AllocatorPt
MS_LOG(ERROR) << "New tensor failed";
return nullptr;
}
result->data_type_ = src_tensor.data_type_;
result->shape_ = src_tensor.shape_;
(void)memcpy(&result->tensor_c_, &src_tensor.tensor_c_, sizeof(TensorC));
result->tensor_c_.data_ = nullptr;
result->category_ = src_tensor.category_;
result->format_ = src_tensor.format_;
result->set_allocator(allocator);
result->set_tensor_name(src_tensor.tensor_name() + "_duplicate");
if (copy_data) {
@ -101,20 +110,22 @@ Tensor *Tensor::CopyTensor(const Tensor &src_tensor, bool copy_data, AllocatorPt
Tensor::~Tensor() {
FreeData();
this->data_ = nullptr;
this->tensor_c_.data_ = nullptr;
}
bool Tensor::operator==(const Tensor &tensor) {
return data_ == tensor.data_ && shape_ == tensor.shape_ && data_type_ == tensor.data_type_;
return tensor_c_.data_ == tensor.tensor_c_.data_ && tensor_c_.shape_size_ == tensor.tensor_c_.shape_size_ &&
tensor_c_.data_type_ == tensor.tensor_c_.data_type_ &&
std::equal(tensor_c_.shape_, tensor_c_.shape_ + tensor_c_.shape_size_, tensor.tensor_c_.shape_);
}
int32_t Tensor::Batch() const {
// Only 2D or 4D tensors have valid batch.
if (this->shape_.size() != 4 && this->shape_.size() != 2) {
MS_LOG(ERROR) << "Unsupported tensor shape: " << this->shape().size();
if (this->tensor_c_.shape_size_ != C4NUM && this->tensor_c_.shape_size_ != C2NUM) {
MS_LOG(ERROR) << "Unsupported tensor shape: " << this->tensor_c_.shape_size_;
return RET_ERROR;
}
switch (this->format_) {
switch (this->tensor_c_.format_) {
case mindspore::NHWC:
case mindspore::NHWC4:
case mindspore::NCHW:
@ -124,56 +135,56 @@ int32_t Tensor::Batch() const {
case mindspore::KHWC:
case mindspore::NC:
case mindspore::NC4:
return this->shape_[0];
return this->tensor_c_.shape_[0];
case mindspore::HWCK:
case mindspore::CHWK:
if (this->shape_.size() != 4) {
if (this->tensor_c_.shape_size_ != C4NUM) {
return RET_ERROR;
}
return this->shape_[3];
return this->tensor_c_.shape_[C3NUM];
case mindspore::HWKC:
if (this->shape_.size() != 4) {
if (this->tensor_c_.shape_size_ != C4NUM) {
return RET_ERROR;
}
return this->shape_[2];
return this->tensor_c_.shape_[C2NUM];
case mindspore::CKHW:
return this->shape_[1];
return this->tensor_c_.shape_[1];
default:
MS_LOG(ERROR) << "Unsupported format: " << EnumNameFormat(static_cast<schema::Format>(this->format_));
MS_LOG(ERROR) << "Unsupported format: " << EnumNameFormat(static_cast<schema::Format>(this->tensor_c_.format_));
return RET_ERROR;
}
}
int32_t Tensor::Channel() const {
// Only 2D or 4D tensors have valid channel.
if (this->shape_.size() != 4 && this->shape_.size() != 2) {
MS_LOG(ERROR) << "Unsupported tensor shape: " << this->shape().size();
if (this->tensor_c_.shape_size_ != C4NUM && this->tensor_c_.shape_size_ != C2NUM) {
MS_LOG(ERROR) << "Unsupported tensor shape: " << this->tensor_c_.shape_size_;
return RET_ERROR;
}
switch (this->format_) {
switch (this->tensor_c_.format_) {
case mindspore::NCHW:
case mindspore::KCHW:
case mindspore::NC:
case mindspore::NC4:
case mindspore::NC4HW4:
case mindspore::NC8HW8:
return this->shape_[1];
return this->tensor_c_.shape_[1];
case mindspore::HWCK:
if (this->shape_.size() != 4) {
if (this->tensor_c_.shape_size_ != C4NUM) {
return RET_ERROR;
}
return this->shape_[2];
return this->tensor_c_.shape_[C2NUM];
case mindspore::HWKC:
case mindspore::NHWC:
case mindspore::NHWC4:
case mindspore::KHWC:
if (this->shape_.size() != 4) {
if (this->tensor_c_.shape_size_ != C4NUM) {
return RET_ERROR;
}
return this->shape_[3];
return this->tensor_c_.shape_[C3NUM];
case mindspore::CKHW:
case mindspore::CHWK:
return this->shape_[0];
return this->tensor_c_.shape_[0];
default:
return RET_ERROR;
}
@ -181,79 +192,81 @@ int32_t Tensor::Channel() const {
int32_t Tensor::Height() const {
// Only 2D or 4D tensors have valid height.
if (this->shape_.size() != 4 && this->shape_.size() != 2) {
MS_LOG(ERROR) << "Unsupported tensor shape: " << this->shape().size();
if (this->tensor_c_.shape_size_ != C4NUM && this->tensor_c_.shape_size_ != C2NUM) {
MS_LOG(ERROR) << "Unsupported tensor shape: " << this->tensor_c_.shape_size_;
return RET_ERROR;
}
switch (this->format_) {
switch (this->tensor_c_.format_) {
case mindspore::NCHW:
case mindspore::KCHW:
case mindspore::CKHW:
case mindspore::NC4HW4:
case mindspore::NC8HW8:
if (this->shape_.size() != 4) {
if (this->tensor_c_.shape_size_ != C4NUM) {
return RET_ERROR;
}
return this->shape_[2];
return this->tensor_c_.shape_[C2NUM];
case mindspore::NHWC:
case mindspore::NHWC4:
case mindspore::KHWC:
case mindspore::CHWK:
return this->shape_[1];
return this->tensor_c_.shape_[1];
case mindspore::HWCK:
case mindspore::HWKC:
case mindspore::HW:
case mindspore::HW4:
return this->shape_[0];
return this->tensor_c_.shape_[0];
default:
MS_LOG(ERROR) << "Unsupported format: " << EnumNameFormat(static_cast<schema::Format>(this->format_));
MS_LOG(ERROR) << "Unsupported format: " << EnumNameFormat(static_cast<schema::Format>(this->tensor_c_.format_));
return RET_ERROR;
}
}
int32_t Tensor::Width() const {
// Only 2D or 4D tensors have valid width.
if (this->shape_.size() != 4 && this->shape_.size() != 2) {
MS_LOG(ERROR) << "Unsupported tensor shape: " << this->shape().size();
if (this->tensor_c_.shape_size_ != C4NUM && this->tensor_c_.shape_size_ != C2NUM) {
MS_LOG(ERROR) << "Unsupported tensor shape: " << this->tensor_c_.shape_size_;
return RET_ERROR;
}
switch (this->format_) {
switch (this->tensor_c_.format_) {
case mindspore::NCHW:
case mindspore::KCHW:
case mindspore::CKHW:
case mindspore::NC4HW4:
case mindspore::NC8HW8:
if (this->shape_.size() != 4) {
if (this->tensor_c_.shape_size_ != C4NUM) {
return RET_ERROR;
}
return this->shape_[3];
return this->tensor_c_.shape_[C3NUM];
case mindspore::KHWC:
case mindspore::NHWC:
case mindspore::NHWC4:
case mindspore::CHWK:
if (this->shape_.size() != 4) {
if (this->tensor_c_.shape_size_ != C4NUM) {
return RET_ERROR;
}
return this->shape_[2];
return this->tensor_c_.shape_[C2NUM];
case mindspore::HWCK:
case mindspore::HWKC:
case mindspore::HW:
case mindspore::HW4:
return this->shape_[1];
return this->tensor_c_.shape_[1];
default:
return RET_ERROR;
}
}
size_t Tensor::Size() const {
size_t element_size = DataTypeSize(this->data_type_);
size_t element_size = DataTypeSize(static_cast<TypeId>(tensor_c_.data_type_));
if (element_size == 0) {
MS_LOG(INFO) << "Unexpected data type: " << data_type_;
MS_LOG(INFO) << "Unexpected data type: " << tensor_c_.data_type_;
return 0;
}
auto element_num = (format_ == mindspore::NC4HW4 || format_ == mindspore::NHWC4) ? ElementsC4Num() : ElementsNum();
auto element_num =
(tensor_c_.format_ == mindspore::NC4HW4 || tensor_c_.format_ == mindspore::NHWC4) ? ElementsC4Num() : ElementsNum();
if (element_num <= 0) {
MS_LOG(DEBUG) << "Element number of tensor should large than 0 : " << element_num << ", shape: " << shape_;
std::vector<int> shape(tensor_c_.shape_, tensor_c_.shape_ + tensor_c_.shape_size_);
MS_LOG(DEBUG) << "Element number of tensor should large than 0 : " << element_num << ", shape: " << shape;
return 0;
}
return element_size * static_cast<size_t>(element_num);
@ -263,16 +276,16 @@ int64_t Tensor::ElementsNum() const {
if (this->category_ == CONST_SCALAR) {
return 1;
}
if (format_ == mindspore::NC4HW4) {
if (tensor_c_.format_ == mindspore::NC4HW4) {
return ElementsC4Num();
}
if (format_ == mindspore::NC8HW8) {
if (tensor_c_.format_ == mindspore::NC8HW8) {
return ElementsC8Num();
}
int64_t num = 1;
for (size_t i = 0; i < shape_.size(); ++i) {
CHECK_INT64_MUL_OVERFLOW(num, shape_[i]);
num *= shape_[i];
for (size_t i = 0; i < tensor_c_.shape_size_; ++i) {
CHECK_INT64_MUL_OVERFLOW(num, tensor_c_.shape_[i]);
num *= tensor_c_.shape_[i];
}
return num;
}
@ -283,7 +296,7 @@ int64_t Tensor::ElementsC4Num() const {
}
int64_t result = 1;
constexpr int kC4Align = 4;
if (this->shape_.size() == 4) {
if (this->tensor_c_.shape_size_ == C4NUM) {
CHECK_INT64_MUL_OVERFLOW(result, Batch());
result *= Batch();
CHECK_INT64_MUL_OVERFLOW(result, Height());
@ -292,11 +305,11 @@ int64_t Tensor::ElementsC4Num() const {
result *= Width();
CHECK_INT64_MUL_OVERFLOW(result, (Channel() + 3LL) / kC4Align * kC4Align);
result *= (Channel() + 3LL) / kC4Align * kC4Align;
} else if (this->shape_.size() == 2) {
CHECK_INT64_MUL_OVERFLOW(result, this->shape_[0]);
result *= this->shape_[0];
CHECK_INT64_MUL_OVERFLOW(result, (this->shape_[1] + 3LL) / kC4Align * kC4Align);
result *= (this->shape_[1] + 3LL) / kC4Align * kC4Align;
} else if (this->tensor_c_.shape_size_ == C2NUM) {
CHECK_INT64_MUL_OVERFLOW(result, this->tensor_c_.shape_[0]);
result *= this->tensor_c_.shape_[0];
CHECK_INT64_MUL_OVERFLOW(result, (this->tensor_c_.shape_[1] + 3LL) / kC4Align * kC4Align);
result *= (this->tensor_c_.shape_[1] + 3LL) / kC4Align * kC4Align;
}
return result;
}
@ -307,7 +320,7 @@ int64_t Tensor::ElementsC8Num() const {
}
int64_t result = 1;
constexpr int kC8Align = 8;
if (this->shape_.size() == 4) {
if (this->tensor_c_.shape_size_ == C4NUM) {
CHECK_INT64_MUL_OVERFLOW(result, Batch());
result *= Batch();
CHECK_INT64_MUL_OVERFLOW(result, Height());
@ -316,19 +329,19 @@ int64_t Tensor::ElementsC8Num() const {
result *= Width();
CHECK_INT64_MUL_OVERFLOW(result, (Channel() + 7LL) / kC8Align * kC8Align);
result *= (Channel() + 7LL) / kC8Align * kC8Align;
} else if (this->shape_.size() == 2) {
CHECK_INT64_MUL_OVERFLOW(result, this->shape_[0]);
result *= this->shape_[0];
CHECK_INT64_MUL_OVERFLOW(result, (this->shape_[1] + 7LL) / kC8Align * kC8Align);
result *= (this->shape_[1] + 7LL) / kC8Align * kC8Align;
} else if (this->tensor_c_.shape_size_ == C2NUM) {
CHECK_INT64_MUL_OVERFLOW(result, this->tensor_c_.shape_[0]);
result *= this->tensor_c_.shape_[0];
CHECK_INT64_MUL_OVERFLOW(result, (this->tensor_c_.shape_[1] + 7LL) / kC8Align * kC8Align);
result *= (this->tensor_c_.shape_[1] + 7LL) / kC8Align * kC8Align;
}
return result;
}
int Tensor::DimensionSize(const size_t index) const {
int dim_size = -1;
if (index < shape_.size()) {
dim_size = shape_[index];
if (index < tensor_c_.shape_size_) {
dim_size = tensor_c_.shape_[index];
} else {
MS_LOG(ERROR) << "Dimension index is wrong: " << index;
}
@ -338,29 +351,30 @@ int Tensor::DimensionSize(const size_t index) const {
std::string Tensor::ToString() const {
std::ostringstream oss;
oss << "Tensor name: " << this->tensor_name();
oss << " schema::Format: " << EnumNameFormat(static_cast<schema::Format>(this->format_));
oss << " DataType: " << this->data_type_;
oss << " schema::Format: " << EnumNameFormat(static_cast<schema::Format>(this->tensor_c_.format_));
oss << " DataType: " << this->tensor_c_.data_type_;
oss << " Category: " << this->category_;
oss << " Shape:";
for (auto &dim : this->shape()) {
oss << " " << dim;
}
oss << std::endl << "Data:";
switch (this->data_type_) {
auto data = tensor_c_.data_;
switch (this->tensor_c_.data_type_) {
case kNumberTypeFloat32: {
oss << DataToString<float>(data_, this->ElementsNum());
oss << DataToString<float>(data, this->ElementsNum());
} break;
case kNumberTypeFloat16: {
oss << DataToString<int16_t>(data_, this->ElementsNum());
oss << DataToString<int16_t>(data, this->ElementsNum());
} break;
case kNumberTypeInt32: {
oss << DataToString<int32_t>(data_, this->ElementsNum());
oss << DataToString<int32_t>(data, this->ElementsNum());
} break;
case kNumberTypeInt16: {
oss << DataToString<int16_t>(data_, this->ElementsNum());
oss << DataToString<int16_t>(data, this->ElementsNum());
} break;
case kNumberTypeInt8: {
oss << DataToString<int8_t>(data_, this->ElementsNum());
oss << DataToString<int8_t>(data, this->ElementsNum());
} break;
default:
oss << "Unsupported data type to print";
@ -370,15 +384,15 @@ std::string Tensor::ToString() const {
}
int Tensor::MallocData(const AllocatorPtr allocator) {
if (this->data_ != nullptr) {
if (this->tensor_c_.data_ != nullptr) {
return RET_OK;
}
if (allocator != nullptr) {
allocator_ = allocator;
}
size_t element_size = DataTypeSize(this->data_type_);
size_t element_size = DataTypeSize(static_cast<TypeId>(this->tensor_c_.data_type_));
if (element_size == 0) {
MS_LOG(ERROR) << "Unexpected data type: " << data_type_;
MS_LOG(ERROR) << "Unexpected data type: " << tensor_c_.data_type_;
return RET_ERROR;
}
auto data_size = this->Size();
@ -391,12 +405,12 @@ int Tensor::MallocData(const AllocatorPtr allocator) {
return RET_ERROR;
}
if (allocator_ == nullptr) {
this->data_ = malloc(data_size);
this->tensor_c_.data_ = malloc(data_size);
} else {
this->data_ = allocator_->Malloc(data_size);
allocator_->SetRefCount(this->data_, 1);
this->tensor_c_.data_ = allocator_->Malloc(data_size);
allocator_->SetRefCount(this->tensor_c_.data_, 1);
}
if (this->data_ == nullptr) {
if (this->tensor_c_.data_ == nullptr) {
MS_LOG(ERROR) << "Malloc tensor data failed, size=" << data_size;
return RET_ERROR;
}
@ -408,43 +422,43 @@ void Tensor::FreeData() {
if (IS_RUNTIME_ALLOCATOR(allocator_)) {
return;
}
if (this->data_ != nullptr && this->own_data_) {
if (this->tensor_c_.data_ != nullptr && this->own_data_) {
if (this->allocator_ != nullptr) {
if (allocator_->DecRefCount(this->data_, 1) <= 0) {
allocator_->Free(this->data_); // Due to existing various allocator, here do not set data to nullptr.
if (allocator_->DecRefCount(this->tensor_c_.data_, 1) <= 0) {
allocator_->Free(this->tensor_c_.data_); // Due to existing various allocator, here do not set data to nullptr.
}
if (!IS_STATIC_ALLOCATOR(allocator_) || allocator_->RefCount(this->data_) != 0) {
this->data_ = nullptr;
if (!IS_STATIC_ALLOCATOR(allocator_) || allocator_->RefCount(this->tensor_c_.data_) != 0) {
this->tensor_c_.data_ = nullptr;
}
} else {
free(this->data_);
this->data_ = nullptr;
free(this->tensor_c_.data_);
this->tensor_c_.data_ = nullptr;
}
} else if (this->category_ == Category::VAR) {
if (!IS_STATIC_ALLOCATOR(allocator_) || allocator_->RefCount(this->data_) != 0) {
if (!IS_STATIC_ALLOCATOR(allocator_) || allocator_->RefCount(this->tensor_c_.data_) != 0) {
if (this->init_ref_count_ == 1) {
this->data_ = nullptr;
this->tensor_c_.data_ = nullptr;
}
}
}
}
void *Tensor::ReallocData() {
if (this->data_ != nullptr) {
if (this->tensor_c_.data_ != nullptr) {
FreeData();
}
return this->MutableData();
}
void *Tensor::MutableData() {
if (this->data_ == nullptr) {
if (this->tensor_c_.data_ == nullptr) {
auto ret = this->MallocData();
if (ret != 0) {
MS_LOG(WARNING) << "Malloc data failed";
}
}
Prepare();
return this->data_;
return this->tensor_c_.data_;
}
void Tensor::DecRefCount() {

View File

@ -26,6 +26,7 @@
#include <atomic>
#include "include/api/format.h"
#include "include/lite_types.h"
#include "nnacl/tensor_c.h"
#include "src/runtime/inner_allocator.h"
#include "src/common/log_adapter.h"
#include "src/common/utils.h"
@ -55,7 +56,7 @@ struct LiteQuantParam {
class Tensor {
public:
Tensor() = default;
Tensor() { tensor_c_ = {kTypeUnknown, DEFAULT_FORMAT, nullptr, 0}; }
Tensor(TypeId data_type, std::vector<int> shape, const mindspore::Format &format = mindspore::NHWC,
Category category = VAR);
@ -85,13 +86,26 @@ class Tensor {
std::string tensor_name() const { return tensor_name_; }
TypeId data_type() const { return data_type_; }
TypeId data_type() const { return static_cast<TypeId>(tensor_c_.data_type_); }
void set_data_type(TypeId data_type) { data_type_ = data_type; }
void set_data_type(TypeId data_type) { tensor_c_.data_type_ = data_type; }
std::vector<int> shape() const { return shape_; }
std::vector<int> shape() const {
return std::vector<int>(tensor_c_.shape_, tensor_c_.shape_ + tensor_c_.shape_size_);
}
void set_shape(const std::vector<int> &shape) { shape_ = shape; }
void set_shape(const std::vector<int> &shape) {
if (shape.size() > MAX_SHAPE_SIZE) {
FreeData();
tensor_c_.shape_size_ = 0;
MS_LOG(WARNING) << "The shape-size has exceeded the limit 8, now is " << shape.size();
return;
}
tensor_c_.shape_size_ = shape.size();
for (size_t i = 0; i < shape.size(); ++i) {
tensor_c_.shape_[i] = shape[i];
}
}
int DimensionSize(size_t index) const;
@ -122,21 +136,21 @@ class Tensor {
void *ReallocData();
virtual void *data() { return data_; }
virtual void *data() { return tensor_c_.data_; }
virtual void *data() const { return data_; }
virtual void *data() const { return tensor_c_.data_; }
// note: in the case of that old_data is valid, set_data just releases the ownership of it but not frees it. Of
// course, you can call FreeData before calling set_data to ensure the data can be freed by current tensor.
void set_data(void *data) {
if (this->data_ == data) {
if (this->tensor_c_.data_ == data) {
return;
}
if (allocator_ != nullptr) {
allocator_->IncRefCount(data, 1);
allocator_->DecRefCount(this->data_, 1);
allocator_->DecRefCount(this->tensor_c_.data_, 1);
}
this->data_ = data;
this->tensor_c_.data_ = data;
this->own_data_ = true;
}
@ -144,9 +158,9 @@ class Tensor {
void set_category(Category category) { this->category_ = category; }
void set_format(mindspore::Format format) { this->format_ = format; }
void set_format(mindspore::Format format) { this->tensor_c_.format_ = format; }
mindspore::Format format() const { return this->format_; }
mindspore::Format format() const { return static_cast<mindspore::Format>(this->tensor_c_.format_); }
virtual int ref_count() const { return ref_count_; }
virtual int init_ref_count() const { return static_cast<int>(this->init_ref_count_); }
@ -176,10 +190,10 @@ class Tensor {
void set_quant_clusters(const std::vector<float> &clusters);
virtual bool IsConst() const {
return (this->category_ == CONST_TENSOR || this->category_ == CONST_SCALAR) && this->data_ != nullptr;
return (this->category_ == CONST_TENSOR || this->category_ == CONST_SCALAR) && this->tensor_c_.data_ != nullptr;
}
bool IsScalar() const { return this->category_ == CONST_SCALAR && this->data_ != nullptr; }
bool IsScalar() const { return this->category_ == CONST_SCALAR && this->tensor_c_.data_ != nullptr; }
bool IsGraphInput() const { return this->category_ == GRAPH_INPUT; }
@ -187,12 +201,12 @@ class Tensor {
void Prepare() {
if (allocator_ != nullptr) {
data_ = allocator_->Prepare(data_);
tensor_c_.data_ = allocator_->Prepare(tensor_c_.data_);
}
}
bool IsReady() const {
return this->IsConst() || (this->IsGraphInput() && this->data_ != nullptr) || ref_count() >= 1;
return this->IsConst() || (this->IsGraphInput() && this->tensor_c_.data_ != nullptr) || ref_count() >= 1;
}
bool own_data() const { return this->own_data_; }
@ -202,7 +216,7 @@ class Tensor {
template <typename T>
int Scale(float scale) {
T cast_scale = static_cast<T>(scale);
auto data = reinterpret_cast<T *>(data_);
auto data = reinterpret_cast<T *>(tensor_c_.data_);
if (data == nullptr) {
return RET_ERROR;
}
@ -220,6 +234,8 @@ class Tensor {
bool IsScale() const { return (std::fabs(this->scale_ - 1.0f) > 1.0e-05); }
TensorC *ConvertToTensorC() { return &tensor_c_; }
private:
template <typename T>
std::string DataToString(void *data, size_t data_number, size_t print_len = 40) const {
@ -235,11 +251,8 @@ class Tensor {
}
protected:
TensorC tensor_c_;
std::string tensor_name_;
void *data_ = nullptr;
TypeId data_type_;
std::vector<int> shape_;
mindspore::Format format_;
Category category_;
std::atomic_int ref_count_ = {0};
int init_ref_count_ = 0;

View File

@ -23,9 +23,21 @@
namespace mindspore::lite {
#ifndef CONTROLFLOW_TENSORLIST_CLIP
namespace {
constexpr int kOffset = 2;
}
TensorList::TensorList(std::vector<int> shape, std::vector<int> element_shape, Category category)
: Tensor(kObjectTypeTensorType, std::move(shape), mindspore::NHWC, category),
element_shape_(std::move(element_shape)) {}
: Tensor(kObjectTypeTensorType, std::move(shape), mindspore::NHWC, category) {
tensor_list_c_ = {kObjectTypeTensorType, Format_NHWC, 0, kTypeUnknown, -1, nullptr, 0, element_shape.size()};
if (shape.size() > MAX_SHAPE_SIZE) {
tensor_list_c_.element_shape_size_ = 0;
MS_LOG(WARNING) << "The shape-size has exceeded the limit 8, now is " << element_shape.size();
return;
}
for (size_t i = 0; i < element_shape.size(); ++i) {
tensor_list_c_.element_shape_[i] = element_shape[i];
}
}
TensorList::~TensorList() {
if (!this->tensors_.empty()) {
@ -82,7 +94,7 @@ int TensorList::MallocTensorListData(TypeId dtype, const std::vector<std::vector
<< " must be equal to param2:tensor_shape.size():" << tensor_shape.size();
return RET_ERROR;
}
this->tensors_data_type_ = dtype;
this->tensor_list_c_.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) {
@ -128,9 +140,9 @@ int TensorList::MallocData(const AllocatorPtr allocator) {
int TensorList::SetTensor(int index, const Tensor *src_tensor) {
MS_CHECK_TRUE_MSG(src_tensor != nullptr, RET_ERROR, "src tensor cannot null");
// your can use this fun to modify tensor[index] value
if (src_tensor->data_type() != this->tensors_data_type_) {
if (src_tensor->data_type() != this->tensor_list_c_.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_;
<< " must be equal to tensors_data_type_:" << this->tensor_list_c_.tensors_data_type_;
return RET_ERROR;
}
auto element_num = this->ElementsNum();
@ -157,9 +169,9 @@ int TensorList::CheckTensorListParam() {
MS_LOG(ERROR) << "CheckTensorListParam: tensors_[" << i << "] is nullptr";
return RET_ERROR;
}
if (this->tensors_[i]->data_type() != this->tensors_data_type_) {
if (this->tensors_[i]->data_type() != this->tensor_list_c_.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_;
<< " is not equal to tensors_data_type_:" << this->tensor_list_c_.tensors_data_type_;
return RET_ERROR;
}
}
@ -176,14 +188,15 @@ Tensor *TensorList::GetTensor(int index) {
}
bool TensorList::IsCompatibleShape(const std::vector<int> &shape) {
if (this->tensors_.empty() && this->element_shape_.empty()) {
if (this->tensors_.empty() && this->tensor_list_c_.element_shape_size_ == 0) {
return true;
}
if (shape.size() != this->element_shape_.size()) {
if (shape.size() != this->tensor_list_c_.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]) {
if (this->tensor_list_c_.element_shape_[i] >= 0 && shape[i] >= 0 &&
this->tensor_list_c_.element_shape_[i] != shape[i]) {
return false;
}
}
@ -193,7 +206,7 @@ bool TensorList::IsCompatibleShape(const std::vector<int> &shape) {
bool TensorList::IsCompatibleShape(const Tensor *src) {
MS_CHECK_TRUE_MSG(src != nullptr, false, "src tensor cannot null");
// shape is store in Tensor.
if (static_cast<size_t>(src->ElementsNum()) != this->element_shape_.size()) {
if (static_cast<size_t>(src->ElementsNum()) != this->tensor_list_c_.element_shape_size_) {
return false;
}
if (src->data_type() != kNumberTypeInt && src->data_type() != kNumberTypeInt32) {
@ -201,8 +214,9 @@ bool TensorList::IsCompatibleShape(const Tensor *src) {
return false;
}
auto src_ptr = reinterpret_cast<int *>(src->data());
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]) {
for (size_t i = 0; i < this->tensor_list_c_.element_shape_size_; ++i) {
if (this->tensor_list_c_.element_shape_[i] >= 0 && src_ptr[i] >= 0 &&
this->tensor_list_c_.element_shape_[i] != src_ptr[i]) {
return false;
}
}
@ -214,8 +228,8 @@ STATUS TensorList::Decode(const int *data) {
MS_LOG(ERROR) << "data is nullptr";
return RET_ERROR;
}
tensors_data_type_ = TypeId(data[0]);
if (tensors_data_type_ < kTypeUnknown || tensors_data_type_ > kMonadTypeEnd) {
tensor_list_c_.tensors_data_type_ = TypeId(data[0]);
if (tensor_list_c_.tensors_data_type_ < kTypeUnknown || tensor_list_c_.tensors_data_type_ > kMonadTypeEnd) {
MS_LOG(ERROR) << "TypeId illegal.";
return RET_ERROR;
}
@ -223,10 +237,15 @@ STATUS TensorList::Decode(const int *data) {
MS_LOG(ERROR) << "element shape size illegal.";
return RET_ERROR;
}
for (int j = 0; j < data[1]; ++j) {
element_shape_.push_back(data[2 + j]);
if (data[1] < 0 || data[1] > MAX_SHAPE_SIZE) {
MS_LOG(WARNING) << "The shape-size must be in [0, 8], now is " << data[1];
return RET_ERROR;
}
int tensors_num = data[2 + data[1]];
tensor_list_c_.element_shape_size_ = data[1];
for (int j = 0; j < data[1]; ++j) {
tensor_list_c_.element_shape_[j] = data[kOffset + j];
}
int tensors_num = data[kOffset + data[1]];
if (tensors_num < 0) {
MS_LOG(WARNING) << "not able to create tensors, need infer shape.";
return RET_OK;
@ -238,14 +257,14 @@ STATUS TensorList::Decode(const int *data) {
MS_LOG(WARNING) << "tensor name: " << this->tensor_name_;
}
tensors_.reserve(tensors_num);
int tensor_index = 2 + data[1] + 1;
int tensor_index = kOffset + data[1] + 1;
for (int i = 0; i < tensors_num; i++) {
int tensor_dims_size = data[tensor_index++];
std::vector<int> shape(tensor_dims_size);
for (int j = 0; j < tensor_dims_size; j++) {
shape[j] = data[tensor_index++];
}
auto tensor = new (std::nothrow) Tensor(tensors_data_type_, shape);
auto tensor = new (std::nothrow) Tensor(static_cast<TypeId>(tensor_list_c_.tensors_data_type_), shape);
if (tensor == nullptr) {
MS_LOG(ERROR) << "new Tensor failed";
return RET_NULL_PTR;
@ -263,15 +282,13 @@ TensorList *TensorList::CopyTensorList(const TensorList &src, bool copy_data, Al
MS_LOG(ERROR) << "New tensor failed";
return nullptr;
}
result->data_type_ = src.data_type_;
result->shape_ = src.shape_;
(void)memcpy(&result->tensor_c_, &src.tensor_c_, sizeof(TensorC));
result->tensor_c_.data_ = nullptr;
(void)memcpy(&result->tensor_list_c_, &src.tensor_list_c_, sizeof(TensorListC));
result->tensor_list_c_.tensors_ = nullptr;
result->category_ = src.category_;
result->format_ = src.format_;
result->tensors_data_type_ = src.tensors_data_type_;
result->element_shape_ = src.element_shape_;
result->set_allocator(allocator);
result->set_tensor_name(src.tensor_name() + "_duplicate");
auto src_tensor_dtype = src.tensors_data_type_;
std::vector<std::vector<int> > tensor_shape{};
std::transform(src.tensors_.begin(), src.tensors_.end(), std::back_inserter(tensor_shape),
[](const Tensor *tensor_item) { return tensor_item->shape(); });
@ -283,7 +300,7 @@ TensorList *TensorList::CopyTensorList(const TensorList &src, bool copy_data, Al
if (result->shape().empty()) {
return result;
}
result->MallocTensorListData(src_tensor_dtype, tensor_shape);
result->MallocTensorListData(static_cast<TypeId>(src.tensor_list_c_.tensors_data_type_), tensor_shape);
if (copy_data) {
for (size_t i = 1; i < src.tensors_.size(); ++i) {
auto src_tensor = src.tensors_;

View File

@ -20,6 +20,7 @@
#include <memory>
#include <vector>
#include "include/errorcode.h"
#include "nnacl/tensorlist_c.h"
#include "src/common/log_adapter.h"
#include "schema/model_generated.h"
#include "src/tensor.h"
@ -57,7 +58,7 @@ namespace mindspore::lite {
*/
class TensorList : public Tensor {
public:
TensorList() = default;
TensorList() { tensor_list_c_ = {kObjectTypeTensorType, DEFAULT_FORMAT, 0, kTypeUnknown, -1, nullptr, 0, 0}; }
TensorList(std::vector<int> shape, std::vector<int> element_shape, Category category = VAR);
@ -67,13 +68,27 @@ class TensorList : public Tensor {
TensorList &operator=(const TensorList &tl) = delete;
void set_element_shape(const std::vector<int> &shape) { element_shape_ = shape; }
void set_element_shape(const std::vector<int> &shape) {
if (shape.size() > MAX_SHAPE_SIZE) {
FreeData();
tensor_list_c_.element_shape_size_ = 0;
MS_LOG(WARNING) << "The shape-size has exceeded the limit 8, now is " << shape.size();
return;
}
tensor_list_c_.element_shape_size_ = shape.size();
for (size_t i = 0; i < shape.size(); ++i) {
tensor_list_c_.element_shape_[i] = shape[i];
}
}
std::vector<int> &element_shape() { return element_shape_; }
std::vector<int> element_shape() {
return std::vector<int>(tensor_list_c_.element_shape_,
tensor_list_c_.element_shape_ + tensor_list_c_.element_shape_size_);
}
void set_max_elements_num(int ele_num) { max_elements_num_ = ele_num; }
void set_max_elements_num(int ele_num) { tensor_list_c_.max_elements_num_ = ele_num; }
int max_elements_num() const { return max_elements_num_; }
int max_elements_num() const { return tensor_list_c_.max_elements_num_; }
static TensorList *CopyTensorList(const TensorList &src, bool copy_data = false, AllocatorPtr allocator = nullptr);
@ -89,9 +104,9 @@ class TensorList : public Tensor {
Tensor *GetTensor(int index);
void set_tensors_data_type(TypeId type) { tensors_data_type_ = type; }
void set_tensors_data_type(TypeId type) { tensor_list_c_.tensors_data_type_ = type; }
TypeId tensors_data_type() const { return tensors_data_type_; }
TypeId tensors_data_type() const { return static_cast<TypeId>(tensor_list_c_.tensors_data_type_); }
std::vector<Tensor *> &tensors() { return tensors_; }
@ -173,15 +188,21 @@ class TensorList : public Tensor {
}
}
TensorListC *ConvertToTensorListC() {
tensor_list_c_.format_ = tensor_c_.format_;
tensor_list_c_.shape_value_ = tensor_c_.shape_size_ == 0 ? 0 : tensor_c_.shape_[0];
tensor_list_c_.element_num_ = tensor_c_.shape_size_ == 0 ? 0 : tensors_.size();
tensor_list_c_.tensors_ = nullptr;
return &tensor_list_c_;
}
protected:
// The following functions must be masked.
void *data() const override { return nullptr; }
void *MutableData() override { return nullptr; }
size_t Size() const override { return 0; }
TensorListC tensor_list_c_;
std::vector<Tensor *> tensors_{};
TypeId tensors_data_type_ = kTypeUnknown;
std::vector<int> element_shape_{};
int max_elements_num_ = -1;
};
#else

View File

@ -43,11 +43,12 @@ TEST_F(TensorlistFromtensorInferTest, TensorlistFromtensorInferTest0) {
inputs[1]->shape_[1] = 2;
std::vector<TensorC *> outputs(1, NULL);
outputs[0] = reinterpret_cast<TensorC *>(malloc(sizeof(TensorListC)));
OpParameter *parameter = new OpParameter;
auto out = reinterpret_cast<TensorListC *>(malloc(sizeof(TensorListC)));
out->tensors_ = nullptr;
outputs[0] = reinterpret_cast<TensorC *>(out);
auto *parameter = new OpParameter;
int ret = TensorListFromTensorInferShape((const TensorC **)inputs.data(), inputs.size(), outputs.data(),
outputs.size(), reinterpret_cast<OpParameter *>(parameter));
TensorListC *out = reinterpret_cast<TensorListC *>(outputs[0]);
ASSERT_EQ(ret, NNACL_OK);
ASSERT_EQ(out->element_num_, 4);
ASSERT_EQ(out->data_type_, kObjectTypeTensorType);
@ -57,22 +58,16 @@ TEST_F(TensorlistFromtensorInferTest, TensorlistFromtensorInferTest0) {
ASSERT_EQ(out->tensors_data_type_, kNumberTypeInt32);
// ASSERT_EQ(outputs[0]->format_, Format_NHWC);
for (size_t i = 0; i < out->element_num_; i++) {
ASSERT_EQ(out->tensors_[i].shape_size_, 2);
ASSERT_EQ(out->tensors_[i].shape_[0], 6);
ASSERT_EQ(out->tensors_[i].shape_[1], 5);
ASSERT_EQ(out->tensors_[i]->shape_size_, 2);
ASSERT_EQ(out->tensors_[i]->shape_[0], 6);
ASSERT_EQ(out->tensors_[i]->shape_[1], 5);
}
delete parameter;
for (size_t i = 0; i < inputs_size; i++) {
delete inputs[i];
}
for (size_t i = 0; i < outputs.size(); i++) {
if (outputs[i]->data_type_ == kObjectTypeTensorType) {
TensorListC *tensorListC = reinterpret_cast<TensorListC *>(outputs[i]);
lite::FreeTensorListC(tensorListC);
} else {
delete outputs[i];
}
}
lite::FreeOutTensorC(&outputs);
delete out;
}
} // namespace mindspore

View File

@ -28,24 +28,25 @@ class TensorlistGetItemInferTest : public mindspore::CommonTest {
TEST_F(TensorlistGetItemInferTest, TensorlistGetItemInferTest0) {
size_t inputs_size = 3;
std::vector<TensorC *> inputs(inputs_size, NULL);
TensorListC *input0 = reinterpret_cast<TensorListC *>(malloc(sizeof(TensorListC)));
auto *input0 = reinterpret_cast<TensorListC *>(malloc(sizeof(TensorListC)));
input0->element_num_ = 3;
input0->tensors_ = reinterpret_cast<TensorC *>(malloc(input0->element_num_ * sizeof(TensorC)));
input0->tensors_[0].shape_size_ = 2;
input0->tensors_[0].shape_[0] = 1;
input0->tensors_[0].shape_[1] = 2;
input0->tensors_[0].data_type_ = kNumberTypeInt32;
input0->tensors_[1].shape_size_ = 3;
input0->tensors_[1].shape_[0] = 3;
input0->tensors_[1].shape_[1] = 4;
input0->tensors_[1].shape_[2] = 5;
input0->tensors_[1].data_type_ = kNumberTypeInt32;
input0->tensors_[2].shape_size_ = 4;
input0->tensors_[2].shape_[0] = 6;
input0->tensors_[2].shape_[1] = 7;
input0->tensors_[2].shape_[2] = 8;
input0->tensors_[2].shape_[3] = 9;
input0->tensors_[2].data_type_ = kNumberTypeInt32;
auto in_tensors_c = reinterpret_cast<TensorC *>(malloc(input0->element_num_ * sizeof(TensorC)));
input0->tensors_ = &in_tensors_c;
in_tensors_c[0].shape_size_ = 2;
in_tensors_c[0].shape_[0] = 1;
in_tensors_c[0].shape_[1] = 2;
in_tensors_c[0].data_type_ = kNumberTypeInt32;
in_tensors_c[1].shape_size_ = 3;
in_tensors_c[1].shape_[0] = 3;
in_tensors_c[1].shape_[1] = 4;
in_tensors_c[1].shape_[2] = 5;
in_tensors_c[1].data_type_ = kNumberTypeInt32;
in_tensors_c[2].shape_size_ = 4;
in_tensors_c[2].shape_[0] = 6;
in_tensors_c[2].shape_[1] = 7;
in_tensors_c[2].shape_[2] = 8;
in_tensors_c[2].shape_[3] = 9;
in_tensors_c[2].data_type_ = kNumberTypeInt32;
// input0->tensors_[2]->format_ = Format_NHWC;
inputs[0] = reinterpret_cast<TensorC *>(input0);
inputs[0]->data_type_ = kObjectTypeTensorType;
@ -60,7 +61,7 @@ TEST_F(TensorlistGetItemInferTest, TensorlistGetItemInferTest0) {
std::vector<TensorC *> outputs(1, NULL);
outputs[0] = reinterpret_cast<TensorC *>(malloc(sizeof(TensorC)));
OpParameter *parameter = new OpParameter;
auto *parameter = new OpParameter;
int ret = TensorListGetItemInferShape((const TensorC **)inputs.data(), inputs.size(), outputs.data(), outputs.size(),
reinterpret_cast<OpParameter *>(parameter));
ASSERT_EQ(ret, NNACL_OK);
@ -75,11 +76,10 @@ TEST_F(TensorlistGetItemInferTest, TensorlistGetItemInferTest0) {
delete parameter;
for (size_t i = 0; i < inputs_size; i++) {
if (inputs[i]->data_type_ == kObjectTypeTensorType) {
TensorListC *tensorListC = reinterpret_cast<TensorListC *>(inputs[i]);
lite::FreeTensorListC(tensorListC);
} else {
free(inputs[i]);
auto *tensorList_c = reinterpret_cast<TensorListC *>(inputs[i]);
free(*tensorList_c->tensors_);
}
free(inputs[i]);
}
for (size_t i = 0; i < outputs.size(); i++) {
free(outputs[i]);

View File

@ -14,6 +14,7 @@
* limitations under the License.
*/
#include "common/common_test.h"
#include "src/common/tensor_util.h"
#include "nnacl/infer/control/tensorlist_reserve_infer.h"
namespace mindspore {
@ -41,11 +42,12 @@ TEST_F(TensorlistReserveInferTest, TensorlistReserveInferTest0) {
inputs[1]->data_type_ = kNumberTypeInt32;
std::vector<TensorC *> outputs(1, NULL);
outputs[0] = reinterpret_cast<TensorC *>(new TensorListC);
OpParameter *parameter = new OpParameter;
auto out = reinterpret_cast<TensorListC *>(malloc(sizeof(TensorListC)));
out->tensors_ = nullptr;
outputs[0] = reinterpret_cast<TensorC *>(out);
auto *parameter = new OpParameter;
int ret = TensorListReserveInferShape((const TensorC **)inputs.data(), inputs.size(), outputs.data(), outputs.size(),
reinterpret_cast<OpParameter *>(parameter));
TensorListC *out = reinterpret_cast<TensorListC *>(outputs[0]);
ASSERT_EQ(ret, NNACL_OK);
ASSERT_EQ(out->element_num_, 5);
ASSERT_EQ(out->data_type_, kObjectTypeTensorType);
@ -56,15 +58,14 @@ TEST_F(TensorlistReserveInferTest, TensorlistReserveInferTest0) {
ASSERT_EQ(out->tensors_data_type_, kTypeUnknown);
// ASSERT_EQ(outputs[0]->format_, Format_NHWC);
for (size_t i = 0; i < out->element_num_; i++) {
ASSERT_EQ(out->tensors_[i].shape_size_, 0);
ASSERT_EQ(out->tensors_[i]->shape_size_, 0);
}
delete parameter;
for (size_t i = 0; i < inputs_size; i++) {
delete inputs[i];
}
for (size_t i = 0; i < outputs.size(); i++) {
delete outputs[i];
}
lite::FreeOutTensorC(&outputs);
delete out;
}
} // namespace mindspore

View File

@ -14,6 +14,7 @@
* limitations under the License.
*/
#include "common/common_test.h"
#include "src/common/tensor_util.h"
#include "nnacl/infer/control/tensorlist_setitem_infer.h"
namespace mindspore {
@ -27,29 +28,30 @@ class TensorlistSetItemInferTest : public mindspore::CommonTest {
TEST_F(TensorlistSetItemInferTest, TensorlistSetItemInferTest0) {
size_t inputs_size = 3;
std::vector<TensorC *> inputs(inputs_size, NULL);
TensorListC *input0 = new TensorListC;
auto *input0 = new TensorListC;
input0->element_num_ = 3;
input0->tensors_ = reinterpret_cast<TensorC *>(malloc(input0->element_num_ * sizeof(TensorC)));
auto in_tensors_c = reinterpret_cast<TensorC *>(malloc(input0->element_num_ * sizeof(TensorC)));
input0->tensors_ = &in_tensors_c;
input0->element_shape_size_ = 2;
input0->element_shape_[0] = 2;
input0->element_shape_[1] = 4;
input0->tensors_data_type_ = kNumberTypeInt32;
input0->data_type_ = kObjectTypeTensorType;
input0->tensors_[0].shape_size_ = 2;
input0->tensors_[0].shape_[0] = 2;
input0->tensors_[0].shape_[1] = 4;
input0->tensors_[0].data_type_ = kNumberTypeInt32;
in_tensors_c[0].shape_size_ = 2;
in_tensors_c[0].shape_[0] = 2;
in_tensors_c[0].shape_[1] = 4;
in_tensors_c[0].data_type_ = kNumberTypeInt32;
input0->tensors_[1].shape_size_ = 2;
input0->tensors_[1].shape_[0] = 2;
input0->tensors_[1].shape_[1] = 4;
input0->tensors_[1].data_type_ = kNumberTypeInt32;
in_tensors_c[1].shape_size_ = 2;
in_tensors_c[1].shape_[0] = 2;
in_tensors_c[1].shape_[1] = 4;
in_tensors_c[1].data_type_ = kNumberTypeInt32;
input0->tensors_[2].shape_size_ = 2;
input0->tensors_[2].shape_[0] = 2;
input0->tensors_[2].shape_[1] = 4;
input0->tensors_[2].data_type_ = kNumberTypeInt32;
in_tensors_c[2].shape_size_ = 2;
in_tensors_c[2].shape_[0] = 2;
in_tensors_c[2].shape_[1] = 4;
in_tensors_c[2].data_type_ = kNumberTypeInt32;
// input0->tensors_[2]->format_ = Format_NHWC;
inputs[0] = reinterpret_cast<TensorC *>(input0);
@ -69,11 +71,13 @@ TEST_F(TensorlistSetItemInferTest, TensorlistSetItemInferTest0) {
inputs[2]->data_ = inputs2_data.data();
std::vector<TensorC *> outputs(1, NULL);
outputs[0] = reinterpret_cast<TensorC *>(new TensorListC);
OpParameter *parameter = new OpParameter;
auto out = reinterpret_cast<TensorListC *>(malloc(sizeof(TensorListC)));
out->tensors_ = nullptr;
outputs[0] = reinterpret_cast<TensorC *>(out);
auto *parameter = new OpParameter;
int ret = TensorListSetItemInferShape((const TensorC **)inputs.data(), inputs.size(), outputs.data(), outputs.size(),
reinterpret_cast<OpParameter *>(parameter));
TensorListC *res = reinterpret_cast<TensorListC *>(outputs[0]);
auto *res = reinterpret_cast<TensorListC *>(outputs[0]);
ASSERT_EQ(ret, NNACL_OK);
ASSERT_EQ(res->element_num_, 3);
ASSERT_EQ(res->element_shape_size_, 2);
@ -81,25 +85,28 @@ TEST_F(TensorlistSetItemInferTest, TensorlistSetItemInferTest0) {
ASSERT_EQ(res->element_shape_[1], 4);
ASSERT_EQ(res->tensors_data_type_, kNumberTypeInt32);
ASSERT_EQ(res->data_type_, kObjectTypeTensorType);
ASSERT_EQ(res->tensors_[0].shape_size_, 2);
ASSERT_EQ(res->tensors_[0].shape_[0], 2);
ASSERT_EQ(res->tensors_[0].shape_[1], 4);
ASSERT_EQ(res->tensors_[1].shape_size_, 2);
ASSERT_EQ(res->tensors_[1].shape_[0], 2);
ASSERT_EQ(res->tensors_[1].shape_[1], 4);
ASSERT_EQ(res->tensors_[2].shape_size_, 2);
ASSERT_EQ(res->tensors_[2].shape_[0], 5);
ASSERT_EQ(res->tensors_[2].shape_[1], 6);
ASSERT_EQ(res->tensors_[0]->shape_size_, 2);
ASSERT_EQ(res->tensors_[0]->shape_[0], 2);
ASSERT_EQ(res->tensors_[0]->shape_[1], 4);
ASSERT_EQ(res->tensors_[1]->shape_size_, 2);
ASSERT_EQ(res->tensors_[1]->shape_[0], 2);
ASSERT_EQ(res->tensors_[1]->shape_[1], 4);
ASSERT_EQ(res->tensors_[2]->shape_size_, 2);
ASSERT_EQ(res->tensors_[2]->shape_[0], 5);
ASSERT_EQ(res->tensors_[2]->shape_[1], 6);
// ASSERT_EQ(outputs[0]->format_, Format_NHWC);
delete parameter;
for (size_t i = 0; i < inputs_size; i++) {
if (inputs[i]->data_type_ == kObjectTypeTensorType) {
auto *tensorList_c = reinterpret_cast<TensorListC *>(inputs[i]);
free(*tensorList_c->tensors_);
}
delete inputs[i];
}
for (size_t i = 0; i < outputs.size(); i++) {
delete outputs[i];
}
lite::FreeOutTensorC(&outputs);
delete out;
}
// retest mergeshape

View File

@ -27,28 +27,29 @@ class TensorlistStackInferTest : public mindspore::CommonTest {
TEST_F(TensorlistStackInferTest, TensorlistStackInferTest0) {
size_t inputs_size = 2;
std::vector<TensorC *> inputs(inputs_size, NULL);
TensorListC *input0 = new TensorListC;
auto *input0 = new TensorListC;
input0->element_num_ = 3;
input0->tensors_ = reinterpret_cast<TensorC *>(malloc(input0->element_num_ * sizeof(TensorC)));
auto in_tensors_c = reinterpret_cast<TensorC *>(malloc(input0->element_num_ * sizeof(TensorC)));
input0->tensors_ = &in_tensors_c;
input0->element_shape_size_ = 2;
input0->element_shape_[0] = 2;
input0->element_shape_[1] = 4;
input0->tensors_data_type_ = kNumberTypeInt32;
input0->tensors_[0].shape_size_ = 2;
input0->tensors_[0].shape_[0] = 2;
input0->tensors_[0].shape_[1] = 4;
input0->tensors_[0].data_type_ = kNumberTypeInt32;
in_tensors_c[0].shape_size_ = 2;
in_tensors_c[0].shape_[0] = 2;
in_tensors_c[0].shape_[1] = 4;
in_tensors_c[0].data_type_ = kNumberTypeInt32;
input0->tensors_[1].shape_size_ = 2;
input0->tensors_[1].shape_[0] = 2;
input0->tensors_[1].shape_[1] = 4;
input0->tensors_[1].data_type_ = kNumberTypeInt32;
in_tensors_c[1].shape_size_ = 2;
in_tensors_c[1].shape_[0] = 2;
in_tensors_c[1].shape_[1] = 4;
in_tensors_c[1].data_type_ = kNumberTypeInt32;
input0->tensors_[2].shape_size_ = 2;
input0->tensors_[2].shape_[0] = 2;
input0->tensors_[2].shape_[1] = 4;
input0->tensors_[2].data_type_ = kNumberTypeInt32;
in_tensors_c[2].shape_size_ = 2;
in_tensors_c[2].shape_[0] = 2;
in_tensors_c[2].shape_[1] = 4;
in_tensors_c[2].data_type_ = kNumberTypeInt32;
// input0->tensors_[2]->format_ = Format_NHWC;
inputs[0] = reinterpret_cast<TensorC *>(input0);
inputs[0]->data_type_ = kObjectTypeTensorType;
@ -61,7 +62,7 @@ TEST_F(TensorlistStackInferTest, TensorlistStackInferTest0) {
std::vector<TensorC *> outputs(1, NULL);
outputs[0] = new TensorC;
OpParameter *parameter = new OpParameter;
auto *parameter = new OpParameter;
int ret = TensorListStackInferShape((const TensorC **)inputs.data(), inputs.size(), outputs.data(), outputs.size(),
reinterpret_cast<OpParameter *>(parameter));
ASSERT_EQ(ret, NNACL_OK);
@ -74,6 +75,10 @@ TEST_F(TensorlistStackInferTest, TensorlistStackInferTest0) {
delete parameter;
for (size_t i = 0; i < inputs_size; i++) {
if (inputs[i]->data_type_ == kObjectTypeTensorType) {
auto *tensorList_c = reinterpret_cast<TensorListC *>(inputs[i]);
free(*tensorList_c->tensors_);
}
delete inputs[i];
}
for (size_t i = 0; i < outputs.size(); i++) {

View File

@ -193,8 +193,8 @@ void NNaclFp32Serializer::CodeArrayStruct(const std::string &name, TensorC *tens
int size = tensor.size();
for (int i = 0; i < size; ++i) {
std::string tensor_name = "tensor" + std::to_string(count++);
CodeBaseStruct<false>("TensorC", name, tensor_name, tensorC[i].is_ready_, tensorC[i].data_type_, tensorC[i].format_,
tensor[i], tensorC[i].shape_size_, ToString(tensorC[i].shape_));
CodeBaseStruct<false>("TensorC", name, tensor_name, tensorC[i].data_type_, tensorC[i].format_, tensor[i],
tensorC[i].shape_size_, ToString(tensorC[i].shape_));
tensor_names.emplace_back(tensor_name);
}
code << " TensorC"

View File

@ -175,6 +175,7 @@ getCommonFile() {
mindspore/lite/experimental/src/exec_env_utils.h
mindspore/lite/src/expression/ops_utils.h
mindspore/ccsrc/plugin/device/cpu/kernel/nnacl/tensor_c_utils.h
mindspore/ccsrc/plugin/device/cpu/kernel/nnacl/tensorlist_c.h
mindspore/ccsrc/plugin/device/cpu/kernel/nnacl/tensorlist_c_utils.h
mindspore/core/utils/log_adapter.h
mindspore/core/ir/api_tensor_impl.h