1 //
2 // Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #define LOG_TAG "arm-armnn-sl"
7
8 #include "ArmnnDevice.hpp"
9
10 #include <LegacyUtils.h>
11 #include <OperationsUtils.h>
12
13 #include <log/log.h>
14
15 #include <memory>
16 #include <string>
17
18 #ifdef __ANDROID__
19 #include <android/log.h>
20 #endif
21
22 namespace
23 {
24
GetBackendString(const armnn_driver::DriverOptions & options)25 std::string GetBackendString(const armnn_driver::DriverOptions& options)
26 {
27 std::stringstream backends;
28 for (auto&& b : options.GetBackends())
29 {
30 backends << b << " ";
31 }
32 return backends.str();
33 }
34
35 } // anonymous namespace
36
37 namespace armnn_driver
38 {
39
40 using namespace android::nn;
41
ArmnnDevice(DriverOptions options)42 ArmnnDevice::ArmnnDevice(DriverOptions options)
43 : m_Runtime(nullptr, nullptr)
44 , m_ClTunedParameters(nullptr)
45 , m_Options(std::move(options))
46 {
47 // First check if the DriverOptions is happy.
48 if (options.ShouldExit())
49 {
50 // Is this a good or bad exit?
51 if (options.GetExitCode() != EXIT_SUCCESS)
52 {
53 throw armnn::InvalidArgumentException("ArmnnDevice: Insufficient or illegal options specified.");
54 }
55 else
56 {
57 throw armnn::InvalidArgumentException("ArmnnDevice: Nothing to do.");
58 }
59 }
60
61 initVLogMask();
62 VLOG(DRIVER) << "ArmnnDevice::ArmnnDevice()";
63
64 #ifdef __ANDROID__
65 __android_log_print(ANDROID_LOG_DEBUG, "ARMNN_SL", "ArmnnDevice::ArmnnDevice()");
66 #endif
67
68 armnn::ConfigureLogging(false, m_Options.IsVerboseLoggingEnabled(), armnn::LogSeverity::Trace);
69 if (m_Options.IsVerboseLoggingEnabled())
70 {
71 SetMinimumLogSeverity(android::base::VERBOSE);
72 }
73 else
74 {
75 SetMinimumLogSeverity(android::base::INFO);
76 }
77 armnn::IRuntime::CreationOptions runtimeOptions;
78
79 #if defined(ARMCOMPUTECL_ENABLED)
80 if (std::find(m_Options.GetBackends().begin(),
81 m_Options.GetBackends().end(),
82 armnn::Compute::GpuAcc) != m_Options.GetBackends().end())
83 {
84 try
85 {
86 if (!m_Options.GetClTunedParametersFile().empty())
87 {
88 m_ClTunedParameters = armnn::IGpuAccTunedParameters::Create(m_Options.GetClTunedParametersMode(),
89 m_Options.GetClTuningLevel());
90 try
91 {
92 m_ClTunedParameters->Load(m_Options.GetClTunedParametersFile().c_str());
93 }
94 catch (std::exception& error)
95 {
96 // This is only a warning because the file won't exist the first time you are generating it.
97 VLOG(DRIVER) << "ArmnnDevice: Failed to load CL tuned parameters file "
98 << m_Options.GetClTunedParametersFile().c_str() << " : " << error.what();
99 }
100 runtimeOptions.m_GpuAccTunedParameters = m_ClTunedParameters;
101 }
102 }
103 catch (const armnn::ClRuntimeUnavailableException& error)
104 {
105 VLOG(DRIVER) << "ArmnnDevice: Failed to setup CL runtime: %s. Device will be unavailable." << error.what();
106 }
107 catch (std::exception& error)
108 {
109 VLOG(DRIVER) << "ArmnnDevice: Unknown exception: %s. Device will be unavailable." << error.what();
110 }
111 }
112 #endif
113 runtimeOptions.m_EnableGpuProfiling = m_Options.IsGpuProfilingEnabled();
114 m_Runtime = armnn::IRuntime::Create(runtimeOptions);
115
116 std::vector<armnn::BackendId> backends;
117
118 if (m_Runtime)
119 {
120 const armnn::BackendIdSet supportedDevices = m_Runtime->GetDeviceSpec().GetSupportedBackends();
121 for (auto &backend : m_Options.GetBackends())
122 {
123 if (std::find(supportedDevices.cbegin(), supportedDevices.cend(), backend) == supportedDevices.cend())
124 {
125 VLOG(DRIVER) << "ArmnnDevice: Requested unknown backend " << backend.Get().c_str();
126 }
127 else
128 {
129 if (m_Options.isAsyncModelExecutionEnabled() &&
130 armnn::HasCapability(armnn::BackendOptions::BackendOption{"AsyncExecution", false}, backend))
131 {
132 VLOG(DRIVER) << "ArmnnDevice: ArmNN does not support AsyncExecution with the following backend: "
133 << backend.Get().c_str();
134 }
135 else
136 {
137 backends.push_back(backend);
138 }
139 }
140 }
141 }
142
143 if (backends.empty())
144 {
145 // No known backend specified
146 throw armnn::InvalidArgumentException("ArmnnDevice: No known backend specified.");
147 }
148
149 m_Options.SetBackends(backends);
150 VLOG(DRIVER) << "ArmnnDevice: Created device with the following backends: " << GetBackendString(m_Options).c_str();
151
152 #ifdef __ANDROID__
153 __android_log_print(ANDROID_LOG_DEBUG,
154 "ARMNN_SL",
155 "ArmnnDevice: Created device with the following backends: %s",
156 GetBackendString(m_Options).c_str());
157 #endif
158 }
159
160 } // namespace armnn_driver
161