Subject: Add CLTuner support
authorInki Dae <inki.dae@samsung.com>
Tue, 2 Feb 2021 06:46:29 +0000 (15:46 +0900)
committerInki Dae <inki.dae@samsung.com>
Tue, 2 Feb 2021 06:51:16 +0000 (15:51 +0900)
Added CLTuner support ARMNN engine.

The use of CLTuner is valid only in case of GpuAcc request.
There are two behaviors of CLTuner according to CLTuner configuration
like below,
    [cltuner->active is true]
        -> It means that ARMNN backend uses CLTuner API of ARMNN engine.
    [cltuner->active is false]
        -> It means that ARMNN backend skips the use of CLTuner API
           of ARMNN engine.
    [cltuner->update is true]
        -> It means that ARMNN backend requests a tuning file generation
           to ARMNN engine.
    [cltuner->update is false]
        -> It means that ARMNN backend requests a inference to ARMNN engine,
           and ARMNN will use a tuned file for the inference.

Change-Id: Id74aeab532d312f1db7b7f856667a53d07abb329
Signed-off-by: Inki Dae <inki.dae@samsung.com>
src/inference_engine_armnn.cpp
src/inference_engine_armnn_private.h

index 057eedbae5ed9e1863420619d188b729e481ed65..a4e2433eb6cc4061278bd447136740823993adaf 100644 (file)
@@ -22,6 +22,7 @@
 #include <unistd.h>
 #include <time.h>
 #include <queue>
+#include <algorithm>
 
 #include <armnn/ArmNN.hpp>
 #include <armnn/backends/ITensorHandle.hpp>
@@ -35,7 +36,8 @@ namespace ARMNNImpl
 
        InferenceARMNN::InferenceARMNN(void) :
                mNetwork(armnn::INetworkPtr(nullptr, nullptr)),
-               mNetworkIdentifier(-1)
+               mNetworkIdentifier(-1),
+               mCLTuner()
        {
                LOGI("ENTER");
                LOGI("LEAVE");
@@ -55,6 +57,7 @@ namespace ARMNNImpl
                mOutputBindingInfo.clear();
                std::vector<armnn::BindingPointInfo>().swap(mOutputBindingInfo);
 
+               armnn::IRuntime::Destroy(sRuntime);
                sRuntime = nullptr;
        }
 
@@ -115,6 +118,31 @@ namespace ARMNNImpl
                return INFERENCE_ENGINE_ERROR_NONE;
        }
 
+
+       int InferenceARMNN::SetCLTuner(const inference_engine_cltuner *cltuner)
+       {
+               LOGI("ENTER");
+
+               if (cltuner == NULL) {
+                       LOGE("cltuner is NULL.");
+                       return INFERENCE_ENGINE_ERROR_INVALID_PARAMETER;
+               }
+
+               mCLTuner = *cltuner;
+
+               LOGI("CLTuner is %s", mCLTuner.active ? "used" : "not used");
+
+               if (mCLTuner.active) {
+                       LOGI("Update mode is %s", mCLTuner.update ? "enabled" : "disabled");
+                       LOGI("tuning_mode is %d\n", mCLTuner.tuning_mode);
+                       LOGI("A given tuned file path is %s", mCLTuner.file_path.c_str());
+               }
+
+               LOGI("LEAVE");
+
+               return INFERENCE_ENGINE_ERROR_NONE;
+       }
+
        int InferenceARMNN::CreateTfLiteNetwork(std::string model_path)
        {
                LOGI("ENTER");
@@ -250,6 +278,41 @@ namespace ARMNNImpl
 
                armnn::IRuntime::CreationOptions creation_options;
 
+               // The use of CLTuner is valid only in case of GpuAcc request.
+               if (mCLTuner.active && UseGpuAcc()) {
+                       std::string tune_path = model_paths[0] + ".tune";
+
+                       // file_path can be set by user. So if file_path is given then
+                       // user-given path will be passed to a given inference engine.
+                       // On the other hand, if file_path is empty then default
+                       // path - "model file path + .tune" - will be passed to the
+                       // inference engine.
+                       if (!mCLTuner.file_path.empty())
+                               tune_path = mCLTuner.file_path;
+
+                       LOGI("CLTuner tuning file name is %s", tune_path.c_str());
+
+                       // If CLTuner is read only mode then set INFERENCE_ENGINE_CLTUNER_READ
+                       // to TuningLevel.
+                       // Ps. if TuningLevel is INFERENCE_ENGINE_CLTUNER_READ then
+                       // ARMCL will read a tuned file for inference.
+                       if (mCLTuner.update == false) {
+                               LOGI("CLTuner mode is read only.");
+                               mCLTuner.tuning_mode = INFERENCE_ENGINE_CLTUNER_READ;
+                       }
+
+                       creation_options.m_BackendOptions.emplace_back(
+                               armnn::BackendOptions
+                               {
+                                       "GpuAcc",
+                                       {
+                                               {"TuningLevel", static_cast<int>(mCLTuner.tuning_mode)},
+                                               {"TuningFile", tune_path.c_str()}
+                                       }
+                               }
+                       );
+               }
+
                if (sRuntime == nullptr) {
                        sRuntime = armnn::IRuntime::CreateRaw(creation_options);
                        LOGI("Created ARMNN runtime");
@@ -447,6 +510,7 @@ namespace ARMNNImpl
 
                capacity->supported_accel_devices = INFERENCE_TARGET_CPU |
                                                                                        INFERENCE_TARGET_GPU;
+               capacity->cltuner_supported = true;
 
                LOGI("LEAVE");
 
@@ -478,6 +542,12 @@ namespace ARMNNImpl
                return ret;
        }
 
+       bool InferenceARMNN::UseGpuAcc(void)
+       {
+               return (std::find(mAccelType.begin(), mAccelType.end(),
+                                                 armnn::Compute::GpuAcc) != mAccelType.end());
+       }
+
        int InferenceARMNN::Run(
                        std::vector<inference_engine_tensor_buffer> &input_buffers,
                        std::vector<inference_engine_tensor_buffer> &output_buffers)
index 0241a09af2452784dc9773a839ae0c90a013bd56..cf589d352f1492db682abcbf69679e4daed97ce1 100644 (file)
@@ -53,6 +53,8 @@ namespace ARMNNImpl
 
                int SetTargetDevices(int types) override;
 
+               int SetCLTuner(const inference_engine_cltuner *cltuner) final;
+
                int Load(std::vector<std::string> model_paths,
                                 inference_model_format_e model_format) override;
 
@@ -88,6 +90,7 @@ namespace ARMNNImpl
                int CheckTensorBuffers(
                                std::vector<inference_engine_tensor_buffer> &input_buffers,
                                std::vector<inference_engine_tensor_buffer> &output_buffers);
+               bool UseGpuAcc(void);
 
                std::vector<armnn::BackendId> mAccelType;
 
@@ -99,6 +102,7 @@ namespace ARMNNImpl
                std::vector<armnn::BindingPointInfo> mOutputBindingInfo;
                std::vector<std::string> mDesignated_inputs;
                std::vector<std::string> mDesignated_outputs;
+               inference_engine_cltuner mCLTuner;
        };
 
 } /* InferenceEngineImpl */