[core.ADT.tensor] Introduce Overlay/Buffer (#386)
author박종현/동작제어Lab(SR)/Staff Engineer/삼성전자 <jh1302.park@samsung.com>
Wed, 27 Jun 2018 06:36:39 +0000 (15:36 +0900)
committerGitHub Enterprise <noreply-CODE@samsung.com>
Wed, 27 Jun 2018 06:36:39 +0000 (15:36 +0900)
This commit revises tensor::View<T> as an interface, and introduces two
implementations: Overlay<T> and Buffer<T>

Overlay<T> is a tensor view over externally allocated memory region, and
Buffer<T> is a tensor view which owns content memory (currently
implemented via vector)

Signed-off-by: Jonghyun Park <jh1302.park@samsung.com>
contrib/nnkit/backends/caffe/Module.cpp
libs/core/include/nncc/core/ADT/tensor/Buffer.h [new file with mode: 0644]
libs/core/include/nncc/core/ADT/tensor/Overlay.h [new file with mode: 0644]
libs/core/include/nncc/core/ADT/tensor/View.h
libs/core/src/ADT/tensor/Buffer.test.cpp [new file with mode: 0644]
libs/core/src/ADT/tensor/Overlay.test.cpp [new file with mode: 0644]
libs/core/src/ADT/tensor/View.test.cpp [deleted file]

index f664fa3..0ca099f 100644 (file)
@@ -1,8 +1,5 @@
 #include <nncc/core/ADT/tensor/LexicalLayout.h>
-#include <nncc/core/ADT/tensor/View.h>
-
-#include <nncc/foundation/Memory.h>
-#include <nncc/foundation/ExternalRegion.h>
+#include <nncc/core/ADT/tensor/Overlay.h>
 
 #include <caffe/caffe.hpp>
 
@@ -33,13 +30,9 @@ template <typename DType> struct BlobContext
   virtual std::string name(uint32_t n) const = 0;
   virtual caffe::Blob<DType> *blob(uint32_t n) = 0;
 
-  std::unique_ptr<nncc::foundation::Region<DType>> region(uint32_t n)
+  DType *region(uint32_t n)
   {
-    auto b = blob(n);
-    auto count = b->count();
-    auto data = b->mutable_cpu_data();
-
-    return nncc::foundation::make_unique<nncc::foundation::ExternalRegion<DType>>(data, count);
+    return blob(n)->mutable_cpu_data();
   }
 };
 
@@ -134,10 +127,10 @@ public:
   void getMutableFloatTensor(uint32_t n, const TensorContext::TypedAccessor<float> &f) override
   {
     using nncc::core::ADT::tensor::LexicalLayout;
-    using nncc::core::ADT::tensor::make_view;
+    using nncc::core::ADT::tensor::make_overlay;
 
-    auto span = _blobs.region(n);
-    auto view = make_view<float, LexicalLayout>(shape(n), std::move(span));
+    auto base = _blobs.region(n);
+    auto view = make_overlay<float, LexicalLayout>(shape(n), base);
 
     f(*this, n, view);
   }
@@ -145,10 +138,10 @@ public:
   void getConstFloatTensor(uint32_t n, const TensorContext::TypedReader<float> &f) const override
   {
     using nncc::core::ADT::tensor::LexicalLayout;
-    using nncc::core::ADT::tensor::make_view;
+    using nncc::core::ADT::tensor::make_overlay;
 
-    auto span = _blobs.region(n);
-    auto view = make_view<float, LexicalLayout>(shape(n), std::move(span));
+    auto base = _blobs.region(n);
+    auto view = make_overlay<float, LexicalLayout>(shape(n), base);
 
     f(*this, n, view);
   }
diff --git a/libs/core/include/nncc/core/ADT/tensor/Buffer.h b/libs/core/include/nncc/core/ADT/tensor/Buffer.h
new file mode 100644 (file)
index 0000000..44d7d3b
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef __NNCC_CORE_ADT_TENSOR_BUFFER_H__
+#define __NNCC_CORE_ADT_TENSOR_BUFFER_H__
+
+#include "nncc/core/ADT/tensor/View.h"
+
+namespace nncc
+{
+namespace core
+{
+namespace ADT
+{
+namespace tensor
+{
+
+template <typename T> class Buffer final : public View<T>
+{
+public:
+  explicit Buffer(const Shape &shape, const Layout &layout) : View<T>{shape, layout}
+  {
+    _buffer.resize(num_elements(shape));
+  }
+
+public:
+  T *base(void) override { return _buffer.data(); }
+  const T *base(void) const override { return _buffer.data(); }
+
+private:
+  std::vector<T> _buffer;
+};
+
+template <typename T, typename LayoutImpl> Buffer<T> make_buffer(const Shape &shape)
+{
+  return Buffer<T>{shape, LayoutImpl{}};
+}
+
+} // namespace tensor
+} // namespace ADT
+} // namespace core
+} // namespace nncc
+
+#endif // __NNCC_CORE_ADT_TENSOR_BUFFER_H__
diff --git a/libs/core/include/nncc/core/ADT/tensor/Overlay.h b/libs/core/include/nncc/core/ADT/tensor/Overlay.h
new file mode 100644 (file)
index 0000000..921d0cb
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef __NNCC_CORE_ADT_TENSOR_OVERLAY_H__
+#define __NNCC_CORE_ADT_TENSOR_OVERLAY_H__
+
+#include "nncc/core/ADT/tensor/View.h"
+
+namespace nncc
+{
+namespace core
+{
+namespace ADT
+{
+namespace tensor
+{
+
+template <typename T> class Overlay final : public View<T>
+{
+public:
+  explicit Overlay(const Shape &shape, const Layout &layout, T *base)
+      : View<T>{shape, layout}, _base{base}
+  {
+    // DO NOTHING
+  }
+
+public:
+  T *base(void) override { return _base; }
+  const T *base(void) const override { return _base; }
+
+private:
+  T *const _base;
+};
+
+template <typename T, typename LayoutImpl> Overlay<T> make_overlay(const Shape &shape, T *base)
+{
+  return Overlay<T>{shape, LayoutImpl{}, base};
+}
+
+} // namespace tensor
+} // namespace ADT
+} // namespace core
+} // namespace nncc
+
+#endif // __NNCC_CORE_ADT_TENSOR_OVERLAY_H__
index c4a1458..6dcf7e2 100644 (file)
@@ -7,10 +7,6 @@
 #include "nncc/core/ADT/tensor/Accessor.h"
 #include "nncc/core/ADT/tensor/Layout.h"
 
-#include <nncc/foundation/Region.h>
-
-#include <memory>
-
 namespace nncc
 {
 namespace core
@@ -20,24 +16,27 @@ namespace ADT
 namespace tensor
 {
 
-template <typename T> class View final : public Reader<T>, public Accessor<T>
+template <typename T> class View : public Reader<T>, public Accessor<T>
 {
 public:
-  explicit View(const Shape &shape, const Layout &layout,
-                std::unique_ptr<nncc::foundation::Region<T>> &&region)
-      : _shape{shape}, _layout{std::move(layout)}, _region{std::move(region)}
+  explicit View(const Shape &shape, const Layout &layout)
+      : _shape{shape}, _layout{std::move(layout)}
   {
     // DO NOTHING
   }
 
 public:
-  T at(const Index &index) const override
-  {
-    return *(_region->base() + _layout.offset(_shape, index));
-  }
+  virtual ~View() = default;
+
+public:
+  virtual T *base(void) = 0;
+  virtual const T *base(void) const = 0;
 
 public:
-  T &at(const Index &index) override { return *(_region->base() + _layout.offset(_shape, index)); }
+  T at(const Index &index) const override { return *(base() + _layout.offset(_shape, index)); }
+
+public:
+  T &at(const Index &index) override { return *(base() + _layout.offset(_shape, index)); }
 
 public:
   const Shape &shape(void) const { return _shape; }
@@ -45,17 +44,8 @@ public:
 private:
   const Shape _shape;
   const Layout _layout;
-
-private:
-  std::unique_ptr<nncc::foundation::Region<T>> _region;
 };
 
-template <typename T, typename LayoutImpl>
-View<T> make_view(const Shape &shape, std::unique_ptr<nncc::foundation::Region<T>> &&region)
-{
-  return View<T>{shape, LayoutImpl{}, std::move(region)};
-}
-
 } // namespace tensor
 } // namespace ADT
 } // namespace core
diff --git a/libs/core/src/ADT/tensor/Buffer.test.cpp b/libs/core/src/ADT/tensor/Buffer.test.cpp
new file mode 100644 (file)
index 0000000..66d386e
--- /dev/null
@@ -0,0 +1,33 @@
+#include "nncc/core/ADT/tensor/Buffer.h"
+#include "nncc/core/ADT/tensor/LexicalLayout.h"
+
+#include <gtest/gtest.h>
+
+using nncc::core::ADT::tensor::Shape;
+using nncc::core::ADT::tensor::Index;
+using nncc::core::ADT::tensor::LexicalLayout;
+using nncc::core::ADT::tensor::Buffer;
+
+using nncc::core::ADT::tensor::make_buffer;
+
+TEST(ADT_TENSOR_BUFFER, ctor)
+{
+  const Shape shape{2, 3};
+  auto buffer = make_buffer<int, LexicalLayout>(shape);
+
+  ASSERT_EQ(buffer.shape(), shape);
+}
+
+TEST(ADT_TENSOR_BUFFER, access)
+{
+  const Shape shape{2, 3};
+  auto buffer = make_buffer<int, LexicalLayout>(shape);
+
+  const Index index{1, 2};
+
+  ASSERT_EQ(buffer.at(index), 0);
+  buffer.at(index) = 4;
+
+  // Casting is introduced to use 'const T &at(...) const' method
+  ASSERT_EQ(static_cast<const Buffer<int> &>(buffer).at(index), 4);
+}
diff --git a/libs/core/src/ADT/tensor/Overlay.test.cpp b/libs/core/src/ADT/tensor/Overlay.test.cpp
new file mode 100644 (file)
index 0000000..00d4991
--- /dev/null
@@ -0,0 +1,59 @@
+#include "nncc/core/ADT/tensor/Overlay.h"
+#include "nncc/core/ADT/tensor/LexicalLayout.h"
+
+#include <gtest/gtest.h>
+
+using nncc::core::ADT::tensor::Shape;
+using nncc::core::ADT::tensor::Index;
+using nncc::core::ADT::tensor::LexicalLayout;
+using nncc::core::ADT::tensor::Overlay;
+
+using nncc::core::ADT::tensor::make_overlay;
+
+TEST(ADT_TENSOR_OVERLAY, ctor)
+{
+  const Shape shape{2, 3};
+
+  int data[2 * 3] = {
+      0,
+  };
+  auto view = make_overlay<int, LexicalLayout>(shape, data);
+
+  ASSERT_EQ(view.shape(), shape);
+}
+
+TEST(ADT_TENSOR_OVERLAY, read)
+{
+  const Shape shape{2, 3};
+
+  int data[2 * 3] = {
+      0,
+  };
+  const auto view = make_overlay<int, LexicalLayout>(shape, data);
+
+  LexicalLayout layout{};
+
+  const Index index{1, 2};
+
+  ASSERT_EQ(data[layout.offset(shape, index)], 0);
+  data[layout.offset(shape, index)] = 2;
+  ASSERT_EQ(view.at(index), 2);
+}
+
+TEST(ADT_TENSOR_OVERLAY, access)
+{
+  const Shape shape{2, 3};
+
+  int data[2 * 3] = {
+      0,
+  };
+  auto view = make_overlay<int, LexicalLayout>(shape, data);
+
+  LexicalLayout layout{};
+
+  const Index index{1, 2};
+
+  ASSERT_EQ(data[layout.offset(shape, index)], 0);
+  view.at(index) = 4;
+  ASSERT_EQ(data[layout.offset(shape, index)], 4);
+}
diff --git a/libs/core/src/ADT/tensor/View.test.cpp b/libs/core/src/ADT/tensor/View.test.cpp
deleted file mode 100644 (file)
index 6b60167..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-#include "nncc/core/ADT/tensor/View.h"
-#include "nncc/core/ADT/tensor/LexicalLayout.h"
-
-#include <nncc/foundation/Memory.h>
-#include <nncc/foundation/ExternalRegion.h>
-
-#include <gtest/gtest.h>
-
-using namespace nncc::core::ADT::tensor;
-
-using nncc::foundation::make_unique;
-using nncc::foundation::ExternalRegion;
-
-TEST(ADT_TENSOR_VIEW, ctor)
-{
-  const Shape shape{2, 3};
-
-  int data[2 * 3] = {
-      0,
-  };
-  auto region = make_unique<ExternalRegion<int>>(data, 2 * 3);
-  auto view = make_view<int, LexicalLayout>(shape, std::move(region));
-
-  ASSERT_EQ(view.shape(), shape);
-}
-
-TEST(ADT_TENSOR_VIEW, read)
-{
-  const Shape shape{2, 3};
-
-  int data[2 * 3] = {
-      0,
-  };
-  auto region = make_unique<ExternalRegion<int>>(data, 2 * 3);
-  const auto view = make_view<int, LexicalLayout>(shape, std::move(region));
-
-  LexicalLayout layout{};
-
-  const Index index{1, 2};
-
-  ASSERT_EQ(data[layout.offset(shape, index)], 0);
-  data[layout.offset(shape, index)] = 2;
-  ASSERT_EQ(view.at(index), 2);
-}
-
-TEST(ADT_TENSOR_VIEW, access)
-{
-  const Shape shape{2, 3};
-
-  int data[2 * 3] = {
-      0,
-  };
-  auto region = make_unique<ExternalRegion<int>>(data, 2 * 3);
-  auto view = make_view<int, LexicalLayout>(shape, std::move(region));
-
-  LexicalLayout layout{};
-
-  const Index index{1, 2};
-
-  ASSERT_EQ(data[layout.offset(shape, index)], 0);
-  view.at(index) = 4;
-  ASSERT_EQ(data[layout.offset(shape, index)], 4);
-}