From: 오형석/On-Device Lab(SR)/Staff Engineer/삼성전자 Date: Tue, 26 Mar 2019 11:20:15 +0000 (+0900) Subject: Enable external IO memory set validation test (#4860) X-Git-Tag: accepted/tizen/unified/20190430.113441~108 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7387f4f04ddb748aa35c31c2783e6f94d511ecfc;p=platform%2Fcore%2Fml%2Fnnfw.git Enable external IO memory set validation test (#4860) Implement NNAPI to set input and output using external memory Signed-off-by: Hyeongseok Oh --- diff --git a/runtimes/neurun/frontend/nnapi/execution.cc b/runtimes/neurun/frontend/nnapi/execution.cc index d7f9f7b..b00a873 100644 --- a/runtimes/neurun/frontend/nnapi/execution.cc +++ b/runtimes/neurun/frontend/nnapi/execution.cc @@ -20,6 +20,7 @@ #include "wrapper/compilation.h" #include "wrapper/execution.h" +#include "wrapper/memory.h" #include "wrapper/event.h" #include "wrapper/NNAPIConvert.h" #include "util/logging.h" @@ -239,11 +240,10 @@ int ANeuralNetworksExecution_startCompute(ANeuralNetworksExecution *execution, void ANeuralNetworksExecution_free(ANeuralNetworksExecution *execution) { delete execution; } -int ANeuralNetworksExecution_setInputFromMemory(ANeuralNetworksExecution *execution, - int32_t /* index */, - const ANeuralNetworksOperandType * /* type */, - const ANeuralNetworksMemory *memory, - size_t /* offset */, size_t /* length */) +int ANeuralNetworksExecution_setInputFromMemory(ANeuralNetworksExecution *execution, int32_t index, + const ANeuralNetworksOperandType *type, + const ANeuralNetworksMemory *memory, size_t offset, + size_t length) { if ((execution == nullptr) || (memory == nullptr)) { @@ -252,16 +252,74 @@ int ANeuralNetworksExecution_setInputFromMemory(ANeuralNetworksExecution *execut return ANEURALNETWORKS_UNEXPECTED_NULL; } - // NYI - VERBOSE(NNAPI::Execution) << "setInputFromMemory: Cannot handle input from memory yet"; - return ANEURALNETWORKS_BAD_STATE; + if (length == 0) + { + VERBOSE(NNAPI::Execution) << "setInputFromMemory: Zero length input" << std::endl; + return ANEURALNETWORKS_BAD_DATA; + } + + const auto operand_index = execution->getInputOperandIndex(index); + if (!operand_index.valid()) + { + VERBOSE(NNAPI::Execution) << "setInputFromMemory: Invalid input index" << std::endl; + return ANEURALNETWORKS_BAD_DATA; + } + + if (type != nullptr) + { + if (!execution->compareDataType(type, operand_index)) + { + VERBOSE(NNAPI::Execution) << "setInputFromMemory: Data type mismatch" << std::endl; + return ANEURALNETWORKS_BAD_DATA; + } + + if (!execution->compareShape(type, operand_index)) + { + VERBOSE(NNAPI::Execution) << "setInputFromMemory: Shape mismatch" << std::endl; + return ANEURALNETWORKS_BAD_DATA; + } + + if (NNAPIConvert::calculateSizeFromType(type) != length) + { + VERBOSE(NNAPI::Execution) << "setInputFromMemory: Invalid length" << std::endl; + return ANEURALNETWORKS_BAD_DATA; + } + } + else + { + if (execution->haveUnspecifiedDims(operand_index)) + { + VERBOSE(NNAPI::Execution) << "setInputFromMemory: Unspecified dimension value" << std::endl; + return ANEURALNETWORKS_BAD_DATA; + } + + if (execution->getOperandSize(operand_index) != length) + { + VERBOSE(NNAPI::Execution) << "setInputFromMemory: Invalid length" << std::endl; + return ANEURALNETWORKS_BAD_DATA; + } + } + + if (!memory->vaildAccess(offset, length)) + { + VERBOSE(NNAPI::Execution) << "setInputFromMemory: Invalid memory access" << std::endl; + return ANEURALNETWORKS_BAD_DATA; + } + + if (!execution->setInput(index, type, reinterpret_cast(memory->base() + offset), + length)) + { + VERBOSE(NNAPI::Execution) << "setInputFromMemory: Fail to set input" << std::endl; + return ANEURALNETWORKS_BAD_DATA; + } + + return ANEURALNETWORKS_NO_ERROR; } -int ANeuralNetworksExecution_setOutputFromMemory(ANeuralNetworksExecution *execution, - int32_t /* index */, - const ANeuralNetworksOperandType * /* type */, - const ANeuralNetworksMemory *memory, - size_t /* offset */, size_t /* length */) +int ANeuralNetworksExecution_setOutputFromMemory(ANeuralNetworksExecution *execution, int32_t index, + const ANeuralNetworksOperandType *type, + const ANeuralNetworksMemory *memory, size_t offset, + size_t length) { if ((execution == nullptr) || (memory == nullptr)) { @@ -270,7 +328,65 @@ int ANeuralNetworksExecution_setOutputFromMemory(ANeuralNetworksExecution *execu return ANEURALNETWORKS_UNEXPECTED_NULL; } - // NYI - VERBOSE(NNAPI::Execution) << "setOutputFromMemory: Cannot handle output from memory yet"; - return ANEURALNETWORKS_BAD_STATE; + if (length == 0) + { + VERBOSE(NNAPI::Execution) << "setOutputFromMemory: Zero length input" << std::endl; + return ANEURALNETWORKS_BAD_DATA; + } + + const auto operand_index = execution->getOutputOperandIndex(index); + if (!operand_index.valid()) + { + VERBOSE(NNAPI::Execution) << "setOutputFromMemory: Invalid output index" << std::endl; + return ANEURALNETWORKS_BAD_DATA; + } + + if (type != nullptr) + { + if (!execution->compareDataType(type, operand_index)) + { + VERBOSE(NNAPI::Execution) << "setOutputFromMemory: Data type mismatch" << std::endl; + return ANEURALNETWORKS_BAD_DATA; + } + + if (!execution->compareShape(type, operand_index)) + { + VERBOSE(NNAPI::Execution) << "setOutputFromMemory: Shape mismatch" << std::endl; + return ANEURALNETWORKS_BAD_DATA; + } + + if (NNAPIConvert::calculateSizeFromType(type) != length) + { + VERBOSE(NNAPI::Execution) << "setOutputFromMemory: Invalid length" << std::endl; + return ANEURALNETWORKS_BAD_DATA; + } + } + else + { + if (execution->haveUnspecifiedDims(operand_index)) + { + VERBOSE(NNAPI::Execution) << "setOutputFromMemory: Unspecified dimension value" << std::endl; + return ANEURALNETWORKS_BAD_DATA; + } + + if (execution->getOperandSize(operand_index) != length) + { + VERBOSE(NNAPI::Execution) << "setOutputFromMemory: Invalid length" << std::endl; + return ANEURALNETWORKS_BAD_DATA; + } + } + + if (!memory->vaildAccess(offset, length)) + { + VERBOSE(NNAPI::Execution) << "setOutputFromMemory: Invalid memory access" << std::endl; + return ANEURALNETWORKS_BAD_DATA; + } + + if (!execution->setOutput(index, type, reinterpret_cast(memory->base() + offset), length)) + { + VERBOSE(NNAPI::Execution) << "setOutputFromMemory: Fail to set input" << std::endl; + return ANEURALNETWORKS_BAD_DATA; + } + + return ANEURALNETWORKS_NO_ERROR; } diff --git a/runtimes/neurun/frontend/nnapi/wrapper/memory.cc b/runtimes/neurun/frontend/nnapi/wrapper/memory.cc index 4560151..e6c9cda 100644 --- a/runtimes/neurun/frontend/nnapi/wrapper/memory.cc +++ b/runtimes/neurun/frontend/nnapi/wrapper/memory.cc @@ -29,3 +29,18 @@ ANeuralNetworksMemory::ANeuralNetworksMemory(size_t size, int protect, int fd, s } ANeuralNetworksMemory::~ANeuralNetworksMemory() { munmap(reinterpret_cast(_base), _size); } + +bool ANeuralNetworksMemory::vaildAccess(size_t offset, size_t length) const +{ + if ((offset >= _size) || (length > _size)) + { + return false; + } + + if ((offset + length) >= _size) + { + return false; + } + + return true; +} diff --git a/runtimes/neurun/frontend/nnapi/wrapper/memory.h b/runtimes/neurun/frontend/nnapi/wrapper/memory.h index a430bcf..48a1bc5 100644 --- a/runtimes/neurun/frontend/nnapi/wrapper/memory.h +++ b/runtimes/neurun/frontend/nnapi/wrapper/memory.h @@ -28,7 +28,8 @@ public: public: size_t size(void) const { return _size; } uint8_t *base(void) { return _base; } - const uint8_t *base(void) const { return _base; } + uint8_t *base(void) const { return _base; } + bool vaildAccess(size_t offset, size_t length) const; private: size_t _size; diff --git a/tests/nnapi/nnapi_gtest.skip.armv7l-linux.neurun b/tests/nnapi/nnapi_gtest.skip.armv7l-linux.neurun index 6c95cfc..d214925 100644 --- a/tests/nnapi/nnapi_gtest.skip.armv7l-linux.neurun +++ b/tests/nnapi/nnapi_gtest.skip.armv7l-linux.neurun @@ -2,8 +2,6 @@ # Following tests will be skipped on armv7l-linux # # Not support operations -ValidationTestExecution.SetInputFromMemory -ValidationTestExecution.SetOutputFromMemory ValidationTestExecution.StartCompute GeneratedTests.depth_to_space* GeneratedTests.local_response_norm*