Enable external IO memory set validation test (#4860)
author오형석/On-Device Lab(SR)/Staff Engineer/삼성전자 <hseok82.oh@samsung.com>
Tue, 26 Mar 2019 11:20:15 +0000 (20:20 +0900)
committerGitHub Enterprise <noreply-CODE@samsung.com>
Tue, 26 Mar 2019 11:20:15 +0000 (20:20 +0900)
Implement NNAPI to set input and output using external memory

Signed-off-by: Hyeongseok Oh <hseok82.oh@samsung.com>
runtimes/neurun/frontend/nnapi/execution.cc
runtimes/neurun/frontend/nnapi/wrapper/memory.cc
runtimes/neurun/frontend/nnapi/wrapper/memory.h
tests/nnapi/nnapi_gtest.skip.armv7l-linux.neurun

index d7f9f7b..b00a873 100644 (file)
@@ -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<const void *>(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<void *>(memory->base() + offset), length))
+  {
+    VERBOSE(NNAPI::Execution) << "setOutputFromMemory: Fail to set input" << std::endl;
+    return ANEURALNETWORKS_BAD_DATA;
+  }
+
+  return ANEURALNETWORKS_NO_ERROR;
 }
index 4560151..e6c9cda 100644 (file)
@@ -29,3 +29,18 @@ ANeuralNetworksMemory::ANeuralNetworksMemory(size_t size, int protect, int fd, s
 }
 
 ANeuralNetworksMemory::~ANeuralNetworksMemory() { munmap(reinterpret_cast<void *>(_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;
+}
index a430bcf..48a1bc5 100644 (file)
@@ -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;
index 6c95cfc..d214925 100644 (file)
@@ -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*