blob: 92ef2d224f79b5c1ffad3d909682b401d375bb72 [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"
Matteo Martincighe5b8eb92019-11-28 15:45:42 +00009
10#include <armnn/backends/ITensorHandle.hpp>
telsoa01c577f2c2018-08-31 09:22:23 +010011
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000012#include <armnn/Tensor.hpp>
13
Matteo Martincighe011d202019-11-28 11:35:47 +000014#include <armnnUtils/Permute.hpp>
15
Kevin May665a964a2019-08-21 16:53:50 +010016#include <Half.hpp>
Matteo Martincigh747ef822018-12-18 09:26:39 +000017#include <Profiling.hpp>
Matteo Martincigh747ef822018-12-18 09:26:39 +000018
telsoa01c577f2c2018-08-31 09:22:23 +010019#include <boost/cast.hpp>
20
21namespace armnn
22{
23namespace
24{
Matteo Martincigh747ef822018-12-18 09:26:39 +000025
Kevin May665a964a2019-08-21 16:53:50 +010026template <typename ArrayType, typename Arg>
telsoa01c577f2c2018-08-31 09:22:23 +010027void AssignValues(unsigned int num, unsigned int& idx, const ArrayType& array, Arg& arg)
28{
Matteo Martincigh747ef822018-12-18 09:26:39 +000029 if (idx >= num)
30 {
31 return;
32 }
telsoa01c577f2c2018-08-31 09:22:23 +010033
Matteo Martincigh747ef822018-12-18 09:26:39 +000034 arg = array[(num - 1) - idx];
35 idx++;
36}
telsoa01c577f2c2018-08-31 09:22:23 +010037
Kevin May665a964a2019-08-21 16:53:50 +010038template <typename T, typename ArrayType, typename... Args>
39void AssignValues(unsigned int num, unsigned int idx, const ArrayType& array, T& assignee, Args&... args)
telsoa01c577f2c2018-08-31 09:22:23 +010040{
Matteo Martincigh747ef822018-12-18 09:26:39 +000041 AssignValues(num, idx, array, assignee);
telsoa01c577f2c2018-08-31 09:22:23 +010042
Matteo Martincigh747ef822018-12-18 09:26:39 +000043 AssignValues(num, idx, array, args...);
telsoa01c577f2c2018-08-31 09:22:23 +010044}
Matteo Martincigh747ef822018-12-18 09:26:39 +000045
Kevin May665a964a2019-08-21 16:53:50 +010046} // anonymous namespace
telsoa01c577f2c2018-08-31 09:22:23 +010047
Kevin May665a964a2019-08-21 16:53:50 +010048template <typename CopyFunc>
telsoa01c577f2c2018-08-31 09:22:23 +010049void CopyTensorContentsGeneric(const ITensorHandle* srcTensor, ITensorHandle* dstTensor, CopyFunc copy)
50{
Matthew Benthamefdbca62019-09-14 23:35:28 +010051 // For ease of understanding, names are assigned to the dimensions
52 // of the tensor as if NHWC, however this routine works with any 5D tensor
Matthew Jacksondba634f2019-08-15 15:14:18 +010053 static_assert(MaxNumOfTensorDimensions == 5, "Please update CopyTensorContents");
telsoa01c577f2c2018-08-31 09:22:23 +010054
Kevin May665a964a2019-08-21 16:53:50 +010055 TensorShape srcStrides = srcTensor->GetStrides();
telsoa01c577f2c2018-08-31 09:22:23 +010056 const TensorShape& srcShape = srcTensor->GetShape();
Rob Hughes9934e4e2019-11-27 14:27:11 +000057 const auto srcSize = srcTensor->GetStrides()[0] * srcShape[0];
58 boost::ignore_unused(srcSize); // Only used for asserts
Kevin May665a964a2019-08-21 16:53:50 +010059 TensorShape dstStrides = dstTensor->GetStrides();
telsoa01c577f2c2018-08-31 09:22:23 +010060 const TensorShape& dstShape = dstTensor->GetShape();
Rob Hughes9934e4e2019-11-27 14:27:11 +000061 const auto dstSize = dstTensor->GetStrides()[0] * dstShape[0];
62 boost::ignore_unused(dstSize); // Only used for asserts
telsoa01c577f2c2018-08-31 09:22:23 +010063
Kevin May665a964a2019-08-21 16:53:50 +010064 size_t srcDepth = 1;
65 size_t srcBatches = 1;
Kevin May665a964a2019-08-21 16:53:50 +010066 size_t srcHeight = 1;
67 size_t srcWidth = 1;
Matthew Benthamefdbca62019-09-14 23:35:28 +010068 size_t srcChannels = 1;
Kevin May665a964a2019-08-21 16:53:50 +010069 AssignValues(srcShape.GetNumDimensions(),
70 0,
71 srcShape,
Matthew Benthamefdbca62019-09-14 23:35:28 +010072 srcChannels,
telsoa01c577f2c2018-08-31 09:22:23 +010073 srcWidth,
74 srcHeight,
Matthew Jacksondba634f2019-08-15 15:14:18 +010075 srcBatches,
76 srcDepth);
telsoa01c577f2c2018-08-31 09:22:23 +010077
Kevin May665a964a2019-08-21 16:53:50 +010078 size_t srcDepthStride = 0;
79 size_t srcBatchStride = 0;
Kevin May665a964a2019-08-21 16:53:50 +010080 size_t srcHeightStride = 0;
81 size_t srcWidthStride = 0;
Matthew Benthamefdbca62019-09-14 23:35:28 +010082 size_t srcChannelStride = 0;
Kevin May665a964a2019-08-21 16:53:50 +010083 AssignValues(srcStrides.GetNumDimensions(),
84 0,
85 srcStrides,
Matthew Benthamefdbca62019-09-14 23:35:28 +010086 srcChannelStride,
telsoa01c577f2c2018-08-31 09:22:23 +010087 srcWidthStride,
88 srcHeightStride,
Matthew Jacksondba634f2019-08-15 15:14:18 +010089 srcBatchStride,
90 srcDepthStride);
telsoa01c577f2c2018-08-31 09:22:23 +010091
Kevin May665a964a2019-08-21 16:53:50 +010092 size_t dstDepth = 1;
93 size_t dstBatches = 1;
Kevin May665a964a2019-08-21 16:53:50 +010094 size_t dstHeight = 1;
95 size_t dstWidth = 1;
Matthew Benthamefdbca62019-09-14 23:35:28 +010096 size_t dstChannels = 1;
Kevin May665a964a2019-08-21 16:53:50 +010097 AssignValues(dstShape.GetNumDimensions(),
98 0,
99 dstShape,
Matthew Benthamefdbca62019-09-14 23:35:28 +0100100 dstChannels,
telsoa01c577f2c2018-08-31 09:22:23 +0100101 dstWidth,
102 dstHeight,
Matthew Jacksondba634f2019-08-15 15:14:18 +0100103 dstBatches,
104 dstDepth);
telsoa01c577f2c2018-08-31 09:22:23 +0100105
Kevin May665a964a2019-08-21 16:53:50 +0100106 size_t dstDepthStride = 0;
107 size_t dstBatchStride = 0;
Kevin May665a964a2019-08-21 16:53:50 +0100108 size_t dstHeightStride = 0;
109 size_t dstWidthStride = 0;
Matthew Benthamefdbca62019-09-14 23:35:28 +0100110 size_t dstChannelStride = 0;
Kevin May665a964a2019-08-21 16:53:50 +0100111 AssignValues(dstStrides.GetNumDimensions(),
112 0,
113 dstStrides,
Matthew Benthamefdbca62019-09-14 23:35:28 +0100114 dstChannelStride,
telsoa01c577f2c2018-08-31 09:22:23 +0100115 dstWidthStride,
116 dstHeightStride,
Matthew Jacksondba634f2019-08-15 15:14:18 +0100117 dstBatchStride,
118 dstDepthStride);
telsoa01c577f2c2018-08-31 09:22:23 +0100119
Rob Hughes9934e4e2019-11-27 14:27:11 +0000120 const unsigned char* srcDataStart;
121 unsigned char* dstDataStart;
Sadik Armaganbf86d512018-12-24 09:01:31 +0000122 {
123 ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "Synchronize buffers");
Rob Hughes9934e4e2019-11-27 14:27:11 +0000124 srcDataStart = static_cast<const uint8_t*>(srcTensor->Map());
125 dstDataStart = static_cast<uint8_t*>(dstTensor->Map());
Sadik Armaganbf86d512018-12-24 09:01:31 +0000126 }
telsoa01c577f2c2018-08-31 09:22:23 +0100127
Rob Hughes9934e4e2019-11-27 14:27:11 +0000128 size_t copyLength = std::min(srcChannels * srcChannelStride, dstChannels * dstChannelStride);
Matthew Benthamefdbca62019-09-14 23:35:28 +0100129 size_t copyWidth = std::min(srcWidth, dstWidth);
130 size_t copyHeight = std::min(srcHeight, dstHeight);
131 size_t copyBatches = std::min(srcBatches, dstBatches);
132 size_t copyDepth = std::min(srcDepth, dstDepth);
telsoa01c577f2c2018-08-31 09:22:23 +0100133
Matthew Bentham019c4b12019-09-15 00:06:05 +0100134 // Coalesce inner dimensions where possible
135 // to reduce overheard calling copy() and to
136 // allow for memory bandwidth optimisations
137 if (copyLength == srcWidthStride &&
138 copyLength == dstWidthStride)
139 {
140 // There is no special padding between rows,
141 // and sizes are compatible, so copy whole rows
142 copyLength *= copyWidth;
143 copyWidth = 1;
144
145 if (copyLength == srcHeightStride &&
146 copyLength == dstHeightStride)
147 {
148 // There is no special padding between batches
149 // and sizes are compatible so copy whole batches
150 copyLength *= copyHeight;
151 copyHeight = 1;
152 }
153 }
154
Rob Hughes9934e4e2019-11-27 14:27:11 +0000155 const unsigned char* srcData = srcDataStart;
156 unsigned char* dstData = dstDataStart;
Kevin May665a964a2019-08-21 16:53:50 +0100157 for (unsigned int d = 0; d < copyDepth; ++d)
telsoa01c577f2c2018-08-31 09:22:23 +0100158 {
Matthew Jacksondba634f2019-08-15 15:14:18 +0100159 auto srcPtrDepth = srcData;
160 auto dstPtrDepth = dstData;
Kevin May665a964a2019-08-21 16:53:50 +0100161 for (unsigned int b = 0; b < copyBatches; ++b)
telsoa01c577f2c2018-08-31 09:22:23 +0100162 {
Matthew Jacksondba634f2019-08-15 15:14:18 +0100163 auto srcPtrBatch = srcData;
164 auto dstPtrBatch = dstData;
Matthew Benthamefdbca62019-09-14 23:35:28 +0100165 for (unsigned int h = 0; h < copyHeight; ++h)
telsoa01c577f2c2018-08-31 09:22:23 +0100166 {
Matthew Jacksondba634f2019-08-15 15:14:18 +0100167 auto srcPtrChannel = srcData;
168 auto dstPtrChannel = dstData;
Matthew Benthamefdbca62019-09-14 23:35:28 +0100169 for (unsigned int w = 0; w < copyWidth; ++w)
Matthew Jacksondba634f2019-08-15 15:14:18 +0100170 {
Rob Hughes9934e4e2019-11-27 14:27:11 +0000171 BOOST_ASSERT(srcData >= srcDataStart && srcData + copyLength <= srcDataStart + srcSize);
172 BOOST_ASSERT(dstData >= dstDataStart && dstData + copyLength <= dstDataStart + dstSize);
Matthew Jacksondba634f2019-08-15 15:14:18 +0100173 copy(dstData, srcData, copyLength);
Matthew Benthamefdbca62019-09-14 23:35:28 +0100174 dstData += dstWidthStride;
175 srcData += srcWidthStride;
Matthew Jacksondba634f2019-08-15 15:14:18 +0100176 }
Matthew Benthamefdbca62019-09-14 23:35:28 +0100177 dstData += (static_cast<long>(dstHeightStride) - (dstData - dstPtrChannel));
178 srcData += (static_cast<long>(srcHeightStride) - (srcData - srcPtrChannel));
telsoa01c577f2c2018-08-31 09:22:23 +0100179 }
Kevin May665a964a2019-08-21 16:53:50 +0100180 dstData += (static_cast<long>(dstBatchStride) - (dstData - dstPtrBatch));
181 srcData += (static_cast<long>(srcBatchStride) - (srcData - srcPtrBatch));
telsoa01c577f2c2018-08-31 09:22:23 +0100182 }
Kevin May665a964a2019-08-21 16:53:50 +0100183 dstData += (static_cast<long>(dstDepthStride) - (dstData - dstPtrDepth));
184 srcData += (static_cast<long>(srcDepthStride) - (srcData - srcPtrDepth));
telsoa01c577f2c2018-08-31 09:22:23 +0100185 }
186
187 srcTensor->Unmap();
188 dstTensor->Unmap();
189}
190
191template <typename SrcTensorHandleType, typename DstTensorHandleType, typename DescriptorType>
192void GatherTensorHandlePairs(const DescriptorType& descriptor,
193 std::vector<std::pair<SrcTensorHandleType*, DstTensorHandleType*>>& tensorHandlePairs)
194{
195 const unsigned int numInputs = static_cast<unsigned int>(descriptor.m_Inputs.size());
196 tensorHandlePairs.reserve(numInputs);
197
198 for (unsigned int i = 0; i < numInputs; ++i)
199 {
Kevin May665a964a2019-08-21 16:53:50 +0100200 SrcTensorHandleType* const srcTensorHandle =
201 boost::polymorphic_downcast<SrcTensorHandleType*>(descriptor.m_Inputs[i]);
202 DstTensorHandleType* const dstTensorHandle =
203 boost::polymorphic_downcast<DstTensorHandleType*>(descriptor.m_Outputs[i]);
telsoa01c577f2c2018-08-31 09:22:23 +0100204
205 tensorHandlePairs.emplace_back(srcTensorHandle, dstTensorHandle);
206 }
207}
208
Francis Murtaghec33a912019-11-05 14:26:23 +0000209int32_t ConvertMaskToACLFormat(int32_t mask, int32_t numDim);
210
Matteo Martincigh747ef822018-12-18 09:26:39 +0000211armnn::ConstTensor PermuteTensor(const ConstCpuTensorHandle* tensor,
212 const PermutationVector& permutationVector,
213 void* permuteBuffer);
214
215void ReshapeWeightsForAcl(TensorInfo& weightInfo, DataLayout dataLayout);
216
217TensorInfo ConvertWeightTensorInfoFromArmnnToAcl(const TensorInfo& weightInfo, DataLayout dataLayout);
218
219armnn::ConstTensor ConvertWeightTensorFromArmnnToAcl(const ConstCpuTensorHandle* weightTensor,
220 DataLayout dataLayout,
221 void* permuteBuffer);
222
Kevin May665a964a2019-08-21 16:53:50 +0100223} //namespace armnn