Github #273 Handle failure to initialise BackendContext in Runtime
authorMatthew Bentham <Matthew.Bentham@arm.com>
Tue, 4 Feb 2020 10:03:55 +0000 (10:03 +0000)
committerDerek Lamberti <derek.lamberti@arm.com>
Tue, 4 Feb 2020 13:13:46 +0000 (13:13 +0000)
Define CreateBackendContext to throw BackendUnavailableException
if necessary runtime components are missing.

Handle this in the constructor of Runtime by not adding those
backends to the internal DeviceSpec owned by the Runtime.

Signed-off-by: Matthew Bentham <Matthew.Bentham@arm.com>
Change-Id: Iadffb5240e32e1f105683c4d361276b92d1e720c

include/armnn/Exceptions.hpp
include/armnn/backends/IBackendInternal.hpp
src/armnn/DeviceSpec.hpp
src/armnn/Runtime.cpp
src/armnn/Runtime.hpp

index e21e974..066f59f 100644 (file)
@@ -64,12 +64,19 @@ private:
     std::string m_Message;
 };
 
-class ClRuntimeUnavailableException : public Exception
+/// Class for non-fatal exceptions raised while initialising a backend
+class BackendUnavailableException : public Exception
 {
 public:
     using Exception::Exception;
 };
 
+class ClRuntimeUnavailableException : public BackendUnavailableException
+{
+public:
+    using BackendUnavailableException::BackendUnavailableException;
+};
+
 class InvalidArgumentException : public Exception
 {
 public:
index 29097b4..6c919ee 100644 (file)
@@ -115,9 +115,16 @@ public:
     virtual IWorkloadFactoryPtr CreateWorkloadFactory(
         class TensorHandleFactoryRegistry& tensorHandleFactoryRegistry) const;
 
+    /// Create the runtime context of the backend
+    ///
+    /// Implementations may return a default-constructed IBackendContextPtr if
+    /// no context is needed at runtime.
+    /// Implementations must throw BackendUnavailableException if the backend
+    /// cannot be used (for example, necessary accelerator hardware is not present).
+    /// The default implementation always returns a default-constructed pointer.
     virtual IBackendContextPtr CreateBackendContext(const IRuntime::CreationOptions&) const;
 
-    // Context specifically used for profiling interaction from backends.
+    /// Create context specifically used for profiling interaction from backends.
     virtual IBackendProfilingContextPtr CreateBackendProfilingContext(const IRuntime::CreationOptions& creationOptions,
         armnn::profiling::IBackendProfiling& backendProfiling) const;
 
index 703a4b1..a1457cf 100644 (file)
@@ -14,6 +14,9 @@ namespace armnn
 class DeviceSpec : public IDeviceSpec
 {
 public:
+    DeviceSpec()
+    {}
+
     DeviceSpec(const BackendIdSet& supportedBackends)
         : m_SupportedBackends{supportedBackends} {}
 
@@ -48,7 +51,6 @@ public:
     }
 
 private:
-    DeviceSpec() = delete;
     BackendIdSet m_SupportedBackends;
     BackendIdSet m_DynamicBackends;
 };
index 2d7269a..47c998a 100644 (file)
@@ -153,7 +153,6 @@ const std::shared_ptr<IProfiler> Runtime::GetProfiler(NetworkId networkId) const
 
 Runtime::Runtime(const CreationOptions& options)
     : m_NetworkIdCounter(0)
-    , m_DeviceSpec{BackendRegistryInstance().GetBackendIds()}
 {
     ARMNN_LOG(info) << "ArmNN v" << ARMNN_VERSION << "\n";
 
@@ -164,12 +163,11 @@ Runtime::Runtime(const CreationOptions& options)
     // goes through the backend registry
     LoadDynamicBackends(options.m_DynamicBackendsPath);
 
+    BackendIdSet supportedBackends;
     for (const auto& id : BackendRegistryInstance().GetBackendIds())
     {
         // Store backend contexts for the supported ones
-        const BackendIdSet& supportedBackends = m_DeviceSpec.GetSupportedBackends();
-        if (supportedBackends.find(id) != supportedBackends.end())
-        {
+        try {
             auto factoryFun = BackendRegistryInstance().GetFactory(id);
             auto backend = factoryFun();
             BOOST_ASSERT(backend.get() != nullptr);
@@ -182,8 +180,15 @@ Runtime::Runtime(const CreationOptions& options)
             {
                 m_BackendContexts.emplace(std::make_pair(id, std::move(context)));
             }
+            supportedBackends.emplace(id);
+        }
+        catch (const BackendUnavailableException&)
+        {
+            // Ignore backends which are unavailable
         }
+
     }
+    m_DeviceSpec.AddSupportedBackends(supportedBackends);
 }
 
 Runtime::~Runtime()
index e5debbf..2ad3c96 100644 (file)
@@ -73,8 +73,6 @@ public:
     virtual void RegisterDebugCallback(NetworkId networkId, const DebugCallbackFunction& func) override;
 
     /// Creates a runtime for workload execution.
-    /// May throw a ClRuntimeUnavailableException if @a defaultComputeDevice requires a CL runtime but
-    /// it cannot be setup for some reason.
     Runtime(const CreationOptions& options);
 
     ~Runtime();