diff options
author | Ryan OShea <ryan.oshea3@arm.com> | 2023-07-25 14:28:27 +0100 |
---|---|---|
committer | ryan.oshea3 <ryan.oshea3@arm.com> | 2023-08-02 14:25:26 +0000 |
commit | b4c493430567bff25e61e9df0dbab554c29f635d (patch) | |
tree | 9d9fa320c25f5aa9f89aafb8b9b8b6c071990161 /src/armnn/Network.cpp | |
parent | 083802d04b7a4499c4daba860c57e4f152f9c060 (diff) | |
download | armnn-b4c493430567bff25e61e9df0dbab554c29f635d.tar.gz |
IVGCVSW-7880 Add check for FP16 backend support
* Check if preferred backends have FP16 support before enable fp16-turbo-mode
* Unit tests
* Replaced global gpuAccCapabilities with getter method construction
* Replaced deprecated function call in SL shim
Signed-off-by: Narumol Prangnawarat <narumol.prangnawarat@arm.com>
Signed-off-by: Ryan OShea <ryan.oshea3@arm.com>
Change-Id: If29b62b330ca8987de8acf6408db11daf25ca0b5
Diffstat (limited to 'src/armnn/Network.cpp')
-rw-r--r-- | src/armnn/Network.cpp | 77 |
1 files changed, 66 insertions, 11 deletions
diff --git a/src/armnn/Network.cpp b/src/armnn/Network.cpp index 22d2c78c65..3074c1ffe9 100644 --- a/src/armnn/Network.cpp +++ b/src/armnn/Network.cpp @@ -37,6 +37,7 @@ #include <algorithm> #include <memory> #include <vector> +#include <armnn/ArmNN.hpp> namespace armnn { @@ -837,14 +838,18 @@ OptimizationResult AttemptBackendAssignment(BackendSettings& backendSettings, // need to set the compute device on the layer // before we can check if it is supported layer->SetBackendId(backend); + std::string currentReasonIfUnsupported; // To run FP16 operations on CpuAcc we need at least v8.2 architecture. If the available architecture // is older than v8.2, we can check if the operator is supported by changing operator inputs & outputs // to be FP32 and inserting convert layers around the FP32 operator. - bool isLayerSupported = IWorkloadFactory::IsLayerSupported(*layer, EmptyOptional(), reasonIfUnsupported); + bool isLayerSupported = IWorkloadFactory::IsLayerSupported(*layer, EmptyOptional(), currentReasonIfUnsupported); + reasonIfUnsupported += currentReasonIfUnsupported; + // This string matches the error message that is produced by acl when attempting to run FP16 kernels on + // a cpu or build that does not have fp16 support. We use this to check if we should add + // conversion layers or not. std::string checkStr = "This CPU architecture does not support F16 data type, you need v8.2 or above"; - if (!isLayerSupported || - reasonIfUnsupported.find(checkStr) != std::string::npos) + if (!isLayerSupported || currentReasonIfUnsupported.find(checkStr) != std::string::npos) { if (dataTypeIn == DataType::Float16 || dataTypeOut == DataType::Float16) { @@ -994,6 +999,51 @@ inline std::vector<DataType> GetLayerInOutDatatype(const Layer* layer) return {dataTypeIn, dataTypeOut}; } +bool CheckFp16Support(BackendsMap& backends, + const std::vector<BackendId>& availablePreferredBackends) +{ + bool hasFp16 = false; + // Check if the first preferred backend has FP16 support + auto firstBackend = availablePreferredBackends[0]; + auto backendObjPtr = backends.find(firstBackend)->second.get(); + ARMNN_ASSERT(backendObjPtr); + auto hasFp16Capability = BackendOptions::BackendOption{"HasFp16", true}; + auto backendCapabilities = backendObjPtr->GetCapabilities(); + + if (HasMatchingCapability(hasFp16Capability, backendCapabilities)) + { + // First preferred backend has FP16 support. Enable reduce FP32 to FP16 when fp16-turbo-mode is enabled. + hasFp16 = true; + ARMNN_LOG(debug) << "The first available preferred backend: " << firstBackend + << ", has FP16 support."; + } + else + { + ARMNN_LOG(warning) << "The first available preferred backend: " << firstBackend + << ", does not have FP16 support. " + << "The FP16 turbo mode option will be disable. It will run using FP32."; + } + + // Check if the rest of the available preferred backends have FP16 support + for (size_t i = 1; i < availablePreferredBackends.size(); ++i) + { + auto backend = availablePreferredBackends[i]; + backendObjPtr = backends.find(backend)->second.get(); + backendCapabilities = backendObjPtr->GetCapabilities(); + if (!HasMatchingCapability(hasFp16Capability, backendCapabilities)) + { + ARMNN_LOG(warning) << "Next preferred backend: " << backend << ", does not have FP16 support. " + << "It will run using FP32 when falling back to this backend."; + } + else + { + ARMNN_LOG(debug) << "Next preferred backend: " << backend << ", has FP16 support."; + } + } + + return hasFp16; +} + // Refactor to allow passing the IConnectableLayer* rather than Layer Iterator // on Graph and SubgraphView which are different types. void AssignBackendsIConnectable(OptimizedNetworkImpl* optNetObjPtr, @@ -1913,16 +1963,10 @@ IOptimizedNetworkPtr Optimize(const Graph& inGraph, FuseBatchNormIntoDepthwiseConvolution2DFloat16())); - if (options.GetReduceFp32ToFp16()) - { - ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "Optimizer_ReduceFp32ToFp16"); - Optimizer::Pass(optGraph, MakeOptimizations(Fp32NetworkToFp16Converter())); - Optimizer::Pass(optGraph, MakeOptimizations(ConvertConstantsFloatToHalf())); - } - // Initialize backend settings BackendSettings backendSettings(backendPreferences, deviceSpec); - if (backendSettings.GetAvailablePreferredBackends().empty()) + auto availablePreferredBackends = backendSettings.GetAvailablePreferredBackends(); + if (availablePreferredBackends.empty()) { std::stringstream failureMsg; failureMsg << "None of the preferred backends " << backendPreferences @@ -1935,6 +1979,17 @@ IOptimizedNetworkPtr Optimize(const Graph& inGraph, TensorHandleFactoryRegistry tensorHandleFactoryRegistry; BackendsMap backends = CreateSupportedBackends(tensorHandleFactoryRegistry, backendSettings); + if (options.GetReduceFp32ToFp16()) + { + bool hasFp16 = CheckFp16Support(backends, availablePreferredBackends); + if (hasFp16) + { + ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "Optimizer_ReduceFp32ToFp16"); + Optimizer::Pass(optGraph, MakeOptimizations(Fp32NetworkToFp16Converter())); + Optimizer::Pass(optGraph, MakeOptimizations(ConvertConstantsFloatToHalf())); + } + } + // Assign an available backend to each layer Graph::Iterator firstLayer = optGraph.begin(); Graph::Iterator lastLayer = optGraph.end(); |