blob: 06d2eccf3e58e3006d7da50857cadf91b83ebd55 [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
James Conroy1f58f032021-04-27 17:13:27 +01008#include "TensorHandle.hpp"
Matteo Martincighe5b8eb92019-11-28 15:45:42 +00009
10#include <armnn/backends/ITensorHandle.hpp>
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000011#include <armnn/Tensor.hpp>
Jan Eilersbb446e52020-04-02 13:56:54 +010012#include <armnn/utility/PolymorphicDowncast.hpp>
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
19namespace armnn
20{
21namespace
22{
Matteo Martincigh747ef822018-12-18 09:26:39 +000023
Kevin May665a964a2019-08-21 16:53:50 +010024template <typename ArrayType, typename Arg>
telsoa01c577f2c2018-08-31 09:22:23 +010025void AssignValues(unsigned int num, unsigned int& idx, const ArrayType& array, Arg& arg)
26{
Matteo Martincigh747ef822018-12-18 09:26:39 +000027 if (idx >= num)
28 {
29 return;
30 }
telsoa01c577f2c2018-08-31 09:22:23 +010031
Matteo Martincigh747ef822018-12-18 09:26:39 +000032 arg = array[(num - 1) - idx];
33 idx++;
34}
telsoa01c577f2c2018-08-31 09:22:23 +010035
Kevin May665a964a2019-08-21 16:53:50 +010036template <typename T, typename ArrayType, typename... Args>
37void AssignValues(unsigned int num, unsigned int idx, const ArrayType& array, T& assignee, Args&... args)
telsoa01c577f2c2018-08-31 09:22:23 +010038{
Matteo Martincigh747ef822018-12-18 09:26:39 +000039 AssignValues(num, idx, array, assignee);
telsoa01c577f2c2018-08-31 09:22:23 +010040
Matteo Martincigh747ef822018-12-18 09:26:39 +000041 AssignValues(num, idx, array, args...);
telsoa01c577f2c2018-08-31 09:22:23 +010042}
Matteo Martincigh747ef822018-12-18 09:26:39 +000043
Kevin May665a964a2019-08-21 16:53:50 +010044} // anonymous namespace
telsoa01c577f2c2018-08-31 09:22:23 +010045
Kevin May665a964a2019-08-21 16:53:50 +010046template <typename CopyFunc>
telsoa01c577f2c2018-08-31 09:22:23 +010047void CopyTensorContentsGeneric(const ITensorHandle* srcTensor, ITensorHandle* dstTensor, CopyFunc copy)
48{
Matthew Benthamefdbca62019-09-14 23:35:28 +010049 // For ease of understanding, names are assigned to the dimensions
50 // of the tensor as if NHWC, however this routine works with any 5D tensor
Matthew Jacksondba634f2019-08-15 15:14:18 +010051 static_assert(MaxNumOfTensorDimensions == 5, "Please update CopyTensorContents");
telsoa01c577f2c2018-08-31 09:22:23 +010052
Kevin May665a964a2019-08-21 16:53:50 +010053 TensorShape srcStrides = srcTensor->GetStrides();
telsoa01c577f2c2018-08-31 09:22:23 +010054 const TensorShape& srcShape = srcTensor->GetShape();
Rob Hughes9934e4e2019-11-27 14:27:11 +000055 const auto srcSize = srcTensor->GetStrides()[0] * srcShape[0];
Jan Eilers8eb25602020-03-09 12:13:48 +000056 IgnoreUnused(srcSize); // Only used for asserts
Kevin May665a964a2019-08-21 16:53:50 +010057 TensorShape dstStrides = dstTensor->GetStrides();
telsoa01c577f2c2018-08-31 09:22:23 +010058 const TensorShape& dstShape = dstTensor->GetShape();
Rob Hughes9934e4e2019-11-27 14:27:11 +000059 const auto dstSize = dstTensor->GetStrides()[0] * dstShape[0];
Jan Eilers8eb25602020-03-09 12:13:48 +000060 IgnoreUnused(dstSize); // Only used for asserts
telsoa01c577f2c2018-08-31 09:22:23 +010061
Kevin May665a964a2019-08-21 16:53:50 +010062 size_t srcDepth = 1;
63 size_t srcBatches = 1;
Kevin May665a964a2019-08-21 16:53:50 +010064 size_t srcHeight = 1;
65 size_t srcWidth = 1;
Matthew Benthamefdbca62019-09-14 23:35:28 +010066 size_t srcChannels = 1;
Kevin May665a964a2019-08-21 16:53:50 +010067 AssignValues(srcShape.GetNumDimensions(),
68 0,
69 srcShape,
Matthew Benthamefdbca62019-09-14 23:35:28 +010070 srcChannels,
telsoa01c577f2c2018-08-31 09:22:23 +010071 srcWidth,
72 srcHeight,
Matthew Jacksondba634f2019-08-15 15:14:18 +010073 srcBatches,
74 srcDepth);
telsoa01c577f2c2018-08-31 09:22:23 +010075
Kevin May665a964a2019-08-21 16:53:50 +010076 size_t srcDepthStride = 0;
77 size_t srcBatchStride = 0;
Kevin May665a964a2019-08-21 16:53:50 +010078 size_t srcHeightStride = 0;
79 size_t srcWidthStride = 0;
Matthew Benthamefdbca62019-09-14 23:35:28 +010080 size_t srcChannelStride = 0;
Kevin May665a964a2019-08-21 16:53:50 +010081 AssignValues(srcStrides.GetNumDimensions(),
82 0,
83 srcStrides,
Matthew Benthamefdbca62019-09-14 23:35:28 +010084 srcChannelStride,
telsoa01c577f2c2018-08-31 09:22:23 +010085 srcWidthStride,
86 srcHeightStride,
Matthew Jacksondba634f2019-08-15 15:14:18 +010087 srcBatchStride,
88 srcDepthStride);
telsoa01c577f2c2018-08-31 09:22:23 +010089
Kevin May665a964a2019-08-21 16:53:50 +010090 size_t dstDepth = 1;
91 size_t dstBatches = 1;
Kevin May665a964a2019-08-21 16:53:50 +010092 size_t dstHeight = 1;
93 size_t dstWidth = 1;
Matthew Benthamefdbca62019-09-14 23:35:28 +010094 size_t dstChannels = 1;
Kevin May665a964a2019-08-21 16:53:50 +010095 AssignValues(dstShape.GetNumDimensions(),
96 0,
97 dstShape,
Matthew Benthamefdbca62019-09-14 23:35:28 +010098 dstChannels,
telsoa01c577f2c2018-08-31 09:22:23 +010099 dstWidth,
100 dstHeight,
Matthew Jacksondba634f2019-08-15 15:14:18 +0100101 dstBatches,
102 dstDepth);
telsoa01c577f2c2018-08-31 09:22:23 +0100103
Kevin May665a964a2019-08-21 16:53:50 +0100104 size_t dstDepthStride = 0;
105 size_t dstBatchStride = 0;
Kevin May665a964a2019-08-21 16:53:50 +0100106 size_t dstHeightStride = 0;
107 size_t dstWidthStride = 0;
Matthew Benthamefdbca62019-09-14 23:35:28 +0100108 size_t dstChannelStride = 0;
Kevin May665a964a2019-08-21 16:53:50 +0100109 AssignValues(dstStrides.GetNumDimensions(),
110 0,
111 dstStrides,
Matthew Benthamefdbca62019-09-14 23:35:28 +0100112 dstChannelStride,
telsoa01c577f2c2018-08-31 09:22:23 +0100113 dstWidthStride,
114 dstHeightStride,
Matthew Jacksondba634f2019-08-15 15:14:18 +0100115 dstBatchStride,
116 dstDepthStride);
telsoa01c577f2c2018-08-31 09:22:23 +0100117
Rob Hughes9934e4e2019-11-27 14:27:11 +0000118 const unsigned char* srcDataStart;
119 unsigned char* dstDataStart;
Sadik Armaganbf86d512018-12-24 09:01:31 +0000120 {
121 ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "Synchronize buffers");
Rob Hughes9934e4e2019-11-27 14:27:11 +0000122 srcDataStart = static_cast<const uint8_t*>(srcTensor->Map());
123 dstDataStart = static_cast<uint8_t*>(dstTensor->Map());
Sadik Armaganbf86d512018-12-24 09:01:31 +0000124 }
telsoa01c577f2c2018-08-31 09:22:23 +0100125
Rob Hughes9934e4e2019-11-27 14:27:11 +0000126 size_t copyLength = std::min(srcChannels * srcChannelStride, dstChannels * dstChannelStride);
Matthew Benthamefdbca62019-09-14 23:35:28 +0100127 size_t copyWidth = std::min(srcWidth, dstWidth);
128 size_t copyHeight = std::min(srcHeight, dstHeight);
129 size_t copyBatches = std::min(srcBatches, dstBatches);
130 size_t copyDepth = std::min(srcDepth, dstDepth);
telsoa01c577f2c2018-08-31 09:22:23 +0100131
Matthew Bentham019c4b12019-09-15 00:06:05 +0100132 // Coalesce inner dimensions where possible
133 // to reduce overheard calling copy() and to
134 // allow for memory bandwidth optimisations
135 if (copyLength == srcWidthStride &&
136 copyLength == dstWidthStride)
137 {
138 // There is no special padding between rows,
139 // and sizes are compatible, so copy whole rows
140 copyLength *= copyWidth;
141 copyWidth = 1;
142
143 if (copyLength == srcHeightStride &&
144 copyLength == dstHeightStride)
145 {
146 // There is no special padding between batches
147 // and sizes are compatible so copy whole batches
148 copyLength *= copyHeight;
149 copyHeight = 1;
150 }
151 }
152
Rob Hughes9934e4e2019-11-27 14:27:11 +0000153 const unsigned char* srcData = srcDataStart;
154 unsigned char* dstData = dstDataStart;
Kevin May665a964a2019-08-21 16:53:50 +0100155 for (unsigned int d = 0; d < copyDepth; ++d)
telsoa01c577f2c2018-08-31 09:22:23 +0100156 {
Matthew Jacksondba634f2019-08-15 15:14:18 +0100157 auto srcPtrDepth = srcData;
158 auto dstPtrDepth = dstData;
Kevin May665a964a2019-08-21 16:53:50 +0100159 for (unsigned int b = 0; b < copyBatches; ++b)
telsoa01c577f2c2018-08-31 09:22:23 +0100160 {
Matthew Jacksondba634f2019-08-15 15:14:18 +0100161 auto srcPtrBatch = srcData;
162 auto dstPtrBatch = dstData;
Matthew Benthamefdbca62019-09-14 23:35:28 +0100163 for (unsigned int h = 0; h < copyHeight; ++h)
telsoa01c577f2c2018-08-31 09:22:23 +0100164 {
Matthew Jacksondba634f2019-08-15 15:14:18 +0100165 auto srcPtrChannel = srcData;
166 auto dstPtrChannel = dstData;
Matthew Benthamefdbca62019-09-14 23:35:28 +0100167 for (unsigned int w = 0; w < copyWidth; ++w)
Matthew Jacksondba634f2019-08-15 15:14:18 +0100168 {
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100169 ARMNN_ASSERT(srcData >= srcDataStart && srcData + copyLength <= srcDataStart + srcSize);
170 ARMNN_ASSERT(dstData >= dstDataStart && dstData + copyLength <= dstDataStart + dstSize);
Matthew Jacksondba634f2019-08-15 15:14:18 +0100171 copy(dstData, srcData, copyLength);
Matthew Benthamefdbca62019-09-14 23:35:28 +0100172 dstData += dstWidthStride;
173 srcData += srcWidthStride;
Matthew Jacksondba634f2019-08-15 15:14:18 +0100174 }
Matthew Benthamefdbca62019-09-14 23:35:28 +0100175 dstData += (static_cast<long>(dstHeightStride) - (dstData - dstPtrChannel));
176 srcData += (static_cast<long>(srcHeightStride) - (srcData - srcPtrChannel));
telsoa01c577f2c2018-08-31 09:22:23 +0100177 }
Kevin May665a964a2019-08-21 16:53:50 +0100178 dstData += (static_cast<long>(dstBatchStride) - (dstData - dstPtrBatch));
179 srcData += (static_cast<long>(srcBatchStride) - (srcData - srcPtrBatch));
telsoa01c577f2c2018-08-31 09:22:23 +0100180 }
Kevin May665a964a2019-08-21 16:53:50 +0100181 dstData += (static_cast<long>(dstDepthStride) - (dstData - dstPtrDepth));
182 srcData += (static_cast<long>(srcDepthStride) - (srcData - srcPtrDepth));
telsoa01c577f2c2018-08-31 09:22:23 +0100183 }
184
185 srcTensor->Unmap();
186 dstTensor->Unmap();
187}
188
189template <typename SrcTensorHandleType, typename DstTensorHandleType, typename DescriptorType>
190void GatherTensorHandlePairs(const DescriptorType& descriptor,
191 std::vector<std::pair<SrcTensorHandleType*, DstTensorHandleType*>>& tensorHandlePairs)
192{
193 const unsigned int numInputs = static_cast<unsigned int>(descriptor.m_Inputs.size());
194 tensorHandlePairs.reserve(numInputs);
195
196 for (unsigned int i = 0; i < numInputs; ++i)
197 {
Kevin May665a964a2019-08-21 16:53:50 +0100198 SrcTensorHandleType* const srcTensorHandle =
Jan Eilersbb446e52020-04-02 13:56:54 +0100199 PolymorphicDowncast<SrcTensorHandleType*>(descriptor.m_Inputs[i]);
Kevin May665a964a2019-08-21 16:53:50 +0100200 DstTensorHandleType* const dstTensorHandle =
Jan Eilersbb446e52020-04-02 13:56:54 +0100201 PolymorphicDowncast<DstTensorHandleType*>(descriptor.m_Outputs[i]);
telsoa01c577f2c2018-08-31 09:22:23 +0100202
203 tensorHandlePairs.emplace_back(srcTensorHandle, dstTensorHandle);
204 }
205}
206
Francis Murtaghec33a912019-11-05 14:26:23 +0000207int32_t ConvertMaskToACLFormat(int32_t mask, int32_t numDim);
208
James Conroy1f58f032021-04-27 17:13:27 +0100209armnn::ConstTensor PermuteTensor(const ConstTensorHandle* tensor,
Matteo Martincigh747ef822018-12-18 09:26:39 +0000210 const PermutationVector& permutationVector,
211 void* permuteBuffer);
212
213void ReshapeWeightsForAcl(TensorInfo& weightInfo, DataLayout dataLayout);
214
215TensorInfo ConvertWeightTensorInfoFromArmnnToAcl(const TensorInfo& weightInfo, DataLayout dataLayout);
216
James Conroy1f58f032021-04-27 17:13:27 +0100217armnn::ConstTensor ConvertWeightTensorFromArmnnToAcl(const ConstTensorHandle* weightTensor,
Matteo Martincigh747ef822018-12-18 09:26:39 +0000218 DataLayout dataLayout,
219 void* permuteBuffer);
220
Kevin May665a964a2019-08-21 16:53:50 +0100221} //namespace armnn