c2bbc5a66187cc515cf61ba6f1a884ed1836dedd
[platform/core/ml/nnfw.git] / runtime / onert / core / src / backend / basic / Tensor.cc
1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "backend/basic/Tensor.h"
18
19 #include "ir/DataType.h"
20 #include "backend/basic/MemoryManager.h"
21
22 namespace onert
23 {
24 namespace backend
25 {
26 namespace basic
27 {
28
29 Tensor::~Tensor() {}
30
31 size_t Tensor::calcOffset(const ir::Coordinates &coords) const
32 {
33   auto shape = getShape();
34   size_t rank = shape.rank();
35   rank = rank == 0 ? 1 : rank;
36   size_t offset = 0;
37   for (size_t i = 0; i < rank; ++i)
38   {
39     auto dim = shape.rank() == 0 ? 1 : shape.dim(i);
40     offset = offset * dim + coords[i];
41   }
42   offset *= sizeOfDataType(data_type());
43   return offset;
44 }
45
46 void Tensor::setShape(const ir::Shape &new_shape) { _info.shape(new_shape); }
47
48 bool Tensor::applyShape(const ir::Shape &new_shape)
49 {
50   bool previously_dynamic = is_dynamic();
51
52   auto allocTensorMem = [&]() {
53     auto capacity = total_size();
54     auto alloc = _dynamic_mem_mgr->allocate(this, capacity);
55     setBuffer(alloc);
56   };
57
58   if (!previously_dynamic || buffer() == nullptr)
59   {
60     // Always set shape - when buffer with same size was already allocated, shape could differ
61     setShape(new_shape);
62     set_dynamic();
63     allocTensorMem();
64   }
65   else
66   {
67     auto previous_size = total_size();
68     auto new_size = new_shape.num_elements() * ir::sizeOfDataType(data_type());
69     if (previous_size != new_size)
70     {
71       _dynamic_mem_mgr->deallocate(this);
72
73       setShape(new_shape);
74       set_dynamic();
75       allocTensorMem();
76     }
77     else
78     { // when buffer with same size was already allocated, shape could differ
79       setShape(new_shape);
80     }
81   }
82   return true;
83 }
84
85 ir::Shape Tensor::getShape() const { return _info.shape(); }
86
87 void Tensor::deallocBuffer()
88 {
89   if (_allocator)
90   {
91     _buffer = nullptr;
92     _allocator.reset();
93     if (_dynamic_mem_mgr)
94     {
95       _dynamic_mem_mgr->deallocate(this);
96     }
97   }
98 }
99
100 } // namespace basic
101 } // namespace backend
102 } // namespace onert
103
104 // ExternalTensor
105
106 namespace onert
107 {
108 namespace backend
109 {
110 namespace basic
111 {
112
113 // `dynamic_cast` not working across library boundaries on NDK
114 // With this as a key function, `dynamic_cast` works across dl
115 ExternalTensor::~ExternalTensor() {}
116
117 } // namespace basic
118 } // namespace backend
119 } // namespace onert