Use input tensor buffers coming from upper layer
authorInki Dae <inki.dae@samsung.com>
Thu, 13 Feb 2020 07:32:33 +0000 (16:32 +0900)
committerInki Dae <inki.dae@samsung.com>
Thu, 13 Feb 2020 07:32:33 +0000 (16:32 +0900)
This patch makes armnn backend to use input tensor buffers
coming from Inference layer for the inference.

As for this, it addes new several callbacks, and drops unnecessary ones.

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

index 605bb1f97ffd78df42c3175d46f43e9e9ff1d768..0d2e9c5e267960e5727cbc912163a3a40ff751a6 100644 (file)
@@ -39,17 +39,6 @@ enum {
     ARMNN_DATA_TYPE_MAX
 };
 
-static const char *ARMNN_DATA_TYPE_STR[ARMNN_DATA_TYPE_MAX] =
-{
-    "",
-    "float32",
-    "int32",
-    "uint8",
-    "int64",
-    "string",
-    "bool"
-};
-
 InferenceARMNN::InferenceARMNN(void) :
     mRuntime(nullptr, &armnn::IRuntime::Destroy),
     mNetwork(armnn::INetworkPtr(nullptr, nullptr))
@@ -63,6 +52,26 @@ InferenceARMNN::~InferenceARMNN()
     ;
 }
 
+inference_tensor_data_type_e InferenceARMNN::ConvertDataType(armnn::DataType type)
+{
+    inference_tensor_data_type_e data_type;
+
+    switch ((int)type) {
+    case ARMNN_DATA_TYPE_FLOAT32:
+        data_type = TENSOR_DATA_TYPE_FLOAT32;
+        break;
+    case ARMNN_DATA_TYPE_UINT8:
+        data_type = TENSOR_DATA_TYPE_UINT8;
+        break;
+    default:
+        LOGE("Invalid Input tensor type so it will use float32 in default.");
+        data_type = TENSOR_DATA_TYPE_FLOAT32;
+        break;
+    }
+
+    return data_type;
+}
+
 void *InferenceARMNN::AllocateTensorBuffer(armnn::DataType type, int tensor_size)
 {
     void *tensor_buffer = nullptr;
@@ -102,38 +111,6 @@ void InferenceARMNN::ReleaseTensorBuffer(armnn::DataType type, void *tensor_buff
     };
 }
 
-int InferenceARMNN::SetInputTensorParamNode(std::string node)
-{
-    LOGI("ENTER");
-
-    mInputLayerName = node;
-    LOGI("Input Layer Name = %s", node.c_str());
-
-    LOGI("LEAVE");
-    return INFERENCE_ENGINE_ERROR_NONE;
-}
-
-int InferenceARMNN::SetOutputTensorParamNodes(std::vector<std::string> nodes)
-{
-    LOGI("ENTER");
-
-    mOutputLayerName = nodes;
-    std::string output_layer_names;
-
-    LOGI("Output Layer Names");
-    for (int i = 0; i < (int)nodes.size(); i++) {
-        std::string node_name = nodes[i];
-
-        output_layer_names.append(node_name.c_str());
-        output_layer_names.append(" ");
-        LOGI("%s", output_layer_names.c_str());
-    }
-
-    LOGI("LEAVE");
-
-    return INFERENCE_ENGINE_ERROR_NONE;
-}
-
 int InferenceARMNN::SetTargetDevices(int types)
 {
     LOGI("ENTER");
@@ -240,65 +217,79 @@ int InferenceARMNN::Load(std::vector<std::string> model_paths, inference_model_f
     return ret;
 }
 
-// Create input tensor buffer and set the input layer type.
-int InferenceARMNN::CreateInputLayerPassage()
+int InferenceARMNN::GetInputTensorBuffers(std::vector<inference_engine_tensor_buffer> &buffers)
 {
     LOGI("ENTER");
 
-    armnn::BindingPointInfo bindingInfo = inputBindingInfo.front();
-    armnn::TensorInfo tensorInfo = bindingInfo.second;
+    // Upper layer will allocate input tensor buffer/buffers. 
 
-    LOGI("Input Tensor Info");
-    armnn::TensorShape shape = tensorInfo.GetShape();
-    int tensor_size = 1;
-    for (int i = 0; i < (int)tensorInfo.GetNumDimensions(); i++) {
-        tensor_size *= shape[i];
-    }
+    LOGI("LEAVE");
 
-    LOGI("Input Tensor size = %d", tensor_size);
-    LOGI("Input Tensor type = %d(%s)", (int)tensorInfo.GetDataType(),
-        ARMNN_DATA_TYPE_STR[(int)tensorInfo.GetDataType()]);
+    return INFERENCE_ENGINE_ERROR_NONE;
+}
 
-    void *inputData = AllocateTensorBuffer((armnn::DataType)tensorInfo.GetDataType(),
-            tensor_size);
-    if (inputData == nullptr) {
-        LOGE("Fail to allocate tensor buffer.");
-        return INFERENCE_ENGINE_ERROR_OUT_OF_MEMORY;
-    }
+int InferenceARMNN::GetInputLayerProperty(inference_engine_layer_property &property)
+{
+    LOGI("ENTER");
 
-    mInputLayerType = (int)tensorInfo.GetDataType();
+    // TODO. Need to check if model file loading is done.
 
-    armnn::Tensor input_tensor(tensorInfo, inputData);
+    std::vector<armnn::BindingPointInfo>::iterator iter;
+    for (iter = inputBindingInfo.begin(); iter != inputBindingInfo.end(); iter++) {
+        inference_engine_tensor_info out_info;
+        armnn::BindingPointInfo bindingInfo = *iter;
+        armnn::TensorInfo tensorInfo = bindingInfo.second;
+        armnn::TensorShape shape = tensorInfo.GetShape();
+        size_t tensor_size = 1;
 
-    mInputTensor.clear();
-    mInputTensor.push_back(input_tensor);
+        for (int i = 0; i < (int)tensorInfo.GetNumDimensions(); i++) {
+            out_info.shape.push_back(shape[i]);
+            tensor_size *= shape[i];
+        }
+
+        out_info.data_type = ConvertDataType((armnn::DataType)tensorInfo.GetDataType());
+        out_info.size = tensor_size;
+        property.tensor_infos.push_back(out_info);
+    }
 
     LOGI("LEAVE");
 
     return INFERENCE_ENGINE_ERROR_NONE;
 }
 
-int InferenceARMNN::GetInputLayerAttrType()
+int InferenceARMNN::GetOutputLayerProperty(inference_engine_layer_property &property)
 {
     LOGI("ENTER");
 
-    LOGI("LEAVE");
+    // TODO. Need to check if model file loading is done.
 
-    return mInputLayerType;
-}
+    std::vector<armnn::BindingPointInfo>::iterator iter;
+    for (iter = outputBindingInfo.begin(); iter != outputBindingInfo.end(); iter++) {
+        inference_engine_tensor_info out_info;
+        armnn::BindingPointInfo bindingInfo = *iter;
+        armnn::TensorInfo tensorInfo = bindingInfo.second;
+        armnn::TensorShape shape = tensorInfo.GetShape();
+        size_t tensor_size = 1;
 
-void * InferenceARMNN::GetInputDataPtr()
-{
-    LOGI("ENTER");
+        for (int i = 0; i < (int)tensorInfo.GetNumDimensions(); i++) {
+            out_info.shape.push_back(shape[i]);
+            tensor_size *= shape[i];
+        }
+
+        out_info.data_type = ConvertDataType((armnn::DataType)tensorInfo.GetDataType());
+        out_info.size = tensor_size;
+        property.tensor_infos.push_back(out_info);
+    }
 
     LOGI("LEAVE");
 
-    // TODO. std::move
-    return (void *)mInputTensor.front().GetMemoryArea();
+    return INFERENCE_ENGINE_ERROR_NONE;
 }
 
 int InferenceARMNN::GetBackendCapacity(inference_engine_capacity *capacity)
 {
+    LOGI("ENTER");
+
     if (capacity == NULL) {
         LOGE("Bad pointer.");
         return INFERENCE_ENGINE_ERROR_INVALID_PARAMETER;
@@ -307,96 +298,59 @@ int InferenceARMNN::GetBackendCapacity(inference_engine_capacity *capacity)
     capacity->supported_accel_devices = INFERENCE_TARGET_CPU |
                                         INFERENCE_TARGET_GPU;
 
-    return INFERENCE_ENGINE_ERROR_NONE;
-}
-
-int InferenceARMNN::SetInputDataBuffer(tensor_t data)
-{
-    LOGI("ENTER");
-
-    // data contains only tensor shape information such as NCHW ro NHWC,
-    // and front end of ARMNN backend, inference-engine-interface, doesn't
-    // provide tensor buffer.
-
-    std::vector<int> tensor = data.dimInfo.front();
-
-    if (tensor.empty()) {
-        LOGE("Tensor data is null");
-        return INFERENCE_ENGINE_ERROR_NONE;
-    }
-
-    LOGI("ch(%d), height(%d), wight(%d)", (int)tensor[1], (int)tensor[2], (int)tensor[3]);
-
-    int tensor_size = 1;
-    for (int i = 0; i < (int)tensor.size(); i++) {
-        tensor_size *= (int)tensor[i];
-    }
-
-    LOGI("Input Tensor size : %d", tensor_size);
-
     LOGI("LEAVE");
 
     return INFERENCE_ENGINE_ERROR_NONE;
 }
 
-int InferenceARMNN::Run()
+int InferenceARMNN::Run(std::vector<inference_engine_tensor_buffer> &input_buffers)
 {
     LOGI("ENTER");
 
-    // TODO. check tensor info.
+    armnn::BindingPointInfo outBindingInfo = outputBindingInfo.front();
+    armnn::TensorInfo outputTensorInfo = outBindingInfo.second;
+    armnn::TensorShape shape = outputTensorInfo.GetShape();
 
-    armnn::BindingPointInfo bindingInfo = outputBindingInfo.front();
-    armnn::TensorInfo tensorInfo = bindingInfo.second;
-    armnn::TensorShape shape = tensorInfo.GetShape();
+    // input
+    armnn::BindingPointInfo inBindingInfo = inputBindingInfo.front();
+    armnn::TensorInfo inputTensorInfo = inBindingInfo.second;
 
     int tensor_size = 1;
-    for (int i = 0; i < (int)tensorInfo.GetNumDimensions(); i++) {
+    for (int i = 0; i < (int)outputTensorInfo.GetNumDimensions(); i++) {
         tensor_size *= shape[i];
     }
 
     LOGI("Output Tensor size = %d", tensor_size);
 
-    void *outputData = AllocateTensorBuffer((armnn::DataType)tensorInfo.GetDataType(),
+    // TODO. consider mutiple input and output.
+
+    void *outputData = AllocateTensorBuffer((armnn::DataType)outputTensorInfo.GetDataType(),
         tensor_size);
     if (outputData == nullptr) {
         LOGE("Fail to allocate tensor buffer.");
         return INFERENCE_ENGINE_ERROR_OUT_OF_MEMORY;
     }
 
-    armnn::Tensor output_tensor(tensorInfo, outputData);
+    armnn::Tensor output_tensor(outputTensorInfo, outputData);
+    armnn::Tensor input_tensor(inputTensorInfo, input_buffers.front().buffer);
 
     mOutputTensor.clear();
     mOutputTensor.push_back(output_tensor);
 
-    // TODO. consider mutiple input and output.
+    std::vector<armnn::Tensor> InputTensors;
+    InputTensors.push_back(input_tensor);
+
     armnn::InputTensors input_tensors;
     armnn::OutputTensors output_tensors;
 
-    input_tensors.push_back({inputBindingInfo[0].first, mInputTensor.front()});
+    input_tensors.push_back({inputBindingInfo[0].first, InputTensors.front()});
     output_tensors.push_back({outputBindingInfo[0].first, mOutputTensor.front()});
 
     armnn::Status ret = mRuntime->EnqueueWorkload(mNetworkIdentifier,
-        input_tensors, output_tensors);
+                                                  input_tensors, output_tensors);
     if (ret == armnn::Status::Failure)
         return INFERENCE_ENGINE_ERROR_INVALID_OPERATION;
 
-    // release all input tensor buffers because they aren't used anymore.
-    std::vector<armnn::Tensor>::iterator iter;
-    for (iter = mInputTensor.begin(); iter != mInputTensor.end(); iter++) {
-        armnn::Tensor inputTensor = *iter;
-        ReleaseTensorBuffer((armnn::DataType)inputTensor.GetDataType(),
-            inputTensor.GetMemoryArea());
-    }
-
-    LOGI("LEAVE");
-
-    return INFERENCE_ENGINE_ERROR_NONE;
-}
-
-int InferenceARMNN::Run(std::vector<float> tensor)
-{
-    LOGI("ENTER");
-
     LOGI("LEAVE");
 
     return INFERENCE_ENGINE_ERROR_NONE;
index fae068f4498a568187b81a5233642a7f4f4ee53c..48911dd45d8432573334af05e2fd2c410b0e52e5 100644 (file)
@@ -47,36 +47,27 @@ public:
     InferenceARMNN();
     ~InferenceARMNN();
 
-    // InputTensor
-    int SetInputTensorParamNode(std::string node = "input") override;
-
-    // Output Tensor Params
-    int SetOutputTensorParamNodes(std::vector<std::string> nodes) override;
-
     int SetTargetDevices(int types) override;
 
     int Load(std::vector<std::string> model_paths, inference_model_format_e model_format) override;
 
-    int CreateInputLayerPassage() override;
+    int GetInputTensorBuffers(std::vector<inference_engine_tensor_buffer> &buffers) override;
 
-    int GetInputLayerAttrType() override;
+    int GetInputLayerProperty(inference_engine_layer_property &property) override;
 
-    void * GetInputDataPtr() override;
+    int GetOutputLayerProperty(inference_engine_layer_property &property) override;
 
     int GetBackendCapacity(inference_engine_capacity *capacity) override;
 
-    int SetInputDataBuffer(tensor_t data) override;
-
-    int Run() override;
+    int Run(std::vector<inference_engine_tensor_buffer> &input_buffers) override;
 
-    int Run(std::vector<float> tensor) override;
-
-    int GetInferenceResult(tensor_t& results);
+    int GetInferenceResult(tensor_t& results) override;
 
 private:
     int CreateTfLiteNetwork(std::string model_path);
     int CreateNetwork(std::string model_path);
     void *AllocateTensorBuffer(armnn::DataType type, int tensor_size);
+    inference_tensor_data_type_e ConvertDataType(armnn::DataType type);
     void ReleaseTensorBuffer(armnn::DataType type, void *tensor_buffer);
 
     std::vector<armnn::BackendId> mAccelType;
@@ -89,12 +80,6 @@ private:
     std::vector<armnn::BindingPointInfo> inputBindingInfo;
     std::vector<armnn::BindingPointInfo> outputBindingInfo;
 
-    std::string mInputLayerName;
-    int mInputLayerType;
-
-    std::vector<std::string> mOutputLayerName;
-
-    std::vector<armnn::Tensor> mInputTensor;
     std::vector<armnn::Tensor> mOutputTensor;
 };