Add experiment code for Convolution with ACL (#186)
author박세희/동작제어Lab(SR)/Principal Engineer/삼성전자 <saehie.park@samsung.com>
Mon, 26 Mar 2018 04:39:36 +0000 (13:39 +0900)
committerGitHub Enterprise <noreply-CODE@samsung.com>
Mon, 26 Mar 2018 04:39:36 +0000 (13:39 +0900)
* Add experiment code for Convolution with ACL

This will add experimental code to work on Convolution with ACL

* add todo using  env var

experiments/CMakeLists.txt
experiments/convacl/CMakeLists.txt [new file with mode: 0644]
experiments/convacl/src/nnapi_acl_conv.cc [new file with mode: 0644]

index 546fe2f..fbf09f1 100644 (file)
@@ -1,3 +1,4 @@
 if(${TARGET_ARCH_BASE} STREQUAL "arm")
   add_subdirectory(bindacl)
+  add_subdirectory(convacl)
 endif()
diff --git a/experiments/convacl/CMakeLists.txt b/experiments/convacl/CMakeLists.txt
new file mode 100644 (file)
index 0000000..2ec0820
--- /dev/null
@@ -0,0 +1,26 @@
+file(GLOB_RECURSE NNAPI_CONVACL_SRCS "src/*.cc")
+
+# TODO: fix nnapi.h location
+set(NNAPI_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/tools/nnapi_bindings/include)
+
+# TODO: fix acl location
+set(ACL_DIR ${CMAKE_SOURCE_DIR}/externals/acl)
+
+# These are not included in arm_compute libraries so add here
+set(ACL_GRAPH_UTILS_SRCS ${ACL_DIR}/utils/GraphUtils.cpp
+                         ${ACL_DIR}/utils/Utils.cpp)
+
+set(ACL_INCLUDES ${ACL_DIR}
+                 ${ACL_DIR}/include)
+set(ACL_LIBS arm_compute_graph arm_compute arm_compute_core)
+
+link_directories(${CMAKE_INSTALL_PREFIX}/lib)
+
+add_library(exp_convacl SHARED ${NNAPI_CONVACL_SRCS}
+                               ${ACL_GRAPH_UTILS_SRCS})
+target_include_directories(exp_convacl PUBLIC ${NNAPI_INCLUDE_DIR}
+                                              ${ACL_INCLUDES})
+target_link_libraries(exp_convacl ${ACL_LIBS})
+
+# we need the library name to be 'neuralnetworks' and this will do the trick
+set_target_properties(exp_convacl PROPERTIES OUTPUT_NAME neuralnetworks)
diff --git a/experiments/convacl/src/nnapi_acl_conv.cc b/experiments/convacl/src/nnapi_acl_conv.cc
new file mode 100644 (file)
index 0000000..3c85faf
--- /dev/null
@@ -0,0 +1,214 @@
+#include <nnapi.h>
+#include <stdexcept>
+#include <iostream>
+#include <string>
+#include <map>
+#include <cassert>
+#include <boost/format.hpp>
+// ACL Headers
+#include <arm_compute/graph/Graph.h>
+#include <arm_compute/graph/Nodes.h>
+#include <utils/GraphUtils.h>
+#include <utils/Utils.h>
+
+//
+// Asynchronous Event
+//
+struct ANeuralNetworksEvent
+{
+};
+
+ResultCode ANeuralNetworksEvent_wait(ANeuralNetworksEvent* event)
+{
+  return ANEURALNETWORKS_NO_ERROR;
+}
+
+ResultCode ANeuralNetworksEvent_free(ANeuralNetworksEvent* event)
+{
+  delete event;
+  return ANEURALNETWORKS_NO_ERROR;
+}
+
+//
+// Memory
+//
+struct ANeuralNetworksMemory
+{
+  // 1st approach - Store all the data inside ANeuralNetworksMemory object
+  // 2nd approach - Store metadata only, and defer data loading as much as possible
+};
+
+ResultCode ANeuralNetworksMemory_createFromFd(size_t size, int protect, int fd, size_t offset, ANeuralNetworksMemory** memory)
+{
+  *memory = new ANeuralNetworksMemory;
+  return ANEURALNETWORKS_NO_ERROR;
+}
+
+ResultCode ANeuralNetworksMemory_free(ANeuralNetworksMemory* memory)
+{
+  delete memory;
+  return ANEURALNETWORKS_NO_ERROR;
+}
+
+//
+// Model
+//
+struct ANeuralNetworksModel
+{
+  // ANeuralNetworksModel should be a factory for Graph IR (a.k.a ISA Frontend)
+  // TODO Record # of operands
+  uint32_t numOperands;
+
+  ANeuralNetworksModel() : numOperands(0)
+  {
+    // DO NOTHING
+  }
+};
+
+ResultCode ANeuralNetworksModel_create(ANeuralNetworksModel** model)
+{
+  *model = new ANeuralNetworksModel;
+  return ANEURALNETWORKS_NO_ERROR;
+}
+
+ResultCode ANeuralNetworksModel_free(ANeuralNetworksModel* model)
+{
+  delete model;
+  return ANEURALNETWORKS_NO_ERROR;
+}
+
+ResultCode ANeuralNetworksModel_addOperand(ANeuralNetworksModel* model, const ANeuralNetworksOperandType *type)
+{
+  model->numOperands += 1;
+  return ANEURALNETWORKS_NO_ERROR;
+}
+
+ResultCode ANeuralNetworksModel_setOperandValue(ANeuralNetworksModel* model, int32_t index, const void* buffer, size_t length)
+{
+  return ANEURALNETWORKS_NO_ERROR;
+}
+
+ResultCode ANeuralNetworksModel_setOperandValueFromMemory(ANeuralNetworksModel* model, int32_t index, const ANeuralNetworksMemory* memory, size_t offset, size_t length)
+{
+  return ANEURALNETWORKS_NO_ERROR;
+}
+
+ResultCode ANeuralNetworksModel_addOperation(ANeuralNetworksModel* model, ANeuralNetworksOperationType type, uint32_t inputCount, const uint32_t* inputs, uint32_t outputCount, const uint32_t* outputs)
+{
+  return ANEURALNETWORKS_NO_ERROR;
+}
+
+ResultCode ANeuralNetworksModel_identifyInputsAndOutputs(ANeuralNetworksModel* model, uint32_t inputCount, const uint32_t* inputs, uint32_t outputCount, const uint32_t* outputs)
+{
+  return ANEURALNETWORKS_NO_ERROR;
+}
+
+ResultCode ANeuralNetworksModel_finish(ANeuralNetworksModel* model)
+{
+  return ANEURALNETWORKS_NO_ERROR;
+}
+
+//
+// Compilation
+//
+struct ANeuralNetworksCompilation
+{
+  // ANeuralNetworksCompilation should hold a compiled IR
+};
+
+ResultCode ANeuralNetworksCompilation_create(ANeuralNetworksModel* model, ANeuralNetworksCompilation** compilation)
+{
+  *compilation = new ANeuralNetworksCompilation;
+  return ANEURALNETWORKS_NO_ERROR;
+}
+
+ResultCode ANeuralNetworksCompilation_finish(ANeuralNetworksCompilation* compilation)
+{
+  return ANEURALNETWORKS_NO_ERROR;
+}
+
+//
+// Execution
+//
+struct ANeuralNetworksExecution
+{
+  // ANeuralNetworksExecution corresponds to NPU::Interp::Session
+
+  arm_compute::graph::Graph graph;
+};
+
+ResultCode ANeuralNetworksExecution_create(ANeuralNetworksCompilation* compilation, ANeuralNetworksExecution** execution)
+{
+  std::cout << __FUNCTION__ << " +++" << std::endl;
+  *execution = new ANeuralNetworksExecution;
+
+  using arm_compute::DataType;
+  using arm_compute::graph::Tensor;
+  using arm_compute::graph::TargetHint;
+  using arm_compute::graph::Graph;
+  using arm_compute::TensorInfo;
+  using arm_compute::TensorShape;
+
+  ANeuralNetworksExecution* execlocal = *execution;
+  arm_compute::graph::Graph& graph = execlocal->graph;
+
+  TargetHint target_hint;
+  std::string image;
+  std::string label;
+  std::string data_path;
+  std::string weight_path;
+  std::string bias_path;
+  constexpr float mean_r = 1.0f; // Mean value to subtract from red channel
+  constexpr float mean_g = 1.0f; // Mean value to subtract from green channel
+  constexpr float mean_b = 1.0f; // Mean value to subtract from blue channel
+
+  // 0 = NEON, 1 = OpenCL
+  // arm_compute::graph_utils can't be used with 'using'
+  // TODO: set NEON/OpenCL hint by Environment variable
+  target_hint = arm_compute::graph_utils::set_target_hint(1);
+
+  graph << target_hint
+        << Tensor(TensorInfo(TensorShape(3U, 3U, 1U, 1U), 1, DataType::F32),
+                  arm_compute::graph_utils::get_input_accessor(image, mean_r, mean_g, mean_b))
+        << arm_compute::graph::ConvolutionLayer(
+              3U, 3U, 1U,
+              arm_compute::graph_utils::get_weights_accessor(data_path, weight_path),
+              arm_compute::graph_utils::get_weights_accessor(data_path, bias_path),
+              arm_compute::PadStrideInfo(1, 1, 1, 1))
+        << Tensor(arm_compute::graph_utils::get_output_accessor(label, 1));
+        ;
+
+  std::cout << __FUNCTION__ << " ---" << std::endl;
+  return ANEURALNETWORKS_NO_ERROR;
+}
+
+// ANeuralNetworksExecution_setInput and ANeuralNetworksExecution_setOutput specify HOST buffer for input/output
+ResultCode ANeuralNetworksExecution_setInput(ANeuralNetworksExecution* execution, int32_t index, const ANeuralNetworksOperandType* type, const void* buffer, size_t length)
+{
+  return ANEURALNETWORKS_NO_ERROR;
+}
+
+ResultCode ANeuralNetworksExecution_setOutput(ANeuralNetworksExecution* execution, int32_t index, const ANeuralNetworksOperandType* type, const void* buffer, size_t length)
+{
+  return ANEURALNETWORKS_NO_ERROR;
+}
+
+ResultCode ANeuralNetworksExecution_startCompute(ANeuralNetworksExecution* execution, ANeuralNetworksEvent** event)
+{
+  std::cout << __FUNCTION__ << " +++" << std::endl;
+  *event = new ANeuralNetworksEvent;
+
+  // graph.run() fails with segment fail when only target_hint is added.
+  // after fix adding 'Tensor' we may call graph.run()
+  arm_compute::graph::Graph& graph = execution->graph;
+  graph.run();
+
+  std::cout << __FUNCTION__ << " ---" << std::endl;
+  return ANEURALNETWORKS_NO_ERROR;
+}
+
+ResultCode ANeuralNetworksExecution_free(ANeuralNetworksExecution* execution)
+{
+  delete execution;
+  return ANEURALNETWORKS_NO_ERROR;
+}