struct BackendOptions;
using NetworkOptions = std::vector<BackendOptions>;
+using ModelOptions = std::vector<BackendOptions>;
+
/// Struct for the users to pass backend specific options
struct BackendOptions
{
std::vector<BackendOption> m_Options;
};
+
+template <typename F>
+void ParseOptions(const std::vector<BackendOptions>& options, BackendId backend, F f)
+{
+ for (auto optionsGroup : options)
+ {
+ if (optionsGroup.GetBackendId() == backend)
+ {
+ for (size_t i=0; i < optionsGroup.GetOptionCount(); i++)
+ {
+ const BackendOptions::BackendOption option = optionsGroup.GetOption(i);
+ f(option.GetName(), option.GetValue());
+ }
+ }
+ }
+}
+
} //namespace armnn
, m_ReduceFp32ToBf16(false)
, m_shapeInferenceMethod(armnn::ShapeInferenceMethod::ValidateOnly)
, m_ImportEnabled(false)
+ , m_ModelOptions()
{}
- OptimizerOptions(bool reduceFp32ToFp16, bool debug, bool reduceFp32ToBf16, bool importEnabled)
+ OptimizerOptions(bool reduceFp32ToFp16, bool debug, bool reduceFp32ToBf16, bool importEnabled,
+ ModelOptions modelOptions = {})
: m_ReduceFp32ToFp16(reduceFp32ToFp16)
, m_Debug(debug)
, m_ReduceFp32ToBf16(reduceFp32ToBf16)
, m_shapeInferenceMethod(armnn::ShapeInferenceMethod::ValidateOnly)
, m_ImportEnabled(importEnabled)
+ , m_ModelOptions(modelOptions)
{
if (m_ReduceFp32ToFp16 && m_ReduceFp32ToBf16)
{
OptimizerOptions(bool reduceFp32ToFp16, bool debug, bool reduceFp32ToBf16 = false,
ShapeInferenceMethod shapeInferenceMethod = armnn::ShapeInferenceMethod::ValidateOnly,
- bool importEnabled = false)
+ bool importEnabled = false, ModelOptions modelOptions = {})
: m_ReduceFp32ToFp16(reduceFp32ToFp16)
, m_Debug(debug)
, m_ReduceFp32ToBf16(reduceFp32ToBf16)
, m_shapeInferenceMethod(shapeInferenceMethod)
, m_ImportEnabled(importEnabled)
+ , m_ModelOptions(modelOptions)
{
if (m_ReduceFp32ToFp16 && m_ReduceFp32ToBf16)
{
// Enable Import
bool m_ImportEnabled;
+
+ // Enable Model Options
+ ModelOptions m_ModelOptions;
};
/// Create an optimized version of the network
//
#pragma once
+#include <armnn/BackendOptions.hpp>
#include <armnn/IRuntime.hpp>
#include <memory>
using IBackendContextUniquePtr = std::unique_ptr<IBackendContext>;
+class IBackendModelContext
+{
+public:
+ virtual ~IBackendModelContext() {}
+};
+
} // namespace armnn
\ No newline at end of file
using Optimizations = std::vector<OptimizationPtr>;
using ILayerSupportSharedPtr = std::shared_ptr<ILayerSupport>;
+ using IBackendSpecificModelContextPtr = std::shared_ptr<IBackendModelContext>;
+
using IMemoryManagerUniquePtr = std::unique_ptr<IMemoryManager>;
using IMemoryManagerSharedPtr = std::shared_ptr<IMemoryManager>;
/// The default implementation always returns a default-constructed pointer.
virtual IBackendContextPtr CreateBackendContext(const IRuntime::CreationOptions&) const;
+ virtual IBackendSpecificModelContextPtr CreateBackendSpecificModelContext(const ModelOptions& modelOptions) const;
+
/// Create context specifically used for profiling interaction from backends.
virtual IBackendProfilingContextPtr CreateBackendProfilingContext(const IRuntime::CreationOptions& creationOptions,
IBackendProfilingPtr& backendProfiling);
virtual ILayerSupportSharedPtr GetLayerSupport() const = 0;
+ virtual ILayerSupportSharedPtr GetLayerSupport(const ModelOptions& modelOptions) const
+ {
+ if (modelOptions.empty())
+ {
+ return GetLayerSupport();
+ }
+ return GetLayerSupport(modelOptions);
+ }
+
virtual OptimizationViews OptimizeSubgraphView(const SubgraphView& subgraph) const;
bool SupportsTensorAllocatorAPI() const;
const Network& network = *PolymorphicDowncast<const Network*>(&inNetwork);
std::unique_ptr<Graph> graph = std::make_unique<Graph>(network.GetGraph());
- auto optNet = IOptimizedNetworkPtr(new OptimizedNetwork(std::move(graph)), &IOptimizedNetwork::Destroy);
+ auto optNet = IOptimizedNetworkPtr(new OptimizedNetwork(std::move(graph), options.m_ModelOptions),
+ &IOptimizedNetwork::Destroy);
OptimizedNetwork* optNetObjPtr = PolymorphicDowncast<OptimizedNetwork*>(optNet.get());
{
}
+OptimizedNetwork::OptimizedNetwork(std::unique_ptr<Graph> graph, const ModelOptions& modelOptions)
+ : m_Graph(std::move(graph)), m_Guid(profiling::ProfilingService::GetNextGuid()), m_ModelOptions(modelOptions)
+{
+}
+
OptimizedNetwork::~OptimizedNetwork()
{
}
NetworkOptions m_NetworkOptions;
std::unique_ptr<Graph> m_Graph;
+ ModelOptions m_ModelOptions;
};
class OptimizedNetwork final : public IOptimizedNetwork
{
public:
OptimizedNetwork(std::unique_ptr<Graph> graph);
+ OptimizedNetwork(std::unique_ptr<Graph> graph, const ModelOptions& modelOptions);
~OptimizedNetwork();
Status PrintGraph() override;
profiling::ProfilingGuid GetGuid() const final { return m_Guid; };
Graph& GetGraph() { return *m_Graph; }
+ ModelOptions& GetModelOptions() { return m_ModelOptions; }
private:
std::unique_ptr<Graph> m_Graph;
profiling::ProfilingGuid m_Guid;
+ ModelOptions m_ModelOptions;
};
return IBackendContextPtr{};
}
+IBackendInternal::IBackendSpecificModelContextPtr IBackendInternal::CreateBackendSpecificModelContext(
+ const ModelOptions&) const
+{
+ return IBackendSpecificModelContextPtr{};
+}
+
IBackendInternal::IBackendProfilingContextPtr IBackendInternal::CreateBackendProfilingContext(
const IRuntime::CreationOptions&, IBackendProfilingPtr&)
{
} // anonymous namespace
-bool IWorkloadFactory::IsLayerSupported(const BackendId& backendId,
- const IConnectableLayer& connectableLayer,
- Optional<DataType> dataType,
- std::string& outReasonIfUnsupported)
+bool IWorkloadFactory::IsLayerConfigurationSupported(const BackendId& backendId,
+ const IConnectableLayer& connectableLayer,
+ Optional<DataType> dataType,
+ std::string& outReasonIfUnsupported,
+ const ModelOptions& modelOptions)
{
Optional<std::string&> reason = outReasonIfUnsupported;
bool result;
auto backendFactory = backendRegistry.GetFactory(backendId);
auto backendObject = backendFactory();
- auto layerSupportObject = backendObject->GetLayerSupport();
+ auto layerSupportObject = backendObject->GetLayerSupport(modelOptions);
switch(layer.GetType())
{
return result;
}
+bool IWorkloadFactory::IsLayerSupported(const BackendId& backendId,
+ const IConnectableLayer& connectableLayer,
+ Optional<DataType> dataType,
+ std::string& outReasonIfUnsupported)
+{
+ return IsLayerConfigurationSupported(backendId, connectableLayer, dataType, outReasonIfUnsupported);
+}
+
bool IWorkloadFactory::IsLayerSupported(const IConnectableLayer& connectableLayer,
Optional<DataType> dataType,
std::string& outReasonIfUnsupported)
{
auto layer = PolymorphicDowncast<const Layer*>(&connectableLayer);
- return IsLayerSupported(layer->GetBackendId(), connectableLayer, dataType, outReasonIfUnsupported);
+ return IsLayerConfigurationSupported(layer->GetBackendId(), connectableLayer, dataType, outReasonIfUnsupported);
+}
+
+// TODO merge with defaulted modelOptions above
+bool IWorkloadFactory::IsLayerSupported(const IConnectableLayer& connectableLayer,
+ Optional<DataType> dataType,
+ std::string& outReasonIfUnsupported,
+ const ModelOptions& modelOptions)
+{
+ auto layer = PolymorphicDowncast<const Layer*>(&connectableLayer);
+ return IsLayerConfigurationSupported(layer->GetBackendId(),
+ connectableLayer,
+ dataType,
+ outReasonIfUnsupported,
+ modelOptions);
}
// Default Implementations
Optional<DataType> dataType,
std::string& outReasonIfUnsupported);
+ static bool IsLayerSupported(const IConnectableLayer& layer,
+ Optional<DataType> dataType,
+ std::string& outReasonIfUnsupported,
+ const ModelOptions& modelOptions);
+
virtual bool SupportsSubTensors() const = 0;
ARMNN_DEPRECATED_MSG("Use ITensorHandleFactory::CreateSubTensorHandle instead")
virtual std::unique_ptr<IWorkload> CreateTransposeConvolution2d(
const TransposeConvolution2dQueueDescriptor& descriptor,
const WorkloadInfo& info) const;
+
+private:
+ static bool IsLayerConfigurationSupported(const BackendId& backendId,
+ const IConnectableLayer& connectableLayer,
+ Optional<DataType> dataType,
+ std::string& outReasonIfUnsupported,
+ const ModelOptions& modelOptions = {});
};
} // namespace armnn
ClBackendContext.cpp
ClBackendContext.hpp
ClBackendId.hpp
+ ClBackendModelContext.cpp
+ ClBackendModelContext.hpp
ClContextControl.cpp
ClContextControl.hpp
ClLayerSupport.cpp
#include "ClBackend.hpp"
#include "ClBackendId.hpp"
+#include "ClBackendModelContext.hpp"
#include "ClWorkloadFactory.hpp"
#include "ClBackendContext.hpp"
#include "ClLayerSupport.hpp"
registry.RegisterFactory(std::make_unique<ClTensorHandleFactory>(mgr));
}
-IBackendInternal::IBackendContextPtr
-ClBackend::CreateBackendContext(const IRuntime::CreationOptions& options) const
+IBackendInternal::IBackendContextPtr ClBackend::CreateBackendContext(const IRuntime::CreationOptions& options) const
{
return IBackendContextPtr{new ClBackendContext{options}};
}
return Optimizations{};
}
+IBackendInternal::IBackendSpecificModelContextPtr ClBackend::CreateBackendSpecificModelContext(
+ const ModelOptions& modelOptions) const
+{
+ return IBackendSpecificModelContextPtr{new ClBackendModelContext{modelOptions}};
+}
+
IBackendInternal::ILayerSupportSharedPtr ClBackend::GetLayerSupport() const
{
- static ILayerSupportSharedPtr layerSupport{new ClLayerSupport};
+ static ILayerSupportSharedPtr layerSupport
+ {
+ new ClLayerSupport(IBackendInternal::IBackendSpecificModelContextPtr{})
+ };
+ return layerSupport;
+}
+
+IBackendInternal::ILayerSupportSharedPtr ClBackend::GetLayerSupport(const ModelOptions& modelOptions) const
+{
+ static ILayerSupportSharedPtr layerSupport
+ {
+ new ClLayerSupport(CreateBackendSpecificModelContext(modelOptions))
+ };
return layerSupport;
}
IBackendInternal::Optimizations GetOptimizations() const override;
IBackendInternal::ILayerSupportSharedPtr GetLayerSupport() const override;
+ IBackendInternal::ILayerSupportSharedPtr GetLayerSupport(const ModelOptions& modelOptions) const override;
OptimizationViews OptimizeSubgraphView(const SubgraphView& subgraph) const override;
+
+ IBackendInternal::IBackendSpecificModelContextPtr CreateBackendSpecificModelContext(
+ const ModelOptions& modelOptions) const override;
};
} // namespace armnn
{
return value.AsBool();
}
-
return defaultValue;
}
return defaultValue;
}
-template <typename F>
-void ParseOptions(const std::vector<BackendOptions>& options, BackendId backend, F f)
-{
- for (auto optionsGroup : options)
- {
- if (optionsGroup.GetBackendId() == backend)
- {
- for (size_t i=0; i < optionsGroup.GetOptionCount(); i++)
- {
- const BackendOptions::BackendOption option = optionsGroup.GetOption(i);
- f(option.GetName(), option.GetValue());
- }
- }
- }
-}
-
void ConfigureTuner(arm_compute::CLTuner &tuner, TuningLevel level)
{
tuner.set_tune_new_kernels(true); // Turn on tuning initially.
--- /dev/null
+//
+// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "ClBackendModelContext.hpp"
+
+namespace
+{
+
+bool ParseBool(const armnn::BackendOptions::Var& value, bool defaultValue)
+{
+ if (value.IsBool())
+ {
+ return value.AsBool();
+ }
+ return defaultValue;
+}
+
+} // namespace anonymous
+
+namespace armnn
+{
+
+ClBackendModelContext::ClBackendModelContext(const ModelOptions& modelOptions)
+ : m_IsFastMathEnabled(false)
+{
+ if (!modelOptions.empty())
+ {
+ ParseOptions(modelOptions, "GpuAcc", [&](std::string name, const BackendOptions::Var& value)
+ {
+ if (name == "FastMathEnabled")
+ {
+ m_IsFastMathEnabled |= ParseBool(value, false);
+ }
+ });
+ }
+}
+
+bool ClBackendModelContext::IsFastMathEnabled() const
+{
+ return m_IsFastMathEnabled;
+}
+
+} // namespace armnn
\ No newline at end of file
--- /dev/null
+//
+// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+#pragma once
+
+#include <armnn/backends/IBackendContext.hpp>
+
+namespace armnn
+{
+
+class ClBackendModelContext : public IBackendModelContext
+{
+public:
+ ClBackendModelContext(const ModelOptions& modelOptions);
+
+ bool IsFastMathEnabled() const;
+
+private:
+ bool m_IsFastMathEnabled;
+};
+
+} // namespace armnn
\ No newline at end of file
#include "ClLayerSupport.hpp"
#include "ClBackendId.hpp"
+#include "ClBackendModelContext.hpp"
-#include <armnn/utility/IgnoreUnused.hpp>
#include <armnn/Descriptors.hpp>
#include <armnn/BackendRegistry.hpp>
#include <InternalTypes.hpp>
#include <LayerSupportCommon.hpp>
+#include <armnn/utility/IgnoreUnused.hpp>
+#include <armnn/utility/PolymorphicDowncast.hpp>
+
#if defined(ARMCOMPUTECL_ENABLED)
#include <aclCommon/ArmComputeUtils.hpp>
#include <aclCommon/ArmComputeTensorUtils.hpp>
}
} // anonymous namespace
+ClLayerSupport::ClLayerSupport(const IBackendInternal::IBackendSpecificModelContextPtr& modelContextPtr)
+ : m_ModelContextPtr(modelContextPtr)
+{
+}
+
+ClLayerSupport::ClLayerSupport()
+ : m_ModelContextPtr(nullptr)
+{
+}
+
bool ClLayerSupport::IsAbsSupported(const TensorInfo& input,
const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported) const
const Optional<TensorInfo>& biases,
Optional<std::string&> reasonIfUnsupported) const
{
+ bool isFastMathEnabled = false;
+#if defined(ARMCOMPUTECL_ENABLED)
+ if (m_ModelContextPtr)
+ {
+ if (m_ModelContextPtr.get() != nullptr)
+ {
+ auto modelOptions = dynamic_cast<ClBackendModelContext*>(m_ModelContextPtr.get());
+ if (modelOptions)
+ {
+ isFastMathEnabled = modelOptions->IsFastMathEnabled();
+ }
+ }
+ }
+#endif
+
FORWARD_WORKLOAD_VALIDATE_FUNC(ClConvolution2dWorkloadValidate,
reasonIfUnsupported,
input,
output,
descriptor,
weights,
- biases);
+ biases,
+ isFastMathEnabled);
}
bool ClLayerSupport::IsDequantizeSupported(const TensorInfo& input,
//
#pragma once
+#include <armnn/backends/IBackendInternal.hpp>
+
#include <backendsCommon/LayerSupportBase.hpp>
namespace armnn
class ClLayerSupport : public LayerSupportBase
{
public:
+ explicit ClLayerSupport(const IBackendInternal::IBackendSpecificModelContextPtr& modelContextPtr);
+ ClLayerSupport();
+ ~ClLayerSupport() {}
+
ARMNN_DEPRECATED_MSG("Use IsElementwiseUnarySupported instead")
bool IsAbsSupported(const TensorInfo& input,
const TensorInfo& output,
const TransposeDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported = EmptyOptional()) const override;
+private:
+ const IBackendInternal::IBackendSpecificModelContextPtr m_ModelContextPtr;
+
};
} // namespace armnn
BACKEND_SOURCES := \
ClBackend.cpp \
ClBackendContext.cpp \
+ ClBackendModelContext.cpp \
ClContextControl.cpp \
ClLayerSupport.cpp \
ClRegistryInitializer.cpp \
BOOST_TEST(GraphHasNamedLayer(graph, "output layer"));
}
+BOOST_AUTO_TEST_CASE(FastMathEnabledTestOnGpuAcc)
+{
+ armnn::INetworkPtr net(armnn::INetwork::Create());
+
+ armnn::IConnectableLayer* input = net->AddInputLayer(0);
+ armnn::IConnectableLayer* output = net->AddOutputLayer(0);
+
+ input->GetOutputSlot(0).Connect(output->GetInputSlot(0));
+ input->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 1, 1, 4, 4 }, armnn::DataType::Float32));
+
+ armnn::IRuntime::CreationOptions options;
+ armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options));
+
+ std::vector<armnn::BackendId> backends = {armnn::Compute::GpuAcc};
+ armnn::OptimizerOptions optimizerOptions;
+ armnn::BackendOptions modelOptions("GpuAcc", {{"FastMathEnabled", true}});
+ optimizerOptions.m_ModelOptions.push_back(modelOptions);
+
+ armnn::IOptimizedNetworkPtr optimizedNet = armnn::Optimize(
+ *net, backends, runtime->GetDeviceSpec(), optimizerOptions);
+
+ BOOST_CHECK(optimizedNet);
+
+ auto modelOptionsOut = static_cast<armnn::OptimizedNetwork*>(optimizedNet.get())->GetModelOptions();
+
+ BOOST_TEST(modelOptionsOut.size() == 1);
+ BOOST_TEST(modelOptionsOut[0].GetOption(0).GetName() == "FastMathEnabled");
+ BOOST_TEST(modelOptionsOut[0].GetOption(0).GetValue().AsBool() == true);
+}
+
BOOST_AUTO_TEST_SUITE_END();
const TensorInfo& output,
const Convolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const Optional<TensorInfo>& biases)
+ const Optional<TensorInfo>& biases,
+ bool isFastMathEnabled)
{
const arm_compute::TensorInfo aclInputInfo = BuildArmComputeTensorInfo(input, descriptor.m_DataLayout);
const arm_compute::TensorInfo aclOutputInfo = BuildArmComputeTensorInfo(output, descriptor.m_DataLayout);
&aclOutputInfo,
layerInfo,
arm_compute::WeightsInfo(),
- aclDilationInfo);
+ aclDilationInfo,
+ arm_compute::ActivationLayerInfo(),
+ isFastMathEnabled);
}
ClConvolution2dWorkload::ClConvolution2dWorkload(const Convolution2dQueueDescriptor& descriptor,
const TensorInfo& output,
const Convolution2dDescriptor& descriptor,
const TensorInfo& weights,
- const Optional<TensorInfo>& biases);
+ const Optional<TensorInfo>& biases,
+ bool isFastMathEnabled = false);
class ClConvolution2dWorkload : public BaseWorkload<Convolution2dQueueDescriptor>
{
NeonBackend.cpp
NeonBackend.hpp
NeonBackendId.hpp
+ NeonBackendModelContext.hpp
+ NeonBackendModelContext.cpp
NeonInterceptorScheduler.hpp
NeonInterceptorScheduler.cpp
NeonLayerSupport.cpp
#include "NeonBackend.hpp"
#include "NeonBackendId.hpp"
+#include "NeonBackendModelContext.hpp"
#include "NeonWorkloadFactory.hpp"
#include "NeonLayerSupport.hpp"
#include "NeonTensorHandleFactory.hpp"
return Optimizations{};
}
+IBackendInternal::IBackendSpecificModelContextPtr NeonBackend::CreateBackendSpecificModelContext(
+ const ModelOptions& modelOptions) const
+{
+ return IBackendSpecificModelContextPtr{new NeonBackendModelContext{modelOptions}};
+}
+
IBackendInternal::ILayerSupportSharedPtr NeonBackend::GetLayerSupport() const
{
- static ILayerSupportSharedPtr layerSupport{new NeonLayerSupport};
+ static ILayerSupportSharedPtr layerSupport
+ {
+ new NeonLayerSupport(IBackendInternal::IBackendSpecificModelContextPtr{})
+ };
+ return layerSupport;
+}
+
+IBackendInternal::ILayerSupportSharedPtr NeonBackend::GetLayerSupport(const ModelOptions& modelOptions) const
+{
+ static ILayerSupportSharedPtr layerSupport
+ {
+ new NeonLayerSupport(CreateBackendSpecificModelContext(modelOptions))
+ };
return layerSupport;
}
const IRuntime::CreationOptions&, IBackendProfilingPtr& backendProfiling) override;
IBackendInternal::Optimizations GetOptimizations() const override;
IBackendInternal::ILayerSupportSharedPtr GetLayerSupport() const override;
+ IBackendInternal::ILayerSupportSharedPtr GetLayerSupport(const ModelOptions& modelOptions) const override;
OptimizationViews OptimizeSubgraphView(const SubgraphView& subgraph) const override;
std::vector<ITensorHandleFactory::FactoryId> GetHandleFactoryPreferences() const override;
void RegisterTensorHandleFactories(class TensorHandleFactoryRegistry& registry) override;
+
+ IBackendInternal::IBackendSpecificModelContextPtr CreateBackendSpecificModelContext(
+ const ModelOptions& modelOptions) const override;
};
} // namespace armnn
--- /dev/null
+//
+// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "NeonBackendModelContext.hpp"
+
+namespace
+{
+
+bool ParseBool(const armnn::BackendOptions::Var& value, bool defaultValue)
+{
+ if (value.IsBool())
+ {
+ return value.AsBool();
+ }
+ return defaultValue;
+}
+
+} // namespace anonymous
+
+namespace armnn
+{
+
+NeonBackendModelContext::NeonBackendModelContext(const ModelOptions& modelOptions)
+ : m_IsFastMathEnabled(false)
+{
+ if (!modelOptions.empty())
+ {
+ ParseOptions(modelOptions, "CpuAcc", [&](std::string name, const BackendOptions::Var& value)
+ {
+ if (name == "FastMathEnabled")
+ {
+ m_IsFastMathEnabled |= ParseBool(value, false);
+ }
+ });
+ }
+}
+
+bool NeonBackendModelContext::IsFastMathEnabled() const
+{
+ return m_IsFastMathEnabled;
+}
+
+} // namespace armnn
\ No newline at end of file
--- /dev/null
+//
+// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+#pragma once
+
+#include <armnn/backends/IBackendContext.hpp>
+
+namespace armnn
+{
+
+class NeonBackendModelContext : public IBackendModelContext
+{
+public:
+ NeonBackendModelContext(const ModelOptions& modelOptions);
+
+ bool IsFastMathEnabled() const;
+
+private:
+ bool m_IsFastMathEnabled;
+};
+
+} // namespace armnn
\ No newline at end of file
#include "NeonLayerSupport.hpp"
#include "NeonBackendId.hpp"
+#include "NeonBackendModelContext.hpp"
#include <armnn/Descriptors.hpp>
#include <armnn/Exceptions.hpp>
#include <InternalTypes.hpp>
#include <LayerSupportCommon.hpp>
#include <armnn/utility/IgnoreUnused.hpp>
+#include <armnn/utility/PolymorphicDowncast.hpp>
#if defined(ARMCOMPUTENEON_ENABLED)
#include <aclCommon/ArmComputeUtils.hpp>
#endif
} // anonymous namespace
+NeonLayerSupport::NeonLayerSupport(const IBackendInternal::IBackendSpecificModelContextPtr& modelContextPtr)
+ : m_ModelContextPtr(modelContextPtr)
+{
+}
+
+NeonLayerSupport::NeonLayerSupport()
+ : m_ModelContextPtr(nullptr)
+{
+}
+
bool NeonLayerSupport::IsAbsSupported(const TensorInfo& input,
const TensorInfo& output,
Optional<std::string&> reasonIfUnsupported) const
const Optional<TensorInfo>& biases,
Optional<std::string&> reasonIfUnsupported) const
{
+ bool isFastMathEnabled = false;
+#if defined(ARMCOMPUTENEON_ENABLED)
+ if (m_ModelContextPtr)
+ {
+ if (m_ModelContextPtr.get() != nullptr)
+ {
+ auto modelOptions = armnn::PolymorphicDowncast<NeonBackendModelContext*>(m_ModelContextPtr.get());
+ if (modelOptions)
+ {
+ isFastMathEnabled = modelOptions->IsFastMathEnabled();
+ }
+ }
+ }
+#endif
+
FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConvolution2dWorkloadValidate,
reasonIfUnsupported,
input,
output,
descriptor,
weights,
- biases);
+ biases,
+ isFastMathEnabled);
}
bool NeonLayerSupport::IsDepthToSpaceSupported(const TensorInfo& input,
//
#pragma once
+#include <armnn/backends/IBackendInternal.hpp>
+
#include <backendsCommon/LayerSupportBase.hpp>
namespace armnn
class NeonLayerSupport : public LayerSupportBase
{
public:
+ explicit NeonLayerSupport(const IBackendInternal::IBackendSpecificModelContextPtr& modelContextPtr);
+ NeonLayerSupport();
+
+ ~NeonLayerSupport() {}
+
ARMNN_DEPRECATED_MSG("Use IsElementwiseUnarySupported instead")
bool IsAbsSupported(const TensorInfo& input,
const TensorInfo& output,
const TransposeDescriptor& descriptor,
Optional<std::string&> reasonIfUnsupported = EmptyOptional()) const override;
+private:
+ const IBackendInternal::IBackendSpecificModelContextPtr m_ModelContextPtr;
+
}; // class NeonLayerSupport
} // namespace armnn
BACKEND_SOURCES := \
NeonBackend.cpp \
+ NeonBackendModelContext.cpp \
NeonInterceptorScheduler.cpp \
NeonLayerSupport.cpp \
NeonRegistryInitializer.cpp \
BOOST_CHECK(!optNet);
}
+BOOST_AUTO_TEST_CASE(FastMathEnabledTestOnCpuAcc)
+{
+ armnn::INetworkPtr net(armnn::INetwork::Create());
+
+ armnn::IConnectableLayer* input = net->AddInputLayer(0);
+ armnn::IConnectableLayer* output = net->AddOutputLayer(0);
+
+ input->GetOutputSlot(0).Connect(output->GetInputSlot(0));
+ input->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 1, 1, 4, 4 }, armnn::DataType::Float32));
+
+ armnn::IRuntime::CreationOptions options;
+ armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options));
+
+ std::vector<armnn::BackendId> backends = {armnn::Compute::CpuAcc};
+ armnn::OptimizerOptions optimizerOptions;
+ armnn::BackendOptions modelOptions("CpuAcc", {{"FastMathEnabled", true}});
+ optimizerOptions.m_ModelOptions.push_back(modelOptions);
+
+ armnn::IOptimizedNetworkPtr optimizedNet = armnn::Optimize(
+ *net, backends, runtime->GetDeviceSpec(), optimizerOptions);
+
+ BOOST_CHECK(optimizedNet);
+
+ auto modelOptionsOut = static_cast<armnn::OptimizedNetwork*>(optimizedNet.get())->GetModelOptions();
+
+ BOOST_TEST(modelOptionsOut.size() == 1);
+ BOOST_TEST(modelOptionsOut[0].GetOption(0).GetName() == "FastMathEnabled");
+ BOOST_TEST(modelOptionsOut[0].GetOption(0).GetValue().AsBool() == true);
+}
+
BOOST_AUTO_TEST_SUITE_END()
\ No newline at end of file
using namespace armcomputetensorutils;
arm_compute::Status NeonConvolution2dWorkloadValidate(const TensorInfo& input,
- const TensorInfo& output,
- const Convolution2dDescriptor& descriptor,
- const TensorInfo& weights,
- const Optional<TensorInfo>& biases)
+ const TensorInfo& output,
+ const Convolution2dDescriptor& descriptor,
+ const TensorInfo& weights,
+ const Optional<TensorInfo>& biases,
+ bool isFastMathEnabled)
{
const arm_compute::TensorInfo aclInputInfo = BuildArmComputeTensorInfo(input, descriptor.m_DataLayout);
const arm_compute::TensorInfo aclOutputInfo = BuildArmComputeTensorInfo(output, descriptor.m_DataLayout);
&aclOutputInfo,
layerInfo,
arm_compute::WeightsInfo(),
- aclDilationInfo);
+ aclDilationInfo,
+ arm_compute::ActivationLayerInfo(),
+ isFastMathEnabled);
}
NeonConvolution2dWorkload::NeonConvolution2dWorkload(
{
arm_compute::Status NeonConvolution2dWorkloadValidate(const TensorInfo& input,
- const TensorInfo& output,
- const Convolution2dDescriptor& descriptor,
- const TensorInfo& weights,
- const Optional<TensorInfo>& biases);
+ const TensorInfo& output,
+ const Convolution2dDescriptor& descriptor,
+ const TensorInfo& weights,
+ const Optional<TensorInfo>& biases,
+ bool isFastMathEnabled = false);
class NeonConvolution2dWorkload : public BaseWorkload<Convolution2dQueueDescriptor>
{