diff options
Diffstat (limited to 'ArmnnDriver.cpp')
-rw-r--r-- | ArmnnDriver.cpp | 453 |
1 files changed, 0 insertions, 453 deletions
diff --git a/ArmnnDriver.cpp b/ArmnnDriver.cpp deleted file mode 100644 index 4d58249e..00000000 --- a/ArmnnDriver.cpp +++ /dev/null @@ -1,453 +0,0 @@ -// -// Copyright © 2017 Arm Ltd. All rights reserved. -// See LICENSE file in the project root for full license information. -// - -#define LOG_TAG "ArmnnDriver" - -#include "ArmnnDriver.hpp" -#include "ArmnnPreparedModel.hpp" -#include "ModelToINetworkConverter.hpp" -#include "Utils.hpp" - -#include <log/log.h> -#include "SystemPropertiesUtils.hpp" - -#include "OperationsUtils.h" - -#if defined(ARMNN_ANDROID_P) -// The headers of the ML framework have changed between Android O and Android P. -// The validation functions have been moved into their own header, ValidateHal.h. -#include <ValidateHal.h> -#endif - -#include <boost/algorithm/string/predicate.hpp> -#include <boost/program_options.hpp> - -#include <cassert> -#include <functional> -#include <string> -#include <sstream> - -using namespace android; -using namespace std; - -namespace -{ - -const char *g_Float32PerformanceExecTimeName = "ArmNN.float32Performance.execTime"; -const char *g_Float32PerformancePowerUsageName = "ArmNN.float32Performance.powerUsage"; -const char *g_Quantized8PerformanceExecTimeName = "ArmNN.quantized8Performance.execTime"; -const char *g_Quantized8PerformancePowerUsageName = "ArmNN.quantized8Performance.powerUsage"; - -}; //namespace - -namespace armnn_driver -{ - -DriverOptions::DriverOptions(armnn::Compute computeDevice) -: m_ComputeDevice(computeDevice) -, m_VerboseLogging(false) -, m_UseAndroidNnCpuExecutor(false) -, m_ClTunedParametersMode(armnn::IClTunedParameters::Mode::UseTunedParameters) -{ -} - -DriverOptions::DriverOptions(int argc, char** argv) -: m_ComputeDevice(armnn::Compute::GpuAcc) -, m_VerboseLogging(false) -, m_UseAndroidNnCpuExecutor(false) -, m_ClTunedParametersMode(armnn::IClTunedParameters::Mode::UseTunedParameters) -{ - namespace po = boost::program_options; - - std::string computeDeviceAsString; - std::string unsupportedOperationsAsString; - std::string clTunedParametersModeAsString; - - po::options_description optionsDesc("Options"); - optionsDesc.add_options() - ("compute,c", - po::value<std::string>(&computeDeviceAsString)->default_value("GpuAcc"), - "Which device to run layers on by default. Possible values are: CpuRef, CpuAcc, GpuAcc") - - ("verbose-logging,v", - po::bool_switch(&m_VerboseLogging), - "Turns verbose logging on") - - ("use-androidnn-cpu-executor,e", - po::bool_switch(&m_UseAndroidNnCpuExecutor), - "Forces the driver to satisfy requests via the Android-provided CpuExecutor") - - ("request-inputs-and-outputs-dump-dir,d", - po::value<std::string>(&m_RequestInputsAndOutputsDumpDir)->default_value(""), - "If non-empty, the directory where request inputs and outputs should be dumped") - - ("unsupported-operations,u", - po::value<std::string>(&unsupportedOperationsAsString)->default_value(""), - "If non-empty, a comma-separated list of operation indices which the driver will forcibly " - "consider unsupported") - - ("cl-tuned-parameters-file,t", - po::value<std::string>(&m_ClTunedParametersFile)->default_value(""), - "If non-empty, the given file will be used to load/save CL tuned parameters. " - "See also --cl-tuned-parameters-mode") - - ("cl-tuned-parameters-mode,m", - po::value<std::string>(&clTunedParametersModeAsString)->default_value("UseTunedParameters"), - "If 'UseTunedParameters' (the default), will read CL tuned parameters from the file specified by " - "--cl-tuned-parameters-file. " - "If 'UpdateTunedParameters', will also find the optimum parameters when preparing new networks and update " - "the file accordingly."); - - - po::variables_map variablesMap; - try - { - po::store(po::parse_command_line(argc, argv, optionsDesc), variablesMap); - po::notify(variablesMap); - } - catch (const po::error& e) - { - ALOGW("An error occurred attempting to parse program options: %s", e.what()); - } - - if (computeDeviceAsString == "CpuRef") - { - m_ComputeDevice = armnn::Compute::CpuRef; - } - else if (computeDeviceAsString == "GpuAcc") - { - m_ComputeDevice = armnn::Compute::GpuAcc; - } - else if (computeDeviceAsString == "CpuAcc") - { - m_ComputeDevice = armnn::Compute::CpuAcc; - } - else - { - ALOGW("Requested unknown compute device %s. Defaulting to compute id %s", - computeDeviceAsString.c_str(), GetComputeDeviceAsCString(m_ComputeDevice)); - } - - if (!unsupportedOperationsAsString.empty()) - { - std::istringstream argStream(unsupportedOperationsAsString); - - std::string s; - while (!argStream.eof()) - { - std::getline(argStream, s, ','); - try - { - unsigned int operationIdx = std::stoi(s); - m_ForcedUnsupportedOperations.insert(operationIdx); - } - catch (const std::invalid_argument&) - { - ALOGW("Ignoring invalid integer argument in -u/--unsupported-operations value: %s", s.c_str()); - } - } - } - - if (!m_ClTunedParametersFile.empty()) - { - // The mode is only relevant if the file path has been provided - if (clTunedParametersModeAsString == "UseTunedParameters") - { - m_ClTunedParametersMode = armnn::IClTunedParameters::Mode::UseTunedParameters; - } - else if (clTunedParametersModeAsString == "UpdateTunedParameters") - { - m_ClTunedParametersMode = armnn::IClTunedParameters::Mode::UpdateTunedParameters; - } - else - { - ALOGW("Requested unknown cl-tuned-parameters-mode '%s'. Defaulting to UseTunedParameters", - clTunedParametersModeAsString.c_str()); - } - } -} - -ArmnnDriver::ArmnnDriver(DriverOptions options) - : m_Runtime(nullptr, nullptr) - , m_ClTunedParameters(nullptr, nullptr) - , m_Options(std::move(options)) -{ - ALOGV("ArmnnDriver::ArmnnDriver()"); - - armnn::ConfigureLogging(false, m_Options.IsVerboseLoggingEnabled(), armnn::LogSeverity::Trace); - if (m_Options.IsVerboseLoggingEnabled()) - { - SetMinimumLogSeverity(base::VERBOSE); - } - else - { - SetMinimumLogSeverity(base::INFO); - } - - try - { - armnn::IRuntime::CreationOptions options(m_Options.GetComputeDevice()); - options.m_UseCpuRefAsFallback = false; - if (!m_Options.GetClTunedParametersFile().empty()) - { - m_ClTunedParameters = armnn::IClTunedParameters::Create(m_Options.GetClTunedParametersMode()); - try - { - m_ClTunedParameters->Load(m_Options.GetClTunedParametersFile().c_str()); - } - catch (const armnn::Exception& error) - { - // This is only a warning because the file won't exist the first time you are generating it. - ALOGW("ArmnnDriver: Failed to load CL tuned parameters file '%s': %s", - m_Options.GetClTunedParametersFile().c_str(), error.what()); - } - options.m_ClTunedParameters = m_ClTunedParameters.get(); - } - m_Runtime = armnn::IRuntime::Create(options); - } - catch (const armnn::ClRuntimeUnavailableException& error) - { - ALOGE("ArmnnDriver: Failed to setup CL runtime: %s. Device will be unavailable.", error.what()); - } -} - -Return<void> ArmnnDriver::getCapabilities(V1_0::IDevice::getCapabilities_cb cb) -{ - ALOGV("ArmnnDriver::getCapabilities()"); - - V1_0::Capabilities capabilities; - if (m_Runtime) - { - capabilities.float32Performance.execTime = - ParseSystemProperty(g_Float32PerformanceExecTimeName, 1.0f); - - capabilities.float32Performance.powerUsage = - ParseSystemProperty(g_Float32PerformancePowerUsageName, 1.0f); - - capabilities.quantized8Performance.execTime = - ParseSystemProperty(g_Quantized8PerformanceExecTimeName, 1.0f); - - capabilities.quantized8Performance.powerUsage = - ParseSystemProperty(g_Quantized8PerformancePowerUsageName, 1.0f); - - cb(ErrorStatus::NONE, capabilities); - } - else - { - capabilities.float32Performance.execTime = 0; - capabilities.float32Performance.powerUsage = 0; - capabilities.quantized8Performance.execTime = 0; - capabilities.quantized8Performance.powerUsage = 0; - - cb(ErrorStatus::DEVICE_UNAVAILABLE, capabilities); - } - - return Void(); -} - -Return<void> ArmnnDriver::getSupportedOperations(const V1_0::Model& model, V1_0::IDevice::getSupportedOperations_cb cb) -{ - ALOGV("ArmnnDriver::getSupportedOperations()"); - - std::vector<bool> result; - - if (!m_Runtime) - { - cb(ErrorStatus::DEVICE_UNAVAILABLE, result); - return Void(); - } - - // Run general model validation, if this doesn't pass we shouldn't analyse the model anyway - if (!android::nn::validateModel(model)) - { - cb(ErrorStatus::INVALID_ARGUMENT, result); - return Void(); - } - - // Attempt to convert the model to an ArmNN input network (INetwork). - ModelToINetworkConverter modelConverter(m_Runtime->GetDeviceSpec().DefaultComputeDevice, model, - m_Options.GetForcedUnsupportedOperations()); - - if (modelConverter.GetConversionResult() != ConversionResult::Success - && modelConverter.GetConversionResult() != ConversionResult::UnsupportedFeature) - { - cb(ErrorStatus::GENERAL_FAILURE, result); - return Void(); - } - - // Check each operation if it was converted successfully and copy the flags - // into the result (vector<bool>) that we need to return to Android - result.reserve(model.operations.size()); - for (uint32_t operationIdx = 0; operationIdx < model.operations.size(); operationIdx++) - { - bool operationSupported = modelConverter.IsOperationSupported(operationIdx); - result.push_back(operationSupported); - } - - cb(ErrorStatus::NONE, result); - return Void(); -} - -namespace -{ - -void NotifyCallbackAndCheck(const sp<IPreparedModelCallback>& callback, ErrorStatus errorStatus, - const ::android::sp<IPreparedModel>& preparedModelPtr) -{ - Return<void> returned = callback->notify(errorStatus, preparedModelPtr); - // This check is required, if the callback fails and it isn't checked it will bring down the service - if (!returned.isOk()) - { - ALOGE("ArmnnDriver::prepareModel: hidl callback failed to return properly: %s ", - returned.description().c_str()); - } -} - -Return<ErrorStatus> FailPrepareModel(ErrorStatus error, - const std::string& message, - const sp<IPreparedModelCallback>& callback) -{ - ALOGW("ArmnnDriver::prepareModel: %s", message.c_str()); - NotifyCallbackAndCheck(callback, error, nullptr); - return error; -} - -} - -Return<ErrorStatus> ArmnnDriver::prepareModel(const V1_0::Model& model, - const sp<IPreparedModelCallback>& cb) -{ - ALOGV("ArmnnDriver::prepareModel()"); - - if (cb.get() == nullptr) - { - ALOGW("ArmnnDriver::prepareModel: Invalid callback passed to prepareModel"); - return ErrorStatus::INVALID_ARGUMENT; - } - - if (!m_Runtime) - { - return FailPrepareModel(ErrorStatus::DEVICE_UNAVAILABLE, "ArmnnDriver::prepareModel: Device unavailable", cb); - } - - if (!android::nn::validateModel(model)) - { - return FailPrepareModel(ErrorStatus::INVALID_ARGUMENT, - "ArmnnDriver::prepareModel: Invalid model passed as input", cb); - } - - if (m_Options.UseAndroidNnCpuExecutor()) - { - sp<AndroidNnCpuExecutorPreparedModel> preparedModel = new AndroidNnCpuExecutorPreparedModel(model, - m_Options.GetRequestInputsAndOutputsDumpDir()); - if (preparedModel->Initialize()) - { - NotifyCallbackAndCheck(cb, ErrorStatus::NONE, preparedModel); - return ErrorStatus::NONE; - } - else - { - NotifyCallbackAndCheck(cb, ErrorStatus::INVALID_ARGUMENT, preparedModel); - return ErrorStatus::INVALID_ARGUMENT; - } - } - - // Deliberately ignore any unsupported operations requested by the options - - // at this point we're being asked to prepare a model that we've already declared support for - // and the operation indices may be different to those in getSupportedOperations anyway. - std::set<unsigned int> unsupportedOperations; - ModelToINetworkConverter modelConverter(m_Runtime->GetDeviceSpec().DefaultComputeDevice, model, - unsupportedOperations); - - if (modelConverter.GetConversionResult() != ConversionResult::Success) - { - FailPrepareModel(ErrorStatus::GENERAL_FAILURE, "ModelToINetworkConverter failed", cb); - return ErrorStatus::NONE; - } - - // optimize the network - armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr); - try - { - optNet = armnn::Optimize(*modelConverter.GetINetwork(), m_Runtime->GetDeviceSpec()); - } - catch (armnn::Exception& e) - { - std::stringstream message; - message << "armnn::Exception ("<<e.what()<<") caught from optimize."; - FailPrepareModel(ErrorStatus::GENERAL_FAILURE, message.str(), cb); - return ErrorStatus::NONE; - } - - // Check that the optimized network is valid. - if (!optNet) - { - FailPrepareModel(ErrorStatus::GENERAL_FAILURE, - "ArmnnDriver::prepareModel: Invalid optimized network", cb); - return ErrorStatus::NONE; - } - - // Export the optimized network graph to a dot file if an output dump directory - // has been specified in the drivers' arguments. - ExportNetworkGraphToDotFile(*optNet, - m_Options.GetRequestInputsAndOutputsDumpDir(), - model); - - // load it into the runtime - armnn::NetworkId netId = 0; - try - { - if (m_Runtime->LoadNetwork(netId, std::move(optNet)) != armnn::Status::Success) - { - return FailPrepareModel(ErrorStatus::GENERAL_FAILURE, - "ArmnnDriver::prepareModel: Network could not be loaded", cb); - } - } - catch (armnn::Exception& e) - { - std::stringstream message; - message << "armnn::Exception (" << e.what()<< ") caught from LoadNetwork."; - FailPrepareModel(ErrorStatus::GENERAL_FAILURE, message.str(), cb); - return ErrorStatus::NONE; - } - - std::unique_ptr<ArmnnPreparedModel> preparedModel(new ArmnnPreparedModel( - netId, - m_Runtime.get(), - model, - m_Options.GetRequestInputsAndOutputsDumpDir() - )); - - // Run a single 'dummy' inference of the model. This means that CL kernels will get compiled (and tuned if - // this is enabled) before the first 'real' inference which removes the overhead of the first inference. - preparedModel->ExecuteWithDummyInputs(); - - if (m_ClTunedParameters && - m_Options.GetClTunedParametersMode() == armnn::IClTunedParameters::Mode::UpdateTunedParameters) - { - // Now that we've done one inference the CL kernel parameters will have been tuned, so save the updated file. - try - { - m_ClTunedParameters->Save(m_Options.GetClTunedParametersFile().c_str()); - } - catch (const armnn::Exception& error) - { - ALOGE("ArmnnDriver: Failed to save CL tuned parameters file '%s': %s", - m_Options.GetClTunedParametersFile().c_str(), error.what()); - } - } - - NotifyCallbackAndCheck(cb, ErrorStatus::NONE, preparedModel.release()); - - return ErrorStatus::NONE; -} - -Return<DeviceStatus> ArmnnDriver::getStatus() -{ - ALOGV("ArmnnDriver::getStatus()"); - return DeviceStatus::AVAILABLE; -} - -} |