From e48bdff741568236d3c0747ad3d18a8eba5b36dd Mon Sep 17 00:00:00 2001 From: Matteo Martincigh Date: Mon, 3 Sep 2018 13:50:50 +0100 Subject: IVGCVSW-1806 Refactored Android-NN-Driver, added common "getCapabilities", "getSupportedOperations" and "prepareModel" implementations * Added common base ArmnnDriverImpl class * Added common template implementation of the driver's "getCapabilities", "getSupportedOperations" and "prepareModel" methods * Refactored ArmnnPreparedModel and RequestThread to support HAL v1.1 models * Moved "getStatus" to the common base class, as it is shared by both HAL implementations * Refactored the code where necessary Change-Id: I747334730026d63b4002662523fb93608f67c899 --- 1.0/ArmnnDriver.hpp | 26 ++-- 1.0/ArmnnDriverImpl.cpp | 277 ----------------------------------------- 1.0/ArmnnDriverImpl.hpp | 41 ------ 1.1/ArmnnDriver.hpp | 63 ++++++---- 1.1/ArmnnDriverImpl.cpp | 151 ----------------------- 1.1/ArmnnDriverImpl.hpp | 39 ------ Android.mk | 5 +- ArmnnDevice.cpp | 2 + ArmnnDriverImpl.cpp | 288 +++++++++++++++++++++++++++++++++++++++++++ ArmnnDriverImpl.hpp | 62 ++++++++++ ArmnnPreparedModel.cpp | 49 +++++--- ArmnnPreparedModel.hpp | 21 ++-- ModelToINetworkConverter.cpp | 5 +- ModelToINetworkConverter.hpp | 17 +-- RequestThread.cpp | 32 +++-- RequestThread.hpp | 9 +- Utils.cpp | 44 ------- Utils.hpp | 49 +++++++- 18 files changed, 533 insertions(+), 647 deletions(-) delete mode 100644 1.0/ArmnnDriverImpl.cpp delete mode 100644 1.0/ArmnnDriverImpl.hpp delete mode 100644 1.1/ArmnnDriverImpl.cpp delete mode 100644 1.1/ArmnnDriverImpl.hpp create mode 100644 ArmnnDriverImpl.cpp create mode 100644 ArmnnDriverImpl.hpp diff --git a/1.0/ArmnnDriver.hpp b/1.0/ArmnnDriver.hpp index 83484ca9..18e25968 100644 --- a/1.0/ArmnnDriver.hpp +++ b/1.0/ArmnnDriver.hpp @@ -7,8 +7,8 @@ #include -#include "ArmnnDriverImpl.hpp" #include "ArmnnDevice.hpp" +#include "../ArmnnDriverImpl.hpp" #include @@ -29,36 +29,44 @@ public: public: Return getCapabilities( - ::android::hardware::neuralnetworks::V1_0::IDevice::getCapabilities_cb cb) + ::android::hardware::neuralnetworks::V1_0::IDevice::getCapabilities_cb cb) override { ALOGV("V1_0::ArmnnDriver::getCapabilities()"); - return ArmnnDriverImpl::getCapabilities(m_Runtime, cb); + return armnn_driver::ArmnnDriverImpl::getCapabilities(m_Runtime, + cb); } Return getSupportedOperations( const ::android::hardware::neuralnetworks::V1_0::Model& model, - ::android::hardware::neuralnetworks::V1_0::IDevice::getSupportedOperations_cb cb) + ::android::hardware::neuralnetworks::V1_0::IDevice::getSupportedOperations_cb cb) override { ALOGV("V1_0::ArmnnDriver::getSupportedOperations()"); - return ArmnnDriverImpl::getSupportedOperations(m_Runtime, m_Options, model, cb); + return armnn_driver::ArmnnDriverImpl::getSupportedOperations(m_Runtime, + m_Options, + model, + cb); } Return prepareModel( const ::android::hardware::neuralnetworks::V1_0::Model& model, - const android::sp& cb) + const android::sp& cb) override { ALOGV("V1_0::ArmnnDriver::prepareModel()"); - return ArmnnDriverImpl::prepareModel(m_Runtime, m_ClTunedParameters, m_Options, model, cb); + return armnn_driver::ArmnnDriverImpl::prepareModel(m_Runtime, + m_ClTunedParameters, + m_Options, + model, + cb); } - Return getStatus() + Return getStatus() override { ALOGV("V1_0::ArmnnDriver::getStatus()"); - return ArmnnDriverImpl::getStatus(); + return armnn_driver::ArmnnDriverImpl::getStatus(); } }; diff --git a/1.0/ArmnnDriverImpl.cpp b/1.0/ArmnnDriverImpl.cpp deleted file mode 100644 index 21a4f2e3..00000000 --- a/1.0/ArmnnDriverImpl.cpp +++ /dev/null @@ -1,277 +0,0 @@ -// -// Copyright © 2017 Arm Ltd. All rights reserved. -// See LICENSE file in the project root for full license information. -// - -#include "ArmnnDriverImpl.hpp" -#include "ModelToINetworkConverter.hpp" -#include "ArmnnPreparedModel.hpp" -#include "SystemPropertiesUtils.hpp" - -#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 -#endif - -#include - -using namespace std; -using namespace android; -using namespace android::nn; -using namespace android::hardware; - -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"; - -void NotifyCallbackAndCheck(const sp& callback, - ErrorStatus errorStatus, - const sp& preparedModelPtr) -{ - Return 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("V1_0::ArmnnDriverImpl::prepareModel: hidl callback failed to return properly: %s ", - returned.description().c_str()); - } -} - -Return FailPrepareModel(ErrorStatus error, - const string& message, - const sp& callback) -{ - ALOGW("V1_0::ArmnnDriverImpl::prepareModel: %s", message.c_str()); - NotifyCallbackAndCheck(callback, error, nullptr); - return error; -} - -} // namespace - -namespace armnn_driver -{ -namespace V1_0 -{ - -Return ArmnnDriverImpl::getCapabilities( - const armnn::IRuntimePtr& runtime, - neuralnetworks::V1_0::IDevice::getCapabilities_cb cb) -{ - ALOGV("V1_0::ArmnnDriverImpl::getCapabilities()"); - - neuralnetworks::V1_0::Capabilities capabilities; - if (runtime) - { - capabilities.float32Performance.execTime = - ParseSystemProperty(g_Float32PerformanceExecTimeName, .1f); - - capabilities.float32Performance.powerUsage = - ParseSystemProperty(g_Float32PerformancePowerUsageName, .1f); - - capabilities.quantized8Performance.execTime = - ParseSystemProperty(g_Quantized8PerformanceExecTimeName, .1f); - - capabilities.quantized8Performance.powerUsage = - ParseSystemProperty(g_Quantized8PerformancePowerUsageName, .1f); - - 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 ArmnnDriverImpl::getSupportedOperations( - const armnn::IRuntimePtr& runtime, - const DriverOptions& options, - const neuralnetworks::V1_0::Model& model, - neuralnetworks::V1_0::IDevice::getSupportedOperations_cb cb) -{ - ALOGV("V1_0::ArmnnDriverImpl::getSupportedOperations()"); - - vector result; - - if (!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). - armnn_driver::ModelToINetworkConverter modelConverter(options.GetComputeDevice(), - model, 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) 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(); -} - -Return ArmnnDriverImpl::prepareModel( - const armnn::IRuntimePtr& runtime, - const armnn::IGpuAccTunedParametersPtr& clTunedParameters, - const DriverOptions& options, - const neuralnetworks::V1_0::Model& model, - const sp& cb, - bool float32ToFloat16) -{ - ALOGV("V1_0::ArmnnDriverImpl::prepareModel()"); - - if (cb.get() == nullptr) - { - ALOGW("V1_0::ArmnnDriverImpl::prepareModel: Invalid callback passed to prepareModel"); - return ErrorStatus::INVALID_ARGUMENT; - } - - if (!runtime) - { - return FailPrepareModel(ErrorStatus::DEVICE_UNAVAILABLE, - "V1_0::ArmnnDriverImpl::prepareModel: Device unavailable", cb); - } - - if (!android::nn::validateModel(model)) - { - return FailPrepareModel(ErrorStatus::INVALID_ARGUMENT, - "V1_0::ArmnnDriverImpl::prepareModel: Invalid model passed as input", cb); - } - - // 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. - set unsupportedOperations; - armnn_driver::ModelToINetworkConverter modelConverter(options.GetComputeDevice(), 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); - armnn::OptimizerOptions OptOptions; - OptOptions.m_ReduceFp32ToFp16 = float32ToFloat16; - - try - { - optNet = armnn::Optimize(*modelConverter.GetINetwork(), - {options.GetComputeDevice()}, - runtime->GetDeviceSpec(), - OptOptions); - } - catch (armnn::Exception &e) - { - 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, - "V1_0::ArmnnDriverImpl::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, - options.GetRequestInputsAndOutputsDumpDir(), - model); - - // load it into the runtime - armnn::NetworkId netId = 0; - try - { - if (runtime->LoadNetwork(netId, move(optNet)) != armnn::Status::Success) - { - return FailPrepareModel(ErrorStatus::GENERAL_FAILURE, - "V1_0::ArmnnDriverImpl::prepareModel: Network could not be loaded", cb); - } - } - catch (armnn::Exception& e) - { - stringstream message; - message << "armnn::Exception (" << e.what()<< ") caught from LoadNetwork."; - FailPrepareModel(ErrorStatus::GENERAL_FAILURE, message.str(), cb); - return ErrorStatus::NONE; - } - - unique_ptr preparedModel(new ArmnnPreparedModel( - netId, - runtime.get(), - model, - options.GetRequestInputsAndOutputsDumpDir(), - options.IsGpuProfilingEnabled() - )); - - // 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 (clTunedParameters && - options.GetClTunedParametersMode() == armnn::IGpuAccTunedParameters::Mode::UpdateTunedParameters) - { - // Now that we've done one inference the CL kernel parameters will have been tuned, so save the updated file. - try - { - clTunedParameters->Save(options.GetClTunedParametersFile().c_str()); - } - catch (const armnn::Exception& error) - { - ALOGE("V1_0::ArmnnDriverImpl: Failed to save CL tuned parameters file '%s': %s", - options.GetClTunedParametersFile().c_str(), error.what()); - } - } - - NotifyCallbackAndCheck(cb, ErrorStatus::NONE, preparedModel.release()); - - return ErrorStatus::NONE; -} - -Return ArmnnDriverImpl::getStatus() -{ - ALOGV("V1_0::ArmnnDriverImpl::getStatus()"); - - return DeviceStatus::AVAILABLE; -} - -} // armnn_driver::namespace V1_0 -} // namespace armnn_driver diff --git a/1.0/ArmnnDriverImpl.hpp b/1.0/ArmnnDriverImpl.hpp deleted file mode 100644 index 2628682d..00000000 --- a/1.0/ArmnnDriverImpl.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright © 2017 Arm Ltd. All rights reserved. -// See LICENSE file in the project root for full license information. -// - -#pragma once - -#include - -#include "DriverOptions.hpp" - -#include - -namespace armnn_driver -{ -namespace V1_0 -{ - -class ArmnnDriverImpl -{ -public: - static Return getCapabilities( - const armnn::IRuntimePtr& runtime, - ::android::hardware::neuralnetworks::V1_0::IDevice::getCapabilities_cb cb); - static Return getSupportedOperations( - const armnn::IRuntimePtr& runtime, - const DriverOptions& options, - const ::android::hardware::neuralnetworks::V1_0::Model& model, - ::android::hardware::neuralnetworks::V1_0::IDevice::getSupportedOperations_cb cb); - static Return prepareModel( - const armnn::IRuntimePtr& runtime, - const armnn::IGpuAccTunedParametersPtr& clTunedParameters, - const DriverOptions& options, - const ::android::hardware::neuralnetworks::V1_0::Model& model, - const android::sp& cb, - bool float32ToFloat16 = false); - static Return getStatus(); -}; - -} // namespace armnn_driver::V1_0 -} // namespace armnn_driver diff --git a/1.1/ArmnnDriver.hpp b/1.1/ArmnnDriver.hpp index 6bd8e03c..f55aad4b 100644 --- a/1.1/ArmnnDriver.hpp +++ b/1.1/ArmnnDriver.hpp @@ -8,13 +8,14 @@ #include #include "ArmnnDevice.hpp" -#include "1.0/ArmnnDriverImpl.hpp" -#include "1.1/ArmnnDriverImpl.hpp" +#include "../ArmnnDriverImpl.hpp" #include -namespace armnn_driver { -namespace V1_1 { +namespace armnn_driver +{ +namespace V1_1 +{ class ArmnnDriver : public ArmnnDevice, public ::android::hardware::neuralnetworks::V1_1::IDevice { @@ -28,74 +29,88 @@ public: public: Return getCapabilities( - ::android::hardware::neuralnetworks::V1_0::IDevice::getCapabilities_cb cb) + ::android::hardware::neuralnetworks::V1_0::IDevice::getCapabilities_cb cb) override { ALOGV("V1_1::ArmnnDriver::getCapabilities()"); - return V1_0::ArmnnDriverImpl::getCapabilities(m_Runtime, cb); + return armnn_driver::ArmnnDriverImpl::getCapabilities(m_Runtime, + cb); } Return getSupportedOperations( const ::android::hardware::neuralnetworks::V1_0::Model& model, - ::android::hardware::neuralnetworks::V1_0::IDevice::getSupportedOperations_cb cb) + ::android::hardware::neuralnetworks::V1_0::IDevice::getSupportedOperations_cb cb) override { ALOGV("V1_1::ArmnnDriver::getSupportedOperations()"); - return V1_0::ArmnnDriverImpl::getSupportedOperations(m_Runtime, m_Options, model, cb); + return armnn_driver::ArmnnDriverImpl::getSupportedOperations(m_Runtime, + m_Options, + model, + cb); } Return prepareModel( const ::android::hardware::neuralnetworks::V1_0::Model& model, - const android::sp& cb) + const android::sp& cb) override { ALOGV("V1_1::ArmnnDriver::prepareModel()"); - return V1_0::ArmnnDriverImpl::prepareModel(m_Runtime, m_ClTunedParameters, m_Options, model, cb); + return armnn_driver::ArmnnDriverImpl::prepareModel(m_Runtime, + m_ClTunedParameters, + m_Options, + model, + cb); } Return getCapabilities_1_1( - ::android::hardware::neuralnetworks::V1_1::IDevice::getCapabilities_1_1_cb cb) + ::android::hardware::neuralnetworks::V1_1::IDevice::getCapabilities_1_1_cb cb) override { ALOGV("V1_1::ArmnnDriver::getCapabilities_1_1()"); - return V1_1::ArmnnDriverImpl::getCapabilities_1_1(m_Runtime, cb); + return armnn_driver::ArmnnDriverImpl::getCapabilities(m_Runtime, + cb); } Return getSupportedOperations_1_1( const ::android::hardware::neuralnetworks::V1_1::Model& model, - ::android::hardware::neuralnetworks::V1_1::IDevice::getSupportedOperations_1_1_cb cb) + ::android::hardware::neuralnetworks::V1_1::IDevice::getSupportedOperations_1_1_cb cb) override { ALOGV("V1_1::ArmnnDriver::getSupportedOperations_1_1()"); - return V1_1::ArmnnDriverImpl::getSupportedOperations_1_1(m_Runtime, m_Options, model, cb); + return armnn_driver::ArmnnDriverImpl::getSupportedOperations(m_Runtime, + m_Options, + model, + cb); } Return prepareModel_1_1( const ::android::hardware::neuralnetworks::V1_1::Model& model, ::android::hardware::neuralnetworks::V1_1::ExecutionPreference preference, - const android::sp& cb) + const android::sp& cb) override { - using namespace ::android::hardware::neuralnetworks::V1_0; - ALOGV("V1_1::ArmnnDriver::prepareModel_1_1()"); - if(!(preference == ExecutionPreference::LOW_POWER || - preference == ExecutionPreference::FAST_SINGLE_ANSWER || - preference == ExecutionPreference::SUSTAINED_SPEED)) + if (!(preference == ExecutionPreference::LOW_POWER || + preference == ExecutionPreference::FAST_SINGLE_ANSWER || + preference == ExecutionPreference::SUSTAINED_SPEED)) { - ALOGV("V1_1::ArmnnDriver::prepareModel_1_1(): Invalid execution preference"); + ALOGV("V1_1::ArmnnDriver::prepareModel_1_1: Invalid execution preference"); cb->notify(ErrorStatus::INVALID_ARGUMENT, nullptr); return ErrorStatus::INVALID_ARGUMENT; } - return V1_1::ArmnnDriverImpl::prepareModel_1_1(m_Runtime, m_ClTunedParameters, m_Options, model, cb); + return armnn_driver::ArmnnDriverImpl::prepareModel(m_Runtime, + m_ClTunedParameters, + m_Options, + model, + cb); } - Return getStatus() + Return getStatus() override { ALOGV("V1_1::ArmnnDriver::getStatus()"); - return V1_0::ArmnnDriverImpl::getStatus(); + return armnn_driver::ArmnnDriverImpl::getStatus(); } }; diff --git a/1.1/ArmnnDriverImpl.cpp b/1.1/ArmnnDriverImpl.cpp deleted file mode 100644 index a5e32766..00000000 --- a/1.1/ArmnnDriverImpl.cpp +++ /dev/null @@ -1,151 +0,0 @@ -// -// Copyright © 2017 Arm Ltd. All rights reserved. -// See LICENSE file in the project root for full license information. -// - -#include "ArmnnDriverImpl.hpp" -#include "../1.0/ArmnnDriverImpl.hpp" - -#include - -#include -#include - -#include - -using namespace std; -using namespace android; -using namespace android::nn; -using namespace android::hardware; - -namespace -{ - -void NotifyCallbackAndCheck(const sp& callback, - ErrorStatus errorStatus, - const sp& preparedModelPtr) -{ - Return 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("V1_1::ArmnnDriverImpl::prepareModel_1_1: hidl callback failed to return properly: %s ", - returned.description().c_str()); - } -} - -Return FailPrepareModel(ErrorStatus error, - const string& message, - const sp& callback) -{ - ALOGW("V1_1::ArmnnDriverImpl::prepareModel_1_1: %s", message.c_str()); - NotifyCallbackAndCheck(callback, error, nullptr); - return error; -} - -} // namespace - -namespace armnn_driver -{ -namespace V1_1 -{ - -Return ArmnnDriverImpl::getCapabilities_1_1( - const armnn::IRuntimePtr& runtime, - neuralnetworks::V1_1::IDevice::getCapabilities_1_1_cb cb) -{ - ALOGV("V1_1::ArmnnDriverImpl::getCapabilities_1_1()"); - - neuralnetworks::V1_0::IDevice::getCapabilities_cb cb_1_0 = - [&](ErrorStatus status, const neuralnetworks::V1_0::Capabilities& capabilities) - { - BOOST_ASSERT_MSG(compliantWithV1_1(capabilities), - "V1_1::ArmnnDriverImpl: V1_0::Capabilities not compliant with V1_1::Capabilities"); - - cb(status, convertToV1_1(capabilities)); - }; - - V1_0::ArmnnDriverImpl::getCapabilities(runtime, cb_1_0); - - return Void(); -} - -Return ArmnnDriverImpl::getSupportedOperations_1_1( - const armnn::IRuntimePtr& runtime, - const DriverOptions& options, - const neuralnetworks::V1_1::Model& model, - neuralnetworks::V1_1::IDevice::getSupportedOperations_1_1_cb cb) -{ - ALOGV("V1_1::ArmnnDriverImpl::getSupportedOperations_1_1()"); - - if(compliantWithV1_0(model)) - { - V1_0::ArmnnDriverImpl::getSupportedOperations(runtime, options, convertToV1_0(model), cb); - } - else - { - std::vector result; - - if (!runtime) - { - ALOGW("V1_1::ArmnnDriverImpl::getSupportedOperations_1_1: Device unavailable"); - cb(ErrorStatus::DEVICE_UNAVAILABLE, result); - return Void(); - } - - if (!android::nn::validateModel(model)) - { - ALOGW("V1_1::ArmnnDriverImpl::getSupportedOperations_1_1: Invalid model passed as input"); - cb(ErrorStatus::INVALID_ARGUMENT, result); - return Void(); - } - - result.assign(model.operations.size(), false); - cb(ErrorStatus::NONE, result); - } - - return Void(); -} - -Return ArmnnDriverImpl::prepareModel_1_1( - const armnn::IRuntimePtr& runtime, - const armnn::IGpuAccTunedParametersPtr& clTunedParameters, - const DriverOptions& options, - const neuralnetworks::V1_1::Model& model, - const sp& cb) -{ - ALOGV("V1_1::ArmnnDriverImpl::prepareModel_1_1()"); - - if(compliantWithV1_0(model)) - { - return V1_0::ArmnnDriverImpl::prepareModel(runtime, clTunedParameters, options, convertToV1_0(model), cb, - model.relaxComputationFloat32toFloat16 && options.GetFp16Enabled()); - } - else - { - if (cb.get() == nullptr) - { - ALOGW("V1_1::ArmnnDriverImpl::prepareModel_1_1: Invalid callback passed to prepareModel"); - return ErrorStatus::INVALID_ARGUMENT; - } - - if (!runtime) - { - return FailPrepareModel(ErrorStatus::DEVICE_UNAVAILABLE, - "V1_1::ArmnnDriverImpl::prepareModel_1_1: Device unavailable", cb); - } - - if (!android::nn::validateModel(model)) - { - return FailPrepareModel(ErrorStatus::INVALID_ARGUMENT, - "V1_1::ArmnnDriverImpl::prepareModel_1_1: Invalid model passed as input", cb); - } - - FailPrepareModel(ErrorStatus::GENERAL_FAILURE, - "V1_1::ArmnnDriverImpl::prepareModel_1_1: Unsupported model", cb); - return ErrorStatus::NONE; - } -} - -} // armnn_driver::namespace V1_1 -} // namespace armnn_driver diff --git a/1.1/ArmnnDriverImpl.hpp b/1.1/ArmnnDriverImpl.hpp deleted file mode 100644 index 307d96bf..00000000 --- a/1.1/ArmnnDriverImpl.hpp +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright © 2017 Arm Ltd. All rights reserved. -// See LICENSE file in the project root for full license information. -// - -#pragma once - -#include - -#include "DriverOptions.hpp" - -#include - -namespace armnn_driver -{ -namespace V1_1 -{ - -class ArmnnDriverImpl -{ -public: - static Return getCapabilities_1_1( - const armnn::IRuntimePtr& runtime, - ::android::hardware::neuralnetworks::V1_1::IDevice::getCapabilities_1_1_cb cb); - static Return getSupportedOperations_1_1( - const armnn::IRuntimePtr& runtime, - const DriverOptions& options, - const ::android::hardware::neuralnetworks::V1_1::Model& model, - ::android::hardware::neuralnetworks::V1_1::IDevice::getSupportedOperations_1_1_cb cb); - static Return prepareModel_1_1( - const armnn::IRuntimePtr& runtime, - const armnn::IGpuAccTunedParametersPtr& clTunedParameters, - const DriverOptions& options, - const ::android::hardware::neuralnetworks::V1_1::Model& model, - const android::sp& cb); -}; - -} // namespace armnn_driver::V1_1 -} // namespace armnn_driver diff --git a/Android.mk b/Android.mk index 960a2f6e..38450705 100644 --- a/Android.mk +++ b/Android.mk @@ -47,7 +47,7 @@ LOCAL_CFLAGS+= \ endif # ARMNN_DRIVER_DEBUG == 1 LOCAL_SRC_FILES := \ - 1.0/ArmnnDriverImpl.cpp \ + ArmnnDriverImpl.cpp \ DriverOptions.cpp \ ArmnnDevice.cpp \ ArmnnPreparedModel.cpp \ @@ -118,8 +118,7 @@ LOCAL_CFLAGS+= \ endif # ARMNN_DRIVER_DEBUG == 1 LOCAL_SRC_FILES := \ - 1.0/ArmnnDriverImpl.cpp \ - 1.1/ArmnnDriverImpl.cpp \ + ArmnnDriverImpl.cpp \ DriverOptions.cpp \ ArmnnDevice.cpp \ ArmnnPreparedModel.cpp \ diff --git a/ArmnnDevice.cpp b/ArmnnDevice.cpp index 3e0b0da2..81e8eaca 100644 --- a/ArmnnDevice.cpp +++ b/ArmnnDevice.cpp @@ -3,6 +3,8 @@ // See LICENSE file in the project root for full license information. // +#define LOG_TAG "ArmnnDriver" + #include "ArmnnDevice.hpp" #include diff --git a/ArmnnDriverImpl.cpp b/ArmnnDriverImpl.cpp new file mode 100644 index 00000000..0298f3b7 --- /dev/null +++ b/ArmnnDriverImpl.cpp @@ -0,0 +1,288 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#define LOG_TAG "ArmnnDriver" + +#include "ArmnnDriverImpl.hpp" +#include "ModelToINetworkConverter.hpp" +#include "ArmnnPreparedModel.hpp" +#include "SystemPropertiesUtils.hpp" + +#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 +#endif + +#include + +using namespace std; +using namespace android; +using namespace android::nn; +using namespace android::hardware; + +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"; + +void NotifyCallbackAndCheck(const sp& callback, + ErrorStatus errorStatus, + const sp& preparedModelPtr) +{ + Return 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("ArmnnDriverImpl::prepareModel: hidl callback failed to return properly: %s ", + returned.description().c_str()); + } +} + +Return FailPrepareModel(ErrorStatus error, + const string& message, + const sp& callback) +{ + ALOGW("ArmnnDriverImpl::prepareModel: %s", message.c_str()); + NotifyCallbackAndCheck(callback, error, nullptr); + return error; +} + +} // namespace + +namespace armnn_driver +{ + +template +Return ArmnnDriverImpl::getCapabilities( + const armnn::IRuntimePtr& runtime, + HalGetCapabilities_cb cb) +{ + ALOGV("ArmnnDriverImpl::getCapabilities()"); + + HalCapabilities capabilities; + if (runtime) + { + capabilities.float32Performance.execTime = + ParseSystemProperty(g_Float32PerformanceExecTimeName, .1f); + + capabilities.float32Performance.powerUsage = + ParseSystemProperty(g_Float32PerformancePowerUsageName, .1f); + + capabilities.quantized8Performance.execTime = + ParseSystemProperty(g_Quantized8PerformanceExecTimeName, .1f); + + capabilities.quantized8Performance.powerUsage = + ParseSystemProperty(g_Quantized8PerformancePowerUsageName, .1f); + + 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(); +} + +template +Return ArmnnDriverImpl::getSupportedOperations( + const armnn::IRuntimePtr& runtime, + const DriverOptions& options, + const HalModel& model, + HalGetSupportedOperations_cb cb) +{ + ALOGV("ArmnnDriverImpl::getSupportedOperations()"); + + vector result; + + if (!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(options.GetComputeDevice(), + model, + 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) 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(); +} + +template +Return ArmnnDriverImpl::prepareModel( + const armnn::IRuntimePtr& runtime, + const armnn::IGpuAccTunedParametersPtr& clTunedParameters, + const DriverOptions& options, + const HalModel& model, + const sp& cb, + bool float32ToFloat16) +{ + ALOGV("ArmnnDriverImpl::prepareModel()"); + + if (cb.get() == nullptr) + { + ALOGW("ArmnnDriverImpl::prepareModel: Invalid callback passed to prepareModel"); + return ErrorStatus::INVALID_ARGUMENT; + } + + if (!runtime) + { + return FailPrepareModel(ErrorStatus::DEVICE_UNAVAILABLE, + "ArmnnDriverImpl::prepareModel: Device unavailable", cb); + } + + if (!android::nn::validateModel(model)) + { + return FailPrepareModel(ErrorStatus::INVALID_ARGUMENT, + "ArmnnDriverImpl::prepareModel: Invalid model passed as input", cb); + } + + // 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. + set unsupportedOperations; + ModelToINetworkConverter modelConverter(options.GetComputeDevice(), + model, + unsupportedOperations); + + if (modelConverter.GetConversionResult() != ConversionResult::Success) + { + FailPrepareModel(ErrorStatus::GENERAL_FAILURE, + "ArmnnDriverImpl::prepareModel: ModelToINetworkConverter failed", cb); + return ErrorStatus::NONE; + } + + // Optimize the network + armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr); + armnn::OptimizerOptions OptOptions; + OptOptions.m_ReduceFp32ToFp16 = float32ToFloat16; + + try + { + optNet = armnn::Optimize(*modelConverter.GetINetwork(), + {options.GetComputeDevice()}, + runtime->GetDeviceSpec(), + OptOptions); + } + catch (armnn::Exception &e) + { + stringstream message; + message << "ArmnnDriverImpl::prepareModel: 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, + "ArmnnDriverImpl::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, options.GetRequestInputsAndOutputsDumpDir(), model); + + // Load it into the runtime. + armnn::NetworkId netId = 0; + try + { + if (runtime->LoadNetwork(netId, move(optNet)) != armnn::Status::Success) + { + return FailPrepareModel(ErrorStatus::GENERAL_FAILURE, + "ArmnnDriverImpl::prepareModel: Network could not be loaded", cb); + } + } + catch (armnn::Exception& e) + { + stringstream message; + message << "ArmnnDriverImpl::prepareModel: armnn::Exception (" << e.what()<< ") caught from LoadNetwork."; + FailPrepareModel(ErrorStatus::GENERAL_FAILURE, message.str(), cb); + return ErrorStatus::NONE; + } + + unique_ptr> preparedModel( + new ArmnnPreparedModel( + netId, + runtime.get(), + model, + options.GetRequestInputsAndOutputsDumpDir(), + options.IsGpuProfilingEnabled())); + + // 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 (clTunedParameters && + options.GetClTunedParametersMode() == armnn::IGpuAccTunedParameters::Mode::UpdateTunedParameters) + { + // Now that we've done one inference the CL kernel parameters will have been tuned, so save the updated file. + try + { + clTunedParameters->Save(options.GetClTunedParametersFile().c_str()); + } + catch (const armnn::Exception& error) + { + ALOGE("ArmnnDriverImpl::prepareModel: Failed to save CL tuned parameters file '%s': %s", + options.GetClTunedParametersFile().c_str(), error.what()); + } + } + + NotifyCallbackAndCheck(cb, ErrorStatus::NONE, preparedModel.release()); + + return ErrorStatus::NONE; +} + +template +Return ArmnnDriverImpl::getStatus() +{ + ALOGV("ArmnnDriver::getStatus()"); + + return DeviceStatus::AVAILABLE; +} + +// Class template specializations +template class ArmnnDriverImpl; + +#ifdef ARMNN_ANDROID_NN_V1_1 +template class ArmnnDriverImpl; +#endif + +} // namespace armnn_driver diff --git a/ArmnnDriverImpl.hpp b/ArmnnDriverImpl.hpp new file mode 100644 index 00000000..c0600977 --- /dev/null +++ b/ArmnnDriverImpl.hpp @@ -0,0 +1,62 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#pragma once + +#include + +#include "DriverOptions.hpp" + +#include + +namespace armnn_driver +{ + +struct HalVersion_1_0 +{ + using Model = ::android::hardware::neuralnetworks::V1_0::Model; + using Capabilities = ::android::hardware::neuralnetworks::V1_0::Capabilities; + using getCapabilities_cb = ::android::hardware::neuralnetworks::V1_0::IDevice::getCapabilities_cb; + using getSupportedOperations_cb = ::android::hardware::neuralnetworks::V1_0::IDevice::getSupportedOperations_cb; +}; + +#if defined(ARMNN_ANDROID_NN_V1_1) +struct HalVersion_1_1 +{ + using Model = ::android::hardware::neuralnetworks::V1_1::Model; + using Capabilities = ::android::hardware::neuralnetworks::V1_1::Capabilities; + using getCapabilities_cb = ::android::hardware::neuralnetworks::V1_1::IDevice::getCapabilities_1_1_cb; + using getSupportedOperations_cb = ::android::hardware::neuralnetworks::V1_1::IDevice::getSupportedOperations_1_1_cb; +}; +#endif + +template +class ArmnnDriverImpl +{ +public: + using HalModel = typename HalVersion::Model; + using HalCapabilities = typename HalVersion::Capabilities; + using HalGetCapabilities_cb = typename HalVersion::getCapabilities_cb; + using HalGetSupportedOperations_cb = typename HalVersion::getSupportedOperations_cb; + + static Return getCapabilities( + const armnn::IRuntimePtr& runtime, + HalGetCapabilities_cb cb); + static Return getSupportedOperations( + const armnn::IRuntimePtr& runtime, + const DriverOptions& options, + const HalModel& model, + HalGetSupportedOperations_cb); + static Return prepareModel( + const armnn::IRuntimePtr& runtime, + const armnn::IGpuAccTunedParametersPtr& clTunedParameters, + const DriverOptions& options, + const HalModel& model, + const android::sp& cb, + bool float32ToFloat16 = false); + static Return getStatus(); +}; + +} // namespace armnn_driver diff --git a/ArmnnPreparedModel.cpp b/ArmnnPreparedModel.cpp index d338fdc8..7cbbcbcb 100644 --- a/ArmnnPreparedModel.cpp +++ b/ArmnnPreparedModel.cpp @@ -81,18 +81,20 @@ inline std::string BuildTensorName(const char* tensorNamePrefix, std::size_t ind return tensorNamePrefix + std::to_string(index); } -} +} // anonymous namespace using namespace android::hardware; namespace armnn_driver { -RequestThread ArmnnPreparedModel::m_RequestThread; +template +RequestThread ArmnnPreparedModel::m_RequestThread; +template template -void ArmnnPreparedModel::DumpTensorsIfRequired(char const* tensorNamePrefix, - const TensorBindingCollection& tensorBindings) +void ArmnnPreparedModel::DumpTensorsIfRequired(char const* tensorNamePrefix, + const TensorBindingCollection& tensorBindings) { if (!m_RequestInputsAndOutputsDumpDir.empty()) { @@ -107,11 +109,12 @@ void ArmnnPreparedModel::DumpTensorsIfRequired(char const* tensorNamePrefix, } } -ArmnnPreparedModel::ArmnnPreparedModel(armnn::NetworkId networkId, - armnn::IRuntime* runtime, - const neuralnetworks::V1_0::Model& model, - const std::string& requestInputsAndOutputsDumpDir, - const bool gpuProfilingEnabled) +template +ArmnnPreparedModel::ArmnnPreparedModel(armnn::NetworkId networkId, + armnn::IRuntime* runtime, + const HalModel& model, + const std::string& requestInputsAndOutputsDumpDir, + const bool gpuProfilingEnabled) : m_NetworkId(networkId) , m_Runtime(runtime) , m_Model(model) @@ -123,7 +126,8 @@ ArmnnPreparedModel::ArmnnPreparedModel(armnn::NetworkId networkId, m_Runtime->GetProfiler(m_NetworkId)->EnableProfiling(m_GpuProfilingEnabled); } -ArmnnPreparedModel::~ArmnnPreparedModel() +template +ArmnnPreparedModel::~ArmnnPreparedModel() { // Get a hold of the profiler used by this model. std::shared_ptr profiler = m_Runtime->GetProfiler(m_NetworkId); @@ -135,8 +139,9 @@ ArmnnPreparedModel::~ArmnnPreparedModel() DumpJsonProfilingIfRequired(m_GpuProfilingEnabled, m_RequestInputsAndOutputsDumpDir, m_NetworkId, profiler.get()); } -Return ArmnnPreparedModel::execute(const Request& request, - const ::android::sp& callback) +template +Return ArmnnPreparedModel::execute(const Request& request, + const ::android::sp& callback) { ALOGV("ArmnnPreparedModel::execute(): %s", GetModelSummary(m_Model).c_str()); m_RequestCount++; @@ -220,10 +225,12 @@ Return ArmnnPreparedModel::execute(const Request& request, return ErrorStatus::NONE; // successfully queued } -void ArmnnPreparedModel::ExecuteGraph(std::shared_ptr>& pMemPools, - std::shared_ptr& pInputTensors, - std::shared_ptr& pOutputTensors, - const ::android::sp& callback) +template +void ArmnnPreparedModel::ExecuteGraph( + std::shared_ptr>& pMemPools, + std::shared_ptr& pInputTensors, + std::shared_ptr& pOutputTensors, + const ::android::sp& callback) { ALOGV("ArmnnPreparedModel::ExecuteGraph(...)"); @@ -254,7 +261,8 @@ void ArmnnPreparedModel::ExecuteGraph(std::shared_ptr +void ArmnnPreparedModel::ExecuteWithDummyInputs() { std::vector> storage; armnn::InputTensors inputTensors; @@ -287,4 +295,11 @@ void ArmnnPreparedModel::ExecuteWithDummyInputs() } } +// Class template specializations +template class ArmnnPreparedModel; + +#ifdef ARMNN_ANDROID_NN_V1_1 // Using ::android::hardware::neuralnetworks::V1_1. +template class ArmnnPreparedModel; +#endif + } // namespace armnn_driver diff --git a/ArmnnPreparedModel.hpp b/ArmnnPreparedModel.hpp index a700e54d..86c6f5cf 100644 --- a/ArmnnPreparedModel.hpp +++ b/ArmnnPreparedModel.hpp @@ -8,6 +8,7 @@ #include "RequestThread.hpp" #include "ArmnnDriver.hpp" +#include "ArmnnDriverImpl.hpp" #include #include @@ -18,12 +19,15 @@ namespace armnn_driver { +template class ArmnnPreparedModel : public IPreparedModel { public: + using HalModel = typename HalVersion::Model; + ArmnnPreparedModel(armnn::NetworkId networkId, armnn::IRuntime* runtime, - const ::android::hardware::neuralnetworks::V1_0::Model& model, + const HalModel& model, const std::string& requestInputsAndOutputsDumpDir, const bool gpuProfilingEnabled); @@ -42,19 +46,18 @@ public: void ExecuteWithDummyInputs(); private: - template void DumpTensorsIfRequired(char const* tensorNamePrefix, const TensorBindingCollection& tensorBindings); - armnn::NetworkId m_NetworkId; - armnn::IRuntime* m_Runtime; - ::android::hardware::neuralnetworks::V1_0::Model m_Model; + armnn::NetworkId m_NetworkId; + armnn::IRuntime* m_Runtime; + HalModel m_Model; // There must be a single RequestThread for all ArmnnPreparedModel objects to ensure serial execution of workloads // It is specific to this class, so it is declared as static here - static RequestThread m_RequestThread; - uint32_t m_RequestCount; - const std::string& m_RequestInputsAndOutputsDumpDir; - const bool m_GpuProfilingEnabled; + static RequestThread m_RequestThread; + uint32_t m_RequestCount; + const std::string& m_RequestInputsAndOutputsDumpDir; + const bool m_GpuProfilingEnabled; }; } diff --git a/ModelToINetworkConverter.cpp b/ModelToINetworkConverter.cpp index 461a8cdb..6db32a05 100644 --- a/ModelToINetworkConverter.cpp +++ b/ModelToINetworkConverter.cpp @@ -484,6 +484,7 @@ template void ModelToINetworkConverter::Convert() { using HalModel = typename HalVersion::Model; + ALOGV("ModelToINetworkConverter::Convert(): %s", GetModelSummary(m_Model).c_str()); // map the memory pool into shared pointers @@ -2658,8 +2659,8 @@ bool ModelToINetworkConverter::IsOperationSupported(uint32_t operati template class ModelToINetworkConverter; -#if defined(ARMNN_ANDROID_NN_V1_1) +#if defined(ARMNN_ANDROID_NN_V1_1) // Using ::android::hardware::neuralnetworks::V1_1. template class ModelToINetworkConverter; #endif -} // armnn_driver \ No newline at end of file +} // armnn_driver diff --git a/ModelToINetworkConverter.hpp b/ModelToINetworkConverter.hpp index 040bec6b..c28ebdcd 100644 --- a/ModelToINetworkConverter.hpp +++ b/ModelToINetworkConverter.hpp @@ -6,6 +6,7 @@ #pragma once #include "ArmnnDriver.hpp" +#include "ArmnnDriverImpl.hpp" #include #include @@ -33,18 +34,6 @@ enum class ConversionResult UnsupportedFeature }; -struct HalVersion_1_0 -{ - using Model = ::android::hardware::neuralnetworks::V1_0::Model; -}; - -#if defined(ARMNN_ANDROID_NN_V1_1) -struct HalVersion_1_1 -{ - using Model = ::android::hardware::neuralnetworks::V1_1::Model; -}; -#endif - // A helper performing the conversion from an AndroidNN driver Model representation, // to an armnn::INetwork object template @@ -54,8 +43,8 @@ public: using HalModel = typename HalVersion::Model; ModelToINetworkConverter(armnn::Compute compute, - const HalModel& model, - const std::set& forcedUnsupportedOperations); + const HalModel& model, + const std::set& forcedUnsupportedOperations); ConversionResult GetConversionResult() const { return m_ConversionResult; } diff --git a/RequestThread.cpp b/RequestThread.cpp index abaee90c..8e44d8d2 100644 --- a/RequestThread.cpp +++ b/RequestThread.cpp @@ -17,13 +17,15 @@ using namespace android; namespace armnn_driver { -RequestThread::RequestThread() +template +RequestThread::RequestThread() { ALOGV("RequestThread::RequestThread()"); m_Thread = std::make_unique(&RequestThread::Process, this); } -RequestThread::~RequestThread() +template +RequestThread::~RequestThread() { ALOGV("RequestThread::~RequestThread()"); @@ -48,11 +50,12 @@ RequestThread::~RequestThread() catch (const std::exception&) { } // Swallow any exception. } -void RequestThread::PostMsg(ArmnnPreparedModel* model, - std::shared_ptr>& memPools, - std::shared_ptr& inputTensors, - std::shared_ptr& outputTensors, - const ::android::sp& callback) +template +void RequestThread::PostMsg(ArmnnPreparedModel* model, + std::shared_ptr>& memPools, + std::shared_ptr& inputTensors, + std::shared_ptr& outputTensors, + const ::android::sp& callback) { ALOGV("RequestThread::PostMsg(...)"); auto data = std::make_shared(model, @@ -64,7 +67,8 @@ void RequestThread::PostMsg(ArmnnPreparedModel* model, PostMsg(pMsg); } -void RequestThread::PostMsg(std::shared_ptr& pMsg) +template +void RequestThread::PostMsg(std::shared_ptr& pMsg) { ALOGV("RequestThread::PostMsg(pMsg)"); // Add a message to the queue and notify the request thread @@ -73,7 +77,8 @@ void RequestThread::PostMsg(std::shared_ptr& pMsg) m_Cv.notify_one(); } -void RequestThread::Process() +template +void RequestThread::Process() { ALOGV("RequestThread::Process()"); while (true) @@ -98,7 +103,7 @@ void RequestThread::Process() { ALOGV("RequestThread::Process() - request"); // invoke the asynchronous execution method - ArmnnPreparedModel* model = pMsg->data->m_Model; + ArmnnPreparedModel* model = pMsg->data->m_Model; model->ExecuteGraph(pMsg->data->m_MemPools, pMsg->data->m_InputTensors, pMsg->data->m_OutputTensors, @@ -126,5 +131,12 @@ void RequestThread::Process() } } +// Class template specializations +template class RequestThread; + +#ifdef ARMNN_ANDROID_NN_V1_1 // Using ::android::hardware::neuralnetworks::V1_1. +template class RequestThread; +#endif + } // namespace armnn_driver diff --git a/RequestThread.hpp b/RequestThread.hpp index 2448dbec..41ad213b 100644 --- a/RequestThread.hpp +++ b/RequestThread.hpp @@ -11,6 +11,7 @@ #include #include "ArmnnDriver.hpp" +#include "ArmnnDriverImpl.hpp" #include #include @@ -18,8 +19,10 @@ namespace armnn_driver { +template class ArmnnPreparedModel; +template class RequestThread { public: @@ -35,7 +38,7 @@ public: /// @param[in] inputTensors pointer to the input tensors for the request /// @param[in] outputTensors pointer to the output tensors for the request /// @param[in] callback the android notification callback - void PostMsg(armnn_driver::ArmnnPreparedModel* model, + void PostMsg(armnn_driver::ArmnnPreparedModel* model, std::shared_ptr>& memPools, std::shared_ptr& inputTensors, std::shared_ptr& outputTensors, @@ -48,7 +51,7 @@ private: /// storage for a prepared model and args for the asyncExecute call struct AsyncExecuteData { - AsyncExecuteData(ArmnnPreparedModel* model, + AsyncExecuteData(ArmnnPreparedModel* model, std::shared_ptr>& memPools, std::shared_ptr& inputTensors, std::shared_ptr& outputTensors, @@ -61,7 +64,7 @@ private: { } - armnn_driver::ArmnnPreparedModel* m_Model; + armnn_driver::ArmnnPreparedModel* m_Model; std::shared_ptr> m_MemPools; std::shared_ptr m_InputTensors; std::shared_ptr m_OutputTensors; diff --git a/Utils.cpp b/Utils.cpp index 726e130f..79384e01 100644 --- a/Utils.cpp +++ b/Utils.cpp @@ -9,13 +9,8 @@ #include -#include -#include - #include #include -#include -#include using namespace android; using namespace android::hardware; @@ -289,43 +284,4 @@ void DumpJsonProfilingIfRequired(bool gpuProfilingEnabled, profiler->Print(fileStream); } -void ExportNetworkGraphToDotFile(const armnn::IOptimizedNetwork& optimizedNetwork, - const std::string& dumpDir, - const neuralnetworks::V1_0::Model& model) -{ - // The dump directory must exist in advance. - if (dumpDir.empty()) - { - return; - } - - // Get the memory address of the model and convert it to a hex string (of at least a '0' character). - size_t modelAddress = uintptr_t(&model); - std::stringstream ss; - ss << std::uppercase << std::hex << std::setfill('0') << std::setw(1) << modelAddress; - std::string modelAddressHexString = ss.str(); - - // Set the name of the output .dot file. - const std::string fileName = boost::str(boost::format("%1%/networkgraph_%2%.dot") - % dumpDir - % modelAddressHexString); - - ALOGV("Exporting the optimized network graph to file: %s", fileName.c_str()); - - // Write the network graph to a dot file. - std::ofstream fileStream; - fileStream.open(fileName, std::ofstream::out | std::ofstream::trunc); - - if (!fileStream.good()) - { - ALOGW("Could not open file %s for writing", fileName.c_str()); - return; - } - - if (optimizedNetwork.SerializeToDot(fileStream) != armnn::Status::Success) - { - ALOGW("An error occurred when writing to file %s", fileName.c_str()); - } -} - } // namespace armnn_driver diff --git a/Utils.hpp b/Utils.hpp index 5d9f7003..ac90a9ab 100644 --- a/Utils.hpp +++ b/Utils.hpp @@ -12,8 +12,13 @@ #include #include +#include +#include + #include #include +#include +#include namespace armnn_driver { @@ -44,8 +49,8 @@ armnn::TensorInfo GetTensorInfoForOperand(const Operand& operand); std::string GetOperandSummary(const Operand& operand); -template -std::string GetModelSummary(const Model& model) +template +std::string GetModelSummary(const HalModel& model) { std::stringstream result; @@ -86,8 +91,44 @@ void DumpJsonProfilingIfRequired(bool gpuProfilingEnabled, armnn::NetworkId networkId, const armnn::IProfiler* profiler); +template void ExportNetworkGraphToDotFile(const armnn::IOptimizedNetwork& optimizedNetwork, const std::string& dumpDir, - const ::android::hardware::neuralnetworks::V1_0::Model& model); + const HalModel& model) +{ + // The dump directory must exist in advance. + if (dumpDir.empty()) + { + return; + } + + // Get the memory address of the model and convert it to a hex string (of at least a '0' character). + size_t modelAddress = uintptr_t(&model); + std::stringstream ss; + ss << std::uppercase << std::hex << std::setfill('0') << std::setw(1) << modelAddress; + std::string modelAddressHexString = ss.str(); + + // Set the name of the output .dot file. + const std::string fileName = boost::str(boost::format("%1%/networkgraph_%2%.dot") + % dumpDir + % modelAddressHexString); + + ALOGV("Exporting the optimized network graph to file: %s", fileName.c_str()); + + // Write the network graph to a dot file. + std::ofstream fileStream; + fileStream.open(fileName, std::ofstream::out | std::ofstream::trunc); -} \ No newline at end of file + if (!fileStream.good()) + { + ALOGW("Could not open file %s for writing", fileName.c_str()); + return; + } + + if (optimizedNetwork.SerializeToDot(fileStream) != armnn::Status::Success) + { + ALOGW("An error occurred when writing to file %s", fileName.c_str()); + } +} + +} -- cgit v1.2.1