From 836b27bd73d62795e82d0ce666d728c94c216067 Mon Sep 17 00:00:00 2001 From: Derek Lamberti Date: Wed, 20 Nov 2019 10:51:57 +0000 Subject: IVGCVSW-4157 Pass custom options directly to backends Change-Id: I98cfb913dbd00cb94bdb5dbe82753ca147f7f671 Signed-off-by: Derek Lamberti --- src/armnn/test/RuntimeTests.cpp | 51 +++++++++- src/backends/cl/ClBackendContext.cpp | 186 +++++++++++++++++++++++++++++++++-- src/backends/cl/ClBackendContext.hpp | 4 + src/backends/cl/ClContextControl.cpp | 43 ++------ src/backends/cl/ClContextControl.hpp | 9 +- 5 files changed, 244 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/armnn/test/RuntimeTests.cpp b/src/armnn/test/RuntimeTests.cpp index 4fd847a577..642f334575 100644 --- a/src/armnn/test/RuntimeTests.cpp +++ b/src/armnn/test/RuntimeTests.cpp @@ -288,6 +288,55 @@ BOOST_AUTO_TEST_CASE(IVGCVSW_1929_QuantizedSoftmaxIssue) BOOST_TEST(!optNet); } +BOOST_AUTO_TEST_CASE(RuntimeBackendOptions) +{ + using namespace armnn; + + IRuntime::CreationOptions creationOptions; + auto& backendOptions = creationOptions.m_BackendOptions; + + + // Define Options on explicit construction + BackendOptions options1("FakeBackend1", + { + {"Option1", 1.3f}, + {"Option2", true} + }); + + // Add an option after construction + options1.AddOption({"Option3", "some_value"}); + + // Add the options to CreationOptions struct + backendOptions.push_back(options1); + + // Add more Options via inplace explicit construction + backendOptions.emplace_back( + BackendOptions{"FakeBackend1", + {{"Option4", 42}} + }); + + + // First group + BOOST_TEST(backendOptions[0].GetBackendId().Get() == "FakeBackend1"); + BOOST_TEST(backendOptions[0].GetOption(0).GetName() == "Option1"); + BOOST_TEST(backendOptions[0].GetOption(0).GetValue().IsFloat() == true); + BOOST_TEST(backendOptions[0].GetOption(0).GetValue().AsFloat() == 1.3f); + + BOOST_TEST(backendOptions[0].GetOption(1).GetName() == "Option2"); + BOOST_TEST(backendOptions[0].GetOption(1).GetValue().IsBool() == true); + BOOST_TEST(backendOptions[0].GetOption(1).GetValue().AsBool() == true); + + BOOST_TEST(backendOptions[0].GetOption(2).GetName() == "Option3"); + BOOST_TEST(backendOptions[0].GetOption(2).GetValue().IsString() == true); + BOOST_TEST(backendOptions[0].GetOption(2).GetValue().AsString() == "some_value"); + + // Second group + BOOST_TEST(backendOptions[1].GetBackendId().Get() == "FakeBackend1"); + BOOST_TEST(backendOptions[1].GetOption(0).GetName() == "Option4"); + BOOST_TEST(backendOptions[1].GetOption(0).GetValue().IsInt() == true); + BOOST_TEST(backendOptions[1].GetOption(0).GetValue().AsInt() == 42); +} + BOOST_AUTO_TEST_CASE(ProfilingDisable) { using namespace armnn; @@ -635,7 +684,7 @@ BOOST_AUTO_TEST_CASE(ProfilingEnableCpuRef) LabelsAndEventClasses::TYPE_GUID, readableData, offset); - + bufferManager.MarkRead(readableBuffer); // Creates structures for input & output. diff --git a/src/backends/cl/ClBackendContext.cpp b/src/backends/cl/ClBackendContext.cpp index a82391cce5..b435c29323 100644 --- a/src/backends/cl/ClBackendContext.cpp +++ b/src/backends/cl/ClBackendContext.cpp @@ -4,23 +4,25 @@ // #include "ClBackendContext.hpp" +#include "ClContextControl.hpp" #include -#include "ClContextControl.hpp" - #include #include #include +#include + +#include namespace armnn { struct ClBackendContext::ClContextControlWrapper { - ClContextControlWrapper(IGpuAccTunedParameters* clTunedParameters, + ClContextControlWrapper(arm_compute::CLTuner* tuner, bool profilingEnabled) - : m_ClContextControl(clTunedParameters, profilingEnabled) + : m_ClContextControl(tuner, profilingEnabled) {} bool Sync() @@ -56,13 +58,172 @@ struct ClBackendContext::ClContextControlWrapper ClContextControl m_ClContextControl; }; +std::string LowerString(std::string value) +{ + std::transform(value.begin(), value.end(), value.begin(), + [](unsigned char c){ return std::tolower(c); }); + + return value; +} + +enum class TuningLevel +{ + None, + Rapid, + Normal, + Exhaustive +}; + + +TuningLevel ParseTuningLevel(const BackendOptions::Var& value, TuningLevel defaultValue) +{ + if (value.IsInt()) + { + int v = value.IsInt(); + if (v > static_cast(TuningLevel::Exhaustive) || + v < static_cast(TuningLevel::None)) + { + ARMNN_LOG(warning) << "Invalid GpuAcc tuning level ("<< v << ") selected. " + "Using default(" << static_cast(defaultValue) << ")"; + } else + { + return static_cast(v); + } + } + return defaultValue; +} + +bool ParseBoolean(const BackendOptions::Var& value, bool defaultValue) +{ + if (value.IsBool()) + { + return value.AsBool(); + } + + return defaultValue; +} + +std::string ParseFile(const BackendOptions::Var& value, std::string defaultValue) +{ + if (value.IsString()) + { + return value.AsString(); + } + return defaultValue; +} + +template +void ParseOptions(const std::vector& options, BackendId backend, F f) +{ + for (auto optionsGroup : options) + { + if (optionsGroup.GetBackendId() == backend) + { + for (size_t i=0; i < optionsGroup.GetOptionCount(); i++) + { + const BackendOptions::BackendOption option = optionsGroup.GetOption(i); + f(option.GetName(), option.GetValue()); + } + } + } +} ClBackendContext::ClBackendContext(const IRuntime::CreationOptions& options) : IBackendContext(options) - , m_ClContextControlWrapper( - std::make_unique(options.m_GpuAccTunedParameters.get(), - options.m_EnableGpuProfiling)) { + bool kernelProfiling = options.m_EnableGpuProfiling; + const TuningLevel defaultTuningLevel = TuningLevel::None; + auto tuningLevel = defaultTuningLevel; + m_TuningFile = ""; + + + arm_compute::CLTuner* tuner = nullptr; + if (m_TuningFile.empty() == false) + { + bool useLegacyTunerAPI = options.m_GpuAccTunedParameters.get() != nullptr; + if (useLegacyTunerAPI) + { + auto clTunerParams = boost::polymorphic_downcast( + options.m_GpuAccTunedParameters.get()); + auto clTuner = &clTunerParams->m_Tuner; + + if (clTuner) + { + auto ConvertTuningLevel = [](IGpuAccTunedParameters::TuningLevel level) + { + switch(level) + { + case IGpuAccTunedParameters::TuningLevel::Rapid: + return arm_compute::CLTunerMode::RAPID; + case IGpuAccTunedParameters::TuningLevel::Normal: + return arm_compute::CLTunerMode::NORMAL; + case IGpuAccTunedParameters::TuningLevel::Exhaustive: + return arm_compute::CLTunerMode::EXHAUSTIVE; + default: + { + BOOST_ASSERT_MSG(false, "Tuning level not recognised."); + return arm_compute::CLTunerMode::NORMAL; + } + } + }; + + clTuner->set_tuner_mode(ConvertTuningLevel(clTunerParams->m_TuningLevel)); + clTuner->set_tune_new_kernels( + clTunerParams->m_Mode == armnn::IGpuAccTunedParameters::Mode::UpdateTunedParameters); + } + } + else //New backend options API + { + ParseOptions(options.m_BackendOptions, "GpuAcc", [&](std::string name, const BackendOptions::Var& value) + { + if (name == "KernelProfilingEnabled") + { + kernelProfiling |= ParseBoolean(value, false); + } else if (name == "TuningFile") + { + m_TuningFile = ParseFile(value, ""); + } else if (name == "TuningLevel") + { + tuningLevel = ParseTuningLevel(value, defaultTuningLevel); + } + }); + + // Create the tuner, in tuning mode initially. + m_Tuner = std::make_unique(true); + + switch (tuningLevel) + { + case TuningLevel::Rapid: + m_Tuner->set_tuner_mode(arm_compute::CLTunerMode::RAPID); + break; + case TuningLevel::Normal: + m_Tuner->set_tuner_mode(arm_compute::CLTunerMode::NORMAL); + break; + case TuningLevel::Exhaustive: + m_Tuner->set_tuner_mode(arm_compute::CLTunerMode::EXHAUSTIVE); + break; + case TuningLevel::None: + default: + m_Tuner->set_tune_new_kernels(false); // Turn of tuning. Set to "use" only mode. + break; + } + + try + { + m_Tuner->load_from_file(m_TuningFile.c_str()); + } catch (const std::exception& e) + { + ARMNN_LOG(warning) << "Could not load GpuAcc tuner data file."; + } + + tuner = m_Tuner.get(); + } + } + + m_ClContextControlWrapper = std::make_unique( + tuner, + kernelProfiling + ); } bool ClBackendContext::BeforeLoadNetwork(NetworkId) @@ -103,6 +264,17 @@ bool ClBackendContext::AfterUnloadNetwork(NetworkId networkId) ClBackendContext::~ClBackendContext() { + if (m_Tuner && !m_TuningFile.empty()) + { + try + { + m_Tuner->save_to_file(m_TuningFile.c_str()); + } + catch(const std::exception& e) + { + ARMNN_LOG(warning) << "Could not save GpuAcc tuner data to file " << m_TuningFile; + } + } } } // namespace armnn \ No newline at end of file diff --git a/src/backends/cl/ClBackendContext.hpp b/src/backends/cl/ClBackendContext.hpp index 8d4960214f..bcac0d245e 100644 --- a/src/backends/cl/ClBackendContext.hpp +++ b/src/backends/cl/ClBackendContext.hpp @@ -8,6 +8,8 @@ #include #include +#include + namespace armnn { @@ -31,6 +33,8 @@ private: std::unordered_set m_NetworkIds; + std::unique_ptr m_Tuner; + std::string m_TuningFile; }; } // namespace armnn \ No newline at end of file diff --git a/src/backends/cl/ClContextControl.cpp b/src/backends/cl/ClContextControl.cpp index cf5ae64c78..72c8e9fe45 100644 --- a/src/backends/cl/ClContextControl.cpp +++ b/src/backends/cl/ClContextControl.cpp @@ -27,9 +27,9 @@ class Device; namespace armnn { -ClContextControl::ClContextControl(IGpuAccTunedParameters* clTunedParameters, +ClContextControl::ClContextControl(arm_compute::CLTuner *tuner, bool profilingEnabled) - : m_clTunedParameters(boost::polymorphic_downcast(clTunedParameters)) + : m_Tuner(tuner) , m_ProfilingEnabled(profilingEnabled) { // Ignore m_ProfilingEnabled if unused to avoid compiling problems when ArmCompute is disabled. @@ -97,7 +97,7 @@ void ClContextControl::UnloadOpenClRuntime() DoLoadOpenClRuntime(false); } -void ClContextControl::DoLoadOpenClRuntime(bool useTunedParameters) +void ClContextControl::DoLoadOpenClRuntime(bool updateTunedParameters) { cl::Device device = cl::Device::getDefault(); cl::Context context; @@ -133,8 +133,8 @@ void ClContextControl::DoLoadOpenClRuntime(bool useTunedParameters) // NOTE: In this specific case profiling has to be enabled on the command queue // in order for the CLTuner to work. - bool profilingNeededForClTuner = useTunedParameters && m_clTunedParameters && - m_clTunedParameters->m_Mode == IGpuAccTunedParameters::Mode::UpdateTunedParameters; + bool profilingNeededForClTuner = updateTunedParameters && m_Tuner && + m_Tuner->tune_new_kernels(); if (m_ProfilingEnabled || profilingNeededForClTuner) { @@ -156,34 +156,7 @@ void ClContextControl::DoLoadOpenClRuntime(bool useTunedParameters) // Note the first argument (path to cl source code) will be ignored as they should be embedded in the armcompute. arm_compute::CLKernelLibrary::get().init(".", context, device); - - arm_compute::ICLTuner* tuner = nullptr; - if (useTunedParameters && m_clTunedParameters) - { - tuner = &m_clTunedParameters->m_Tuner; - auto clTuner = boost::polymorphic_downcast(tuner); - - auto ConvertTuningLevel = [](IGpuAccTunedParameters::TuningLevel level) - { - switch(level) - { - case IGpuAccTunedParameters::TuningLevel::Rapid: - return arm_compute::CLTunerMode::RAPID; - case IGpuAccTunedParameters::TuningLevel::Normal: - return arm_compute::CLTunerMode::NORMAL; - case IGpuAccTunedParameters::TuningLevel::Exhaustive: - return arm_compute::CLTunerMode::EXHAUSTIVE; - default: - { - BOOST_ASSERT_MSG(false, "Tuning level not recognised."); - return arm_compute::CLTunerMode::NORMAL; - } - } - }; - - clTuner->set_tuner_mode(ConvertTuningLevel(m_clTunedParameters->m_TuningLevel)); - } - arm_compute::CLScheduler::get().init(context, commandQueue, device, tuner); + arm_compute::CLScheduler::get().init(context, commandQueue, device, m_Tuner); } void ClContextControl::ClearClCache() @@ -225,7 +198,7 @@ void ClTunedParameters::Load(const char* filename) catch (const std::exception& e) { throw armnn::Exception(std::string("Failed to load tuned parameters file '") + filename + "': " + - e.what()); + e.what()); } } @@ -238,7 +211,7 @@ void ClTunedParameters::Save(const char* filename) const catch (const std::exception& e) { throw armnn::Exception(std::string("Failed to save tuned parameters file to '") + filename + "': " + - e.what()); + e.what()); } } diff --git a/src/backends/cl/ClContextControl.hpp b/src/backends/cl/ClContextControl.hpp index 8a5abf7bb2..fd27ced1f9 100644 --- a/src/backends/cl/ClContextControl.hpp +++ b/src/backends/cl/ClContextControl.hpp @@ -11,15 +11,12 @@ namespace armnn { -class IGpuAccTunedParameters; -class ClTunedParameters; - // ARM Compute OpenCL context control. class ClContextControl { public: - ClContextControl(IGpuAccTunedParameters* clTunedParameters = nullptr, + ClContextControl(arm_compute::CLTuner* = nullptr, bool profilingEnabled = false); virtual ~ClContextControl(); @@ -35,9 +32,9 @@ public: private: - void DoLoadOpenClRuntime(bool useTunedParameters); + void DoLoadOpenClRuntime(bool updateTunedParameters); - ClTunedParameters* m_clTunedParameters; + arm_compute::CLTuner* m_Tuner; bool m_ProfilingEnabled; }; -- cgit v1.2.1