From e3c07dd78fdd4418fee1412356aa8d254db62faa Mon Sep 17 00:00:00 2001 From: =?utf8?q?=EB=B0=95=EC=84=B8=ED=9D=AC/=EB=8F=99=EC=9E=91=EC=A0=9C?= =?utf8?q?=EC=96=B4Lab=28SR=29/Principal=20Engineer/=EC=82=BC=EC=84=B1?= =?utf8?q?=EC=A0=84=EC=9E=90?= Date: Mon, 26 Mar 2018 13:39:36 +0900 Subject: [PATCH] Add experiment code for Convolution with ACL (#186) * 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 | 1 + experiments/convacl/CMakeLists.txt | 26 ++++ experiments/convacl/src/nnapi_acl_conv.cc | 214 ++++++++++++++++++++++++++++++ 3 files changed, 241 insertions(+) create mode 100644 experiments/convacl/CMakeLists.txt create mode 100644 experiments/convacl/src/nnapi_acl_conv.cc diff --git a/experiments/CMakeLists.txt b/experiments/CMakeLists.txt index 546fe2f..fbf09f1 100644 --- a/experiments/CMakeLists.txt +++ b/experiments/CMakeLists.txt @@ -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 index 0000000..2ec0820 --- /dev/null +++ b/experiments/convacl/CMakeLists.txt @@ -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 index 0000000..3c85faf --- /dev/null +++ b/experiments/convacl/src/nnapi_acl_conv.cc @@ -0,0 +1,214 @@ +#include +#include +#include +#include +#include +#include +#include +// ACL Headers +#include +#include +#include +#include + +// +// 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; +} -- 2.7.4