blob: cf5f50025a3ecaaebb244d8c7c20477e9e58e364 [file] [log] [blame]
arovir014424b0a2018-10-04 10:46:04 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include "ClBackend.hpp"
Narumol Prangnawarate5f0b242021-05-07 17:52:36 +01007#include "ClBackendContext.hpp"
David Monahan6642b8a2021-11-04 16:31:46 +00008#include "ClBackendDefaultAllocator.hpp"
David Beck3e9e1152018-10-17 14:17:50 +01009#include "ClBackendId.hpp"
Sadik Armagan045f6be2020-09-10 13:37:32 +010010#include "ClBackendModelContext.hpp"
Narumol Prangnawarate5f0b242021-05-07 17:52:36 +010011#include "ClImportTensorHandleFactory.hpp"
David Beck111b5d92018-11-12 14:59:37 +000012#include "ClLayerSupport.hpp"
Jan Eilerse9f0f0f2019-08-16 10:28:37 +010013#include "ClTensorHandleFactory.hpp"
Narumol Prangnawarate5f0b242021-05-07 17:52:36 +010014#include "ClWorkloadFactory.hpp"
arovir01a0944792018-10-11 15:00:58 +010015
Matteo Martincighc601aa62019-10-29 15:03:22 +000016#include <armnn/BackendRegistry.hpp>
Mike Kelly07810fc2020-11-12 10:58:48 +000017#include <armnn/Descriptors.hpp>
Matteo Martincighc601aa62019-10-29 15:03:22 +000018
Mike Kelly07810fc2020-11-12 10:58:48 +000019#include <aclCommon/ArmComputeSubgraphUtils.hpp>
20#include <aclCommon/ArmComputeUtils.hpp>
Aron Virginas-Tar56055192018-11-12 18:10:43 +000021#include <aclCommon/BaseMemoryManager.hpp>
22
Matteo Martincighe5b8eb92019-11-28 15:45:42 +000023#include <armnn/backends/IBackendContext.hpp>
24#include <armnn/backends/IMemoryManager.hpp>
Jan Eilers3c9e0452020-04-10 13:00:44 +010025#include <armnn/utility/PolymorphicDowncast.hpp>
26
Mike Kelly07810fc2020-11-12 10:58:48 +000027#include "workloads/ClAdditionWorkload.hpp"
28#include "workloads/ClBatchNormalizationFloatWorkload.hpp"
29#include "workloads/ClConvolution2dWorkload.hpp"
30#include "workloads/ClDepthwiseConvolutionWorkload.hpp"
Teresa Charline11e63d2021-04-21 12:56:45 +010031#include "workloads/ClDivisionWorkload.hpp"
Mike Kelly07810fc2020-11-12 10:58:48 +000032#include "workloads/ClFullyConnectedWorkload.hpp"
33#include "workloads/ClMultiplicationWorkload.hpp"
Matthew Sloyan5fc0fd62021-05-03 12:22:03 +010034#include "workloads/ClReduceWorkload.hpp"
Mike Kelly07810fc2020-11-12 10:58:48 +000035#include "workloads/ClSubtractionWorkload.hpp"
36
David Beck263e3492018-11-09 14:46:40 +000037#include <Optimizer.hpp>
arovir014424b0a2018-10-04 10:46:04 +010038
Mike Kelly07810fc2020-11-12 10:58:48 +000039#include <arm_compute/core/Types.h>
Aron Virginas-Tar56055192018-11-12 18:10:43 +000040#include <arm_compute/runtime/CL/CLBufferAllocator.h>
41
arovir014424b0a2018-10-04 10:46:04 +010042namespace armnn
43{
44
David Beck3cc9a622018-10-12 10:38:31 +010045const BackendId& ClBackend::GetIdStatic()
arovir014424b0a2018-10-04 10:46:04 +010046{
David Beck3e9e1152018-10-17 14:17:50 +010047 static const BackendId s_Id{ClBackendId()};
arovir014424b0a2018-10-04 10:46:04 +010048 return s_Id;
49}
50
Aron Virginas-Tar56055192018-11-12 18:10:43 +000051IBackendInternal::IMemoryManagerUniquePtr ClBackend::CreateMemoryManager() const
arovir014424b0a2018-10-04 10:46:04 +010052{
Jan Eilersc1c872f2021-07-22 13:17:04 +010053 if (m_UsingCustomAllocator)
54 {
55 return std::make_unique<ClMemoryManager>(m_CustomAllocator);
56 }
Aron Virginas-Tar56055192018-11-12 18:10:43 +000057 return std::make_unique<ClMemoryManager>(std::make_unique<arm_compute::CLBufferAllocator>());
58}
59
60IBackendInternal::IWorkloadFactoryPtr ClBackend::CreateWorkloadFactory(
61 const IBackendInternal::IMemoryManagerSharedPtr& memoryManager) const
62{
63 return std::make_unique<ClWorkloadFactory>(
Jan Eilers3c9e0452020-04-10 13:00:44 +010064 PolymorphicPointerDowncast<ClMemoryManager>(memoryManager));
arovir014424b0a2018-10-04 10:46:04 +010065}
66
Jan Eilerse9f0f0f2019-08-16 10:28:37 +010067IBackendInternal::IWorkloadFactoryPtr ClBackend::CreateWorkloadFactory(
Sadik Armagan04a72972020-09-14 15:44:18 +010068 const IBackendInternal::IMemoryManagerSharedPtr& memoryManager, const ModelOptions& modelOptions) const
69{
70 return std::make_unique<ClWorkloadFactory>(
71 PolymorphicPointerDowncast<ClMemoryManager>(memoryManager), CreateBackendSpecificModelContext(modelOptions));
72}
73
74IBackendInternal::IWorkloadFactoryPtr ClBackend::CreateWorkloadFactory(
Jan Eilerse9f0f0f2019-08-16 10:28:37 +010075 TensorHandleFactoryRegistry& registry) const
76{
Jan Eilersc1c872f2021-07-22 13:17:04 +010077 std::shared_ptr<ClMemoryManager> memoryManager;
78 if (m_UsingCustomAllocator)
79 {
80 memoryManager = std::make_shared<ClMemoryManager>(m_CustomAllocator);
81 }
82 else
83 {
84 memoryManager = std::make_shared<ClMemoryManager>(std::make_unique<arm_compute::CLBufferAllocator>());
85 }
Jan Eilerse9f0f0f2019-08-16 10:28:37 +010086
87 registry.RegisterMemoryManager(memoryManager);
Narumol Prangnawarat549cb7a2020-07-10 17:50:53 +010088 registry.RegisterFactory(std::make_unique<ClTensorHandleFactory>(memoryManager));
Narumol Prangnawarate5f0b242021-05-07 17:52:36 +010089 registry.RegisterFactory(std::make_unique<ClImportTensorHandleFactory>(
90 static_cast<MemorySourceFlags>(MemorySource::Malloc), static_cast<MemorySourceFlags>(MemorySource::Malloc)));
Jan Eilerse9f0f0f2019-08-16 10:28:37 +010091
92 return std::make_unique<ClWorkloadFactory>(
Jan Eilers3c9e0452020-04-10 13:00:44 +010093 PolymorphicPointerDowncast<ClMemoryManager>(memoryManager));
Jan Eilerse9f0f0f2019-08-16 10:28:37 +010094}
95
Sadik Armagan04a72972020-09-14 15:44:18 +010096IBackendInternal::IWorkloadFactoryPtr ClBackend::CreateWorkloadFactory(
97 TensorHandleFactoryRegistry& registry, const ModelOptions& modelOptions) const
98{
Jan Eilersc1c872f2021-07-22 13:17:04 +010099 std::shared_ptr<ClMemoryManager> memoryManager;
100 if (m_UsingCustomAllocator)
101 {
102 memoryManager = std::make_shared<ClMemoryManager>(m_CustomAllocator);
103 }
104 else
105 {
106 memoryManager = std::make_shared<ClMemoryManager>(std::make_unique<arm_compute::CLBufferAllocator>());
107 }
Sadik Armagan04a72972020-09-14 15:44:18 +0100108
109 registry.RegisterMemoryManager(memoryManager);
110 registry.RegisterFactory(std::make_unique<ClTensorHandleFactory>(memoryManager));
Narumol Prangnawarate5f0b242021-05-07 17:52:36 +0100111 registry.RegisterFactory(std::make_unique<ClImportTensorHandleFactory>(
112 static_cast<MemorySourceFlags>(MemorySource::Malloc), static_cast<MemorySourceFlags>(MemorySource::Malloc)));
113
114 return std::make_unique<ClWorkloadFactory>(
115 PolymorphicPointerDowncast<ClMemoryManager>(memoryManager), CreateBackendSpecificModelContext(modelOptions));
116}
117
118IBackendInternal::IWorkloadFactoryPtr ClBackend::CreateWorkloadFactory(
119 TensorHandleFactoryRegistry& registry,
120 const ModelOptions& modelOptions,
121 MemorySourceFlags inputFlags,
122 MemorySourceFlags outputFlags) const
123{
Jan Eilersc1c872f2021-07-22 13:17:04 +0100124 std::shared_ptr<ClMemoryManager> memoryManager;
125 if (m_UsingCustomAllocator)
126 {
127 memoryManager = std::make_shared<ClMemoryManager>(m_CustomAllocator);
128 }
129 else
130 {
131 memoryManager = std::make_shared<ClMemoryManager>(std::make_unique<arm_compute::CLBufferAllocator>());
132 }
Narumol Prangnawarate5f0b242021-05-07 17:52:36 +0100133
134 registry.RegisterMemoryManager(memoryManager);
135 registry.RegisterFactory(std::make_unique<ClTensorHandleFactory>(memoryManager));
136 registry.RegisterFactory(std::make_unique<ClImportTensorHandleFactory>(inputFlags, outputFlags));
Sadik Armagan04a72972020-09-14 15:44:18 +0100137
138 return std::make_unique<ClWorkloadFactory>(
139 PolymorphicPointerDowncast<ClMemoryManager>(memoryManager), CreateBackendSpecificModelContext(modelOptions));
140}
141
Jan Eilerse9f0f0f2019-08-16 10:28:37 +0100142std::vector<ITensorHandleFactory::FactoryId> ClBackend::GetHandleFactoryPreferences() const
143{
Narumol Prangnawarate5f0b242021-05-07 17:52:36 +0100144 return std::vector<ITensorHandleFactory::FactoryId> {ClTensorHandleFactory::GetIdStatic(),
145 ClImportTensorHandleFactory::GetIdStatic()};
Jan Eilerse9f0f0f2019-08-16 10:28:37 +0100146}
147
148void ClBackend::RegisterTensorHandleFactories(TensorHandleFactoryRegistry& registry)
149{
Jan Eilersc1c872f2021-07-22 13:17:04 +0100150 std::shared_ptr<ClMemoryManager> memoryManager;
151 if (m_UsingCustomAllocator)
152 {
153 memoryManager = std::make_shared<ClMemoryManager>(m_CustomAllocator);
154 }
155 else
156 {
157 memoryManager = std::make_shared<ClMemoryManager>(std::make_unique<arm_compute::CLBufferAllocator>());
158 }
Jan Eilerse9f0f0f2019-08-16 10:28:37 +0100159
Jan Eilersc1c872f2021-07-22 13:17:04 +0100160 registry.RegisterMemoryManager(memoryManager);
161 registry.RegisterFactory(std::make_unique<ClTensorHandleFactory>(memoryManager));
Narumol Prangnawarate5f0b242021-05-07 17:52:36 +0100162 registry.RegisterFactory(std::make_unique<ClImportTensorHandleFactory>(
163 static_cast<MemorySourceFlags>(MemorySource::Malloc), static_cast<MemorySourceFlags>(MemorySource::Malloc)));
164}
165
166void ClBackend::RegisterTensorHandleFactories(TensorHandleFactoryRegistry& registry,
167 MemorySourceFlags inputFlags,
168 MemorySourceFlags outputFlags)
169{
Jan Eilersc1c872f2021-07-22 13:17:04 +0100170 std::shared_ptr<ClMemoryManager> memoryManager;
171 if (m_UsingCustomAllocator)
172 {
173 memoryManager = std::make_shared<ClMemoryManager>(m_CustomAllocator);
174 }
175 else
176 {
177 memoryManager = std::make_shared<ClMemoryManager>(std::make_unique<arm_compute::CLBufferAllocator>());
178 }
Narumol Prangnawarate5f0b242021-05-07 17:52:36 +0100179
Jan Eilersc1c872f2021-07-22 13:17:04 +0100180 registry.RegisterMemoryManager(memoryManager);
181 registry.RegisterFactory(std::make_unique<ClTensorHandleFactory>(memoryManager));
Narumol Prangnawarate5f0b242021-05-07 17:52:36 +0100182 registry.RegisterFactory(std::make_unique<ClImportTensorHandleFactory>(inputFlags, outputFlags));
Jan Eilerse9f0f0f2019-08-16 10:28:37 +0100183}
184
Sadik Armagan045f6be2020-09-10 13:37:32 +0100185IBackendInternal::IBackendContextPtr ClBackend::CreateBackendContext(const IRuntime::CreationOptions& options) const
David Beck1b61be52018-11-08 09:19:14 +0000186{
187 return IBackendContextPtr{new ClBackendContext{options}};
188}
189
Colm Donelane49755b2020-01-29 15:22:43 +0000190IBackendInternal::IBackendProfilingContextPtr ClBackend::CreateBackendProfilingContext(
Colm Donelan1aff3932020-02-05 17:48:59 +0000191 const IRuntime::CreationOptions&, IBackendProfilingPtr&)
Colm Donelane49755b2020-01-29 15:22:43 +0000192{
193 return IBackendProfilingContextPtr{};
194}
195
Sadik Armagan045f6be2020-09-10 13:37:32 +0100196IBackendInternal::IBackendSpecificModelContextPtr ClBackend::CreateBackendSpecificModelContext(
197 const ModelOptions& modelOptions) const
198{
199 return IBackendSpecificModelContextPtr{new ClBackendModelContext{modelOptions}};
200}
201
David Beck111b5d92018-11-12 14:59:37 +0000202IBackendInternal::ILayerSupportSharedPtr ClBackend::GetLayerSupport() const
203{
Sadik Armagan045f6be2020-09-10 13:37:32 +0100204 static ILayerSupportSharedPtr layerSupport
205 {
206 new ClLayerSupport(IBackendInternal::IBackendSpecificModelContextPtr{})
207 };
208 return layerSupport;
209}
210
211IBackendInternal::ILayerSupportSharedPtr ClBackend::GetLayerSupport(const ModelOptions& modelOptions) const
212{
213 static ILayerSupportSharedPtr layerSupport
214 {
215 new ClLayerSupport(CreateBackendSpecificModelContext(modelOptions))
216 };
David Beck111b5d92018-11-12 14:59:37 +0000217 return layerSupport;
218}
219
David Monahan6642b8a2021-11-04 16:31:46 +0000220std::unique_ptr<ICustomAllocator> ClBackend::GetDefaultAllocator() const
221{
222 return std::make_unique<ClBackendDefaultAllocator>();
223}
224
Mike Kelly07810fc2020-11-12 10:58:48 +0000225OptimizationViews ClBackend::OptimizeSubgraphView(const SubgraphView& subgraph,
226 const ModelOptions& modelOptions) const
Matteo Martincighadddddb2019-01-24 14:06:23 +0000227{
Matteo Martincighc3ba50e2019-05-22 14:28:16 +0100228 OptimizationViews optimizationViews;
Matteo Martincighadddddb2019-01-24 14:06:23 +0000229
Francis Murtagh56ccf682021-12-13 18:48:12 +0000230 auto it = subgraph.endIConnectable();
Mike Kelly07810fc2020-11-12 10:58:48 +0000231 bool isFastMathEnabled = false;
Mike Kelly1ac690a2020-11-17 11:41:38 +0000232 std::map<LayerGuid, Layer*> untouched;
Mike Kelly07810fc2020-11-12 10:58:48 +0000233
Francis Murtagh56ccf682021-12-13 18:48:12 +0000234 while (it != subgraph.beginIConnectable())
Mike Kelly1ac690a2020-11-17 11:41:38 +0000235 {
236 --it;
Francis Murtagh56ccf682021-12-13 18:48:12 +0000237 Layer& base = *(PolymorphicDowncast<Layer*>(*it));
Mike Kelly1ac690a2020-11-17 11:41:38 +0000238 untouched.insert({base.GetGuid(), &base});
239 }
240
Francis Murtagh56ccf682021-12-13 18:48:12 +0000241 it = subgraph.endIConnectable();
Mike Kelly07810fc2020-11-12 10:58:48 +0000242#if defined(ARMCOMPUTECL_ENABLED)
243 IBackendInternal::IBackendSpecificModelContextPtr modelContextPtr = CreateBackendSpecificModelContext(modelOptions);
244
245 if (modelContextPtr)
246 {
247 auto clModelOptions = dynamic_cast<ClBackendModelContext*>(modelContextPtr.get());
248 if (clModelOptions)
249 {
250 isFastMathEnabled = clModelOptions->IsFastMathEnabled();
251 }
252 }
253#endif
Francis Murtagh56ccf682021-12-13 18:48:12 +0000254 while (it != subgraph.beginIConnectable())
Mike Kelly07810fc2020-11-12 10:58:48 +0000255 {
256 --it;
Francis Murtagh56ccf682021-12-13 18:48:12 +0000257 Layer& base = *(PolymorphicDowncast<Layer*>(*it));
Mike Kelly07810fc2020-11-12 10:58:48 +0000258
Matthew Sloyan5fc0fd62021-05-03 12:22:03 +0100259 // Fuse activation into previous layer if supported by backend
Mike Kelly07810fc2020-11-12 10:58:48 +0000260 if ((base.GetType() == LayerType::DepthwiseConvolution2d || base.GetType() == LayerType::Convolution2d
261 || base.GetType() == LayerType::BatchNormalization || base.GetType() == LayerType::FullyConnected
262 || base.GetType() == LayerType::Addition || base.GetType() == LayerType::Multiplication
Matthew Sloyanae123062021-05-07 14:18:01 +0000263 || base.GetType() == LayerType::Subtraction || base.GetType() == LayerType::Division)
Mike Kelly07810fc2020-11-12 10:58:48 +0000264 && (base.GetAdditionalInformation<ActivationDescriptor>() == nullptr))
265 {
266 for (auto output = base.BeginOutputSlots(); output != base.EndOutputSlots(); ++output)
267 {
268 if (output->GetNumConnections() == 1)
269 {
270 for (auto&& childInput : output->GetConnections())
271 {
Teresa Charlind672f5d2021-01-18 18:07:57 +0000272 if ((childInput->GetOwningLayer().GetType() == LayerType::Activation) &&
273 (checkDataTypeInputandOutput(childInput->GetOwningLayer())))
Mike Kelly07810fc2020-11-12 10:58:48 +0000274 {
275 Layer& child = childInput->GetOwningLayer();
276
277 auto* activationLayer = PolymorphicDowncast<ActivationLayer*>(&child);
278
279 const std::string name = std::string("fused-") + child.GetName() + std::string("-into-") +
280 base.GetName();
281
282 // Get params from activation layer
283 ActivationDescriptor activationDesc = activationLayer->GetParameters();
284
285 if (base.GetType() == LayerType::Convolution2d)
286 {
287 Convolution2dLayer* baseLayer = PolymorphicDowncast<Convolution2dLayer*>(&base);
288
289 Optional<TensorInfo> biases;
290
291 if (baseLayer->GetParameters().m_BiasEnabled)
292 {
Mike Kelly1ac690a2020-11-17 11:41:38 +0000293 biases = baseLayer->m_Bias->GetTensorInfo();
Mike Kelly07810fc2020-11-12 10:58:48 +0000294 }
295
296 arm_compute::Status status = ClConvolution2dWorkloadValidate(
297 baseLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
298 activationLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
299 baseLayer->GetParameters(),
300 baseLayer->m_Weight->GetTensorInfo(),
301 biases,
302 isFastMathEnabled,
303 &activationDesc);
304
305 if (status)
306 {
Cathal Corbettcbfd7182021-12-15 17:12:59 +0000307 FuseConvolution2dLayer<Convolution2dLayer>(optimizationViews,
308 baseLayer,
309 activationLayer,
310 activationDesc,
311 name);
Mike Kelly1ac690a2020-11-17 11:41:38 +0000312 untouched.erase(baseLayer->GetGuid());
313 untouched.erase(activationLayer->GetGuid());
Mike Kelly07810fc2020-11-12 10:58:48 +0000314 }
315 }
316 else if (base.GetType() == LayerType::DepthwiseConvolution2d)
317 {
318 DepthwiseConvolution2dLayer* baseLayer =
319 PolymorphicDowncast<DepthwiseConvolution2dLayer*>(&base);
320
321 Optional<TensorInfo> biases;
322
323 if (baseLayer->GetParameters().m_BiasEnabled)
324 {
Mike Kelly1ac690a2020-11-17 11:41:38 +0000325 biases = baseLayer->m_Bias->GetTensorInfo();
Mike Kelly07810fc2020-11-12 10:58:48 +0000326 }
327
328 arm_compute::Status status = ClDepthwiseConvolutionWorkloadValidate(
329 baseLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
330 activationLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
331 baseLayer->GetParameters(),
332 baseLayer->m_Weight->GetTensorInfo(),
333 biases,
334 &activationDesc);
335
336 if (status)
337 {
Cathal Corbettcbfd7182021-12-15 17:12:59 +0000338 FuseDepthwiseConvolution2dLayer<DepthwiseConvolution2dLayer>(optimizationViews,
339 baseLayer,
340 activationLayer,
341 activationDesc,
342 name);
Mike Kelly1ac690a2020-11-17 11:41:38 +0000343 untouched.erase(baseLayer->GetGuid());
344 untouched.erase(activationLayer->GetGuid());
Mike Kelly07810fc2020-11-12 10:58:48 +0000345 }
346 }
347 else if (base.GetType() == LayerType::FullyConnected)
348 {
349 FullyConnectedLayer* baseLayer = PolymorphicDowncast<FullyConnectedLayer*>(&base);
350
351 arm_compute::Status status = ClFullyConnectedWorkloadValidate(
352 baseLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
353 activationLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
354 baseLayer->m_Weight->GetTensorInfo(),
355 baseLayer->m_Bias->GetTensorInfo(),
356 baseLayer->GetParameters(),
357 &activationDesc);
358
359 if (status)
360 {
Cathal Corbettcbfd7182021-12-15 17:12:59 +0000361 FuseFullyConnectedLayer<FullyConnectedLayer>(optimizationViews,
362 baseLayer,
363 activationLayer,
364 activationDesc,
365 name);
Mike Kelly1ac690a2020-11-17 11:41:38 +0000366 untouched.erase(baseLayer->GetGuid());
367 untouched.erase(activationLayer->GetGuid());
Mike Kelly07810fc2020-11-12 10:58:48 +0000368 }
369 }
370 else if (base.GetType() == LayerType::BatchNormalization)
371 {
372 BatchNormalizationLayer* baseLayer =
373 PolymorphicDowncast<BatchNormalizationLayer*>(&base);
374
375 arm_compute::Status status = ClBatchNormalizationValidate(
376 baseLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
377 activationLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
378 baseLayer->m_Mean->GetTensorInfo(),
379 baseLayer->m_Variance->GetTensorInfo(),
380 baseLayer->m_Beta->GetTensorInfo(),
381 baseLayer->m_Gamma->GetTensorInfo(),
382 baseLayer->GetParameters(),
383 &activationDesc);
384
385 if (status)
386 {
387 BatchNormalizationLayer* replacementLayer =
Cathal Corbettcbfd7182021-12-15 17:12:59 +0000388 FuseBatchNormalizationLayer<BatchNormalizationLayer>(optimizationViews,
Mike Kelly07810fc2020-11-12 10:58:48 +0000389 baseLayer,
390 activationLayer,
391 activationDesc,
392 name);
393
394 replacementLayer->m_Beta = std::move(baseLayer->m_Beta);
395 replacementLayer->m_Gamma = std::move(baseLayer->m_Gamma);
396 replacementLayer->m_Mean = std::move(baseLayer->m_Mean);
397 replacementLayer->m_Variance = std::move(baseLayer->m_Variance);
Mike Kelly1ac690a2020-11-17 11:41:38 +0000398 untouched.erase(baseLayer->GetGuid());
399 untouched.erase(activationLayer->GetGuid());
Mike Kelly07810fc2020-11-12 10:58:48 +0000400 }
401 }
402 else if (base.GetType() == LayerType::Addition)
403 {
404 AdditionLayer* baseLayer = PolymorphicDowncast<AdditionLayer*>(&base);
405
406 arm_compute::Status status = ClAdditionValidate(
407 baseLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
408 baseLayer->GetInputSlot(1).GetConnectedOutputSlot()->GetTensorInfo(),
409 activationLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
410 &activationDesc);
411
412 if (status)
413 {
Cathal Corbettcbfd7182021-12-15 17:12:59 +0000414 FuseAdditionLayer<AdditionLayer>(optimizationViews,
415 baseLayer,
416 activationLayer,
417 activationDesc,
418 name);
Mike Kelly1ac690a2020-11-17 11:41:38 +0000419 untouched.erase(baseLayer->GetGuid());
420 untouched.erase(activationLayer->GetGuid());
Mike Kelly07810fc2020-11-12 10:58:48 +0000421 }
422 }
423 else if (base.GetType() == LayerType::Division)
424 {
425 DivisionLayer* baseLayer = PolymorphicDowncast<DivisionLayer*>(&base);
426
427 arm_compute::Status status = ClDivisionWorkloadValidate(
428 baseLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
429 baseLayer->GetInputSlot(1).GetConnectedOutputSlot()->GetTensorInfo(),
430 activationLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
431 &activationDesc);
432
433 if (status)
434 {
Cathal Corbettcbfd7182021-12-15 17:12:59 +0000435 FuseDivisionLayer<DivisionLayer>(optimizationViews,
436 baseLayer,
437 activationLayer,
438 activationDesc,
439 name);
Mike Kelly1ac690a2020-11-17 11:41:38 +0000440 untouched.erase(baseLayer->GetGuid());
441 untouched.erase(activationLayer->GetGuid());
Mike Kelly07810fc2020-11-12 10:58:48 +0000442 }
443 }
444 else if (base.GetType() == LayerType::Multiplication)
445 {
446 MultiplicationLayer* baseLayer = PolymorphicDowncast<MultiplicationLayer*>(&base);
447
448 arm_compute::Status status = ClMultiplicationWorkloadValidate(
449 baseLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
450 baseLayer->GetInputSlot(1).GetConnectedOutputSlot()->GetTensorInfo(),
451 activationLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
452 &activationDesc);
453
454 if (status)
455 {
Cathal Corbettcbfd7182021-12-15 17:12:59 +0000456 FuseMultiplicationLayer<MultiplicationLayer>(optimizationViews,
457 baseLayer,
458 activationLayer,
459 activationDesc,
460 name);
Mike Kelly1ac690a2020-11-17 11:41:38 +0000461 untouched.erase(baseLayer->GetGuid());
462 untouched.erase(activationLayer->GetGuid());
Mike Kelly07810fc2020-11-12 10:58:48 +0000463 }
464 }
465 else if (base.GetType() == LayerType::Subtraction)
466 {
467 SubtractionLayer* baseLayer = PolymorphicDowncast<SubtractionLayer*>(&base);
468
469 arm_compute::Status status = ClSubtractionValidate(
470 baseLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
471 baseLayer->GetInputSlot(1).GetConnectedOutputSlot()->GetTensorInfo(),
472 activationLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
473 &activationDesc);
474
475 if (status)
476 {
Cathal Corbettcbfd7182021-12-15 17:12:59 +0000477 FuseSubtractionLayer<SubtractionLayer>(optimizationViews,
478 baseLayer,
479 activationLayer,
480 activationDesc,
481 name);
Mike Kelly1ac690a2020-11-17 11:41:38 +0000482 untouched.erase(baseLayer->GetGuid());
483 untouched.erase(activationLayer->GetGuid());
Mike Kelly07810fc2020-11-12 10:58:48 +0000484 }
485 }
486 }
487 }
488 }
489 }
490 }
Matthew Sloyan5fc0fd62021-05-03 12:22:03 +0100491
492 // Separate reduce layer with multiple axes into multiple reduce layers with 1 axis.
493 if (base.GetType() == LayerType::Reduce)
494 {
495 ReduceLayer* baseLayer = PolymorphicDowncast<ReduceLayer*>(&base);
496 ReduceDescriptor reduceDescriptor = baseLayer->GetParameters();
497
498 if (!reduceDescriptor.m_vAxis.empty() && reduceDescriptor.m_vAxis.size() > 1)
499 {
500 // Add new layers to the graph and connect them.
Francis Murtagh56ccf682021-12-13 18:48:12 +0000501 std::vector<IConnectableLayer*> layers = ChainReduceLayers<ReduceLayer>(optimizationViews,
502 baseLayer,
503 reduceDescriptor);
Matthew Sloyan5fc0fd62021-05-03 12:22:03 +0100504
505 // Replace existing baselayer with new subgraph.
506 ReplaceLayers<ReduceLayer>(optimizationViews, baseLayer, layers);
507 untouched.erase(baseLayer->GetGuid());
508 }
509 }
Mike Kelly07810fc2020-11-12 10:58:48 +0000510 }
Mike Kelly1ac690a2020-11-17 11:41:38 +0000511
Mike Kelly07810fc2020-11-12 10:58:48 +0000512 if (optimizationViews.GetSubstitutions().empty())
513 {
514 optimizationViews.AddUntouchedSubgraph(SubgraphView(subgraph));
515 }
Mike Kelly1ac690a2020-11-17 11:41:38 +0000516 else
517 {
518 ReportUntouchedLayers(optimizationViews, untouched);
519 }
Matteo Martincighc3ba50e2019-05-22 14:28:16 +0100520
521 return optimizationViews;
Matteo Martincighadddddb2019-01-24 14:06:23 +0000522}
523
David Beck9efb57d2018-11-05 13:40:33 +0000524} // namespace armnn