blob: 6092c5fc9055da3158fcae9623ec2c9107a330be [file] [log] [blame]
telsoa01c577f2c2018-08-31 09:22:23 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
David Beckecb56cd2018-09-05 12:52:57 +01003// SPDX-License-Identifier: MIT
telsoa01c577f2c2018-08-31 09:22:23 +01004//
5
6#pragma once
7
Matteo Martincigh747ef822018-12-18 09:26:39 +00008#include "CpuTensorHandle.hpp"
Kevin May665a964a2019-08-21 16:53:50 +01009#include "ITensorHandle.hpp"
telsoa01c577f2c2018-08-31 09:22:23 +010010
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000011#include <armnn/Tensor.hpp>
12
Matteo Martincighe011d202019-11-28 11:35:47 +000013#include <armnnUtils/Permute.hpp>
14
Kevin May665a964a2019-08-21 16:53:50 +010015#include <Half.hpp>
Matteo Martincigh747ef822018-12-18 09:26:39 +000016#include <Profiling.hpp>
Matteo Martincigh747ef822018-12-18 09:26:39 +000017
telsoa01c577f2c2018-08-31 09:22:23 +010018#include <boost/cast.hpp>
19
20namespace armnn
21{
22namespace
23{
Matteo Martincigh747ef822018-12-18 09:26:39 +000024
Kevin May665a964a2019-08-21 16:53:50 +010025template <typename ArrayType, typename Arg>
telsoa01c577f2c2018-08-31 09:22:23 +010026void AssignValues(unsigned int num, unsigned int& idx, const ArrayType& array, Arg& arg)
27{
Matteo Martincigh747ef822018-12-18 09:26:39 +000028 if (idx >= num)
29 {
30 return;
31 }
telsoa01c577f2c2018-08-31 09:22:23 +010032
Matteo Martincigh747ef822018-12-18 09:26:39 +000033 arg = array[(num - 1) - idx];
34 idx++;
35}
telsoa01c577f2c2018-08-31 09:22:23 +010036
Kevin May665a964a2019-08-21 16:53:50 +010037template <typename T, typename ArrayType, typename... Args>
38void AssignValues(unsigned int num, unsigned int idx, const ArrayType& array, T& assignee, Args&... args)
telsoa01c577f2c2018-08-31 09:22:23 +010039{
Matteo Martincigh747ef822018-12-18 09:26:39 +000040 AssignValues(num, idx, array, assignee);
telsoa01c577f2c2018-08-31 09:22:23 +010041
Matteo Martincigh747ef822018-12-18 09:26:39 +000042 AssignValues(num, idx, array, args...);
telsoa01c577f2c2018-08-31 09:22:23 +010043}
Matteo Martincigh747ef822018-12-18 09:26:39 +000044
Kevin May665a964a2019-08-21 16:53:50 +010045} // anonymous namespace
telsoa01c577f2c2018-08-31 09:22:23 +010046
Kevin May665a964a2019-08-21 16:53:50 +010047template <typename CopyFunc>
telsoa01c577f2c2018-08-31 09:22:23 +010048void CopyTensorContentsGeneric(const ITensorHandle* srcTensor, ITensorHandle* dstTensor, CopyFunc copy)
49{
Matthew Benthamefdbca62019-09-14 23:35:28 +010050 // For ease of understanding, names are assigned to the dimensions
51 // of the tensor as if NHWC, however this routine works with any 5D tensor
Matthew Jacksondba634f2019-08-15 15:14:18 +010052 static_assert(MaxNumOfTensorDimensions == 5, "Please update CopyTensorContents");
telsoa01c577f2c2018-08-31 09:22:23 +010053
Kevin May665a964a2019-08-21 16:53:50 +010054 TensorShape srcStrides = srcTensor->GetStrides();
telsoa01c577f2c2018-08-31 09:22:23 +010055 const TensorShape& srcShape = srcTensor->GetShape();
Kevin May665a964a2019-08-21 16:53:50 +010056 TensorShape dstStrides = dstTensor->GetStrides();
telsoa01c577f2c2018-08-31 09:22:23 +010057 const TensorShape& dstShape = dstTensor->GetShape();
58
Kevin May665a964a2019-08-21 16:53:50 +010059 size_t srcDepth = 1;
60 size_t srcBatches = 1;
Kevin May665a964a2019-08-21 16:53:50 +010061 size_t srcHeight = 1;
62 size_t srcWidth = 1;
Matthew Benthamefdbca62019-09-14 23:35:28 +010063 size_t srcChannels = 1;
Kevin May665a964a2019-08-21 16:53:50 +010064 AssignValues(srcShape.GetNumDimensions(),
65 0,
66 srcShape,
Matthew Benthamefdbca62019-09-14 23:35:28 +010067 srcChannels,
telsoa01c577f2c2018-08-31 09:22:23 +010068 srcWidth,
69 srcHeight,
Matthew Jacksondba634f2019-08-15 15:14:18 +010070 srcBatches,
71 srcDepth);
telsoa01c577f2c2018-08-31 09:22:23 +010072
Kevin May665a964a2019-08-21 16:53:50 +010073 size_t srcDepthStride = 0;
74 size_t srcBatchStride = 0;
Kevin May665a964a2019-08-21 16:53:50 +010075 size_t srcHeightStride = 0;
76 size_t srcWidthStride = 0;
Matthew Benthamefdbca62019-09-14 23:35:28 +010077 size_t srcChannelStride = 0;
Kevin May665a964a2019-08-21 16:53:50 +010078 AssignValues(srcStrides.GetNumDimensions(),
79 0,
80 srcStrides,
Matthew Benthamefdbca62019-09-14 23:35:28 +010081 srcChannelStride,
telsoa01c577f2c2018-08-31 09:22:23 +010082 srcWidthStride,
83 srcHeightStride,
Matthew Jacksondba634f2019-08-15 15:14:18 +010084 srcBatchStride,
85 srcDepthStride);
telsoa01c577f2c2018-08-31 09:22:23 +010086
Kevin May665a964a2019-08-21 16:53:50 +010087 size_t dstDepth = 1;
88 size_t dstBatches = 1;
Kevin May665a964a2019-08-21 16:53:50 +010089 size_t dstHeight = 1;
90 size_t dstWidth = 1;
Matthew Benthamefdbca62019-09-14 23:35:28 +010091 size_t dstChannels = 1;
Kevin May665a964a2019-08-21 16:53:50 +010092 AssignValues(dstShape.GetNumDimensions(),
93 0,
94 dstShape,
Matthew Benthamefdbca62019-09-14 23:35:28 +010095 dstChannels,
telsoa01c577f2c2018-08-31 09:22:23 +010096 dstWidth,
97 dstHeight,
Matthew Jacksondba634f2019-08-15 15:14:18 +010098 dstBatches,
99 dstDepth);
telsoa01c577f2c2018-08-31 09:22:23 +0100100
Kevin May665a964a2019-08-21 16:53:50 +0100101 size_t dstDepthStride = 0;
102 size_t dstBatchStride = 0;
Kevin May665a964a2019-08-21 16:53:50 +0100103 size_t dstHeightStride = 0;
104 size_t dstWidthStride = 0;
Matthew Benthamefdbca62019-09-14 23:35:28 +0100105 size_t dstChannelStride = 0;
Kevin May665a964a2019-08-21 16:53:50 +0100106 AssignValues(dstStrides.GetNumDimensions(),
107 0,
108 dstStrides,
Matthew Benthamefdbca62019-09-14 23:35:28 +0100109 dstChannelStride,
telsoa01c577f2c2018-08-31 09:22:23 +0100110 dstWidthStride,
111 dstHeightStride,
Matthew Jacksondba634f2019-08-15 15:14:18 +0100112 dstBatchStride,
113 dstDepthStride);
telsoa01c577f2c2018-08-31 09:22:23 +0100114
Sadik Armaganbf86d512018-12-24 09:01:31 +0000115 const unsigned char* srcData;
116 unsigned char* dstData;
117 {
118 ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "Synchronize buffers");
Kevin May665a964a2019-08-21 16:53:50 +0100119 srcData = static_cast<const uint8_t*>(srcTensor->Map());
120 dstData = static_cast<uint8_t*>(dstTensor->Map());
Sadik Armaganbf86d512018-12-24 09:01:31 +0000121 }
telsoa01c577f2c2018-08-31 09:22:23 +0100122
Matthew Benthamefdbca62019-09-14 23:35:28 +0100123 size_t copyLength = std::min(srcChannels*srcChannelStride, dstChannels*dstChannelStride);
124 size_t copyWidth = std::min(srcWidth, dstWidth);
125 size_t copyHeight = std::min(srcHeight, dstHeight);
126 size_t copyBatches = std::min(srcBatches, dstBatches);
127 size_t copyDepth = std::min(srcDepth, dstDepth);
telsoa01c577f2c2018-08-31 09:22:23 +0100128
Matthew Bentham019c4b12019-09-15 00:06:05 +0100129 // Coalesce inner dimensions where possible
130 // to reduce overheard calling copy() and to
131 // allow for memory bandwidth optimisations
132 if (copyLength == srcWidthStride &&
133 copyLength == dstWidthStride)
134 {
135 // There is no special padding between rows,
136 // and sizes are compatible, so copy whole rows
137 copyLength *= copyWidth;
138 copyWidth = 1;
139
140 if (copyLength == srcHeightStride &&
141 copyLength == dstHeightStride)
142 {
143 // There is no special padding between batches
144 // and sizes are compatible so copy whole batches
145 copyLength *= copyHeight;
146 copyHeight = 1;
147 }
148 }
149
Kevin May665a964a2019-08-21 16:53:50 +0100150 for (unsigned int d = 0; d < copyDepth; ++d)
telsoa01c577f2c2018-08-31 09:22:23 +0100151 {
Matthew Jacksondba634f2019-08-15 15:14:18 +0100152 auto srcPtrDepth = srcData;
153 auto dstPtrDepth = dstData;
Kevin May665a964a2019-08-21 16:53:50 +0100154 for (unsigned int b = 0; b < copyBatches; ++b)
telsoa01c577f2c2018-08-31 09:22:23 +0100155 {
Matthew Jacksondba634f2019-08-15 15:14:18 +0100156 auto srcPtrBatch = srcData;
157 auto dstPtrBatch = dstData;
Matthew Benthamefdbca62019-09-14 23:35:28 +0100158 for (unsigned int h = 0; h < copyHeight; ++h)
telsoa01c577f2c2018-08-31 09:22:23 +0100159 {
Matthew Jacksondba634f2019-08-15 15:14:18 +0100160 auto srcPtrChannel = srcData;
161 auto dstPtrChannel = dstData;
Matthew Benthamefdbca62019-09-14 23:35:28 +0100162 for (unsigned int w = 0; w < copyWidth; ++w)
Matthew Jacksondba634f2019-08-15 15:14:18 +0100163 {
164 copy(dstData, srcData, copyLength);
Matthew Benthamefdbca62019-09-14 23:35:28 +0100165 dstData += dstWidthStride;
166 srcData += srcWidthStride;
Matthew Jacksondba634f2019-08-15 15:14:18 +0100167 }
Matthew Benthamefdbca62019-09-14 23:35:28 +0100168 dstData += (static_cast<long>(dstHeightStride) - (dstData - dstPtrChannel));
169 srcData += (static_cast<long>(srcHeightStride) - (srcData - srcPtrChannel));
telsoa01c577f2c2018-08-31 09:22:23 +0100170 }
Kevin May665a964a2019-08-21 16:53:50 +0100171 dstData += (static_cast<long>(dstBatchStride) - (dstData - dstPtrBatch));
172 srcData += (static_cast<long>(srcBatchStride) - (srcData - srcPtrBatch));
telsoa01c577f2c2018-08-31 09:22:23 +0100173 }
Kevin May665a964a2019-08-21 16:53:50 +0100174 dstData += (static_cast<long>(dstDepthStride) - (dstData - dstPtrDepth));
175 srcData += (static_cast<long>(srcDepthStride) - (srcData - srcPtrDepth));
telsoa01c577f2c2018-08-31 09:22:23 +0100176 }
177
178 srcTensor->Unmap();
179 dstTensor->Unmap();
180}
181
182template <typename SrcTensorHandleType, typename DstTensorHandleType, typename DescriptorType>
183void GatherTensorHandlePairs(const DescriptorType& descriptor,
184 std::vector<std::pair<SrcTensorHandleType*, DstTensorHandleType*>>& tensorHandlePairs)
185{
186 const unsigned int numInputs = static_cast<unsigned int>(descriptor.m_Inputs.size());
187 tensorHandlePairs.reserve(numInputs);
188
189 for (unsigned int i = 0; i < numInputs; ++i)
190 {
Kevin May665a964a2019-08-21 16:53:50 +0100191 SrcTensorHandleType* const srcTensorHandle =
192 boost::polymorphic_downcast<SrcTensorHandleType*>(descriptor.m_Inputs[i]);
193 DstTensorHandleType* const dstTensorHandle =
194 boost::polymorphic_downcast<DstTensorHandleType*>(descriptor.m_Outputs[i]);
telsoa01c577f2c2018-08-31 09:22:23 +0100195
196 tensorHandlePairs.emplace_back(srcTensorHandle, dstTensorHandle);
197 }
198}
199
Francis Murtaghec33a912019-11-05 14:26:23 +0000200int32_t ConvertMaskToACLFormat(int32_t mask, int32_t numDim);
201
Matteo Martincigh747ef822018-12-18 09:26:39 +0000202armnn::ConstTensor PermuteTensor(const ConstCpuTensorHandle* tensor,
203 const PermutationVector& permutationVector,
204 void* permuteBuffer);
205
206void ReshapeWeightsForAcl(TensorInfo& weightInfo, DataLayout dataLayout);
207
208TensorInfo ConvertWeightTensorInfoFromArmnnToAcl(const TensorInfo& weightInfo, DataLayout dataLayout);
209
210armnn::ConstTensor ConvertWeightTensorFromArmnnToAcl(const ConstCpuTensorHandle* weightTensor,
211 DataLayout dataLayout,
212 void* permuteBuffer);
213
Kevin May665a964a2019-08-21 16:53:50 +0100214} //namespace armnn