[TensorDim] Change behaviour of default tensorDim constructor
authorParichay Kapoor <pk.kapoor@samsung.com>
Wed, 5 Aug 2020 01:29:05 +0000 (10:29 +0900)
committerJijoong Moon <jijoong.moon@samsung.com>
Tue, 11 Aug 2020 02:37:06 +0000 (11:37 +0900)
Default tensor dim constructor sets up tensorDim of all 0 which are invalid to use by nature
Setting any dimension resets all the 0 dimensions to 1
This removes allocation of memory by tensor on default constructor yet allows using default constructor of tensor

**Self evaluation:**
1. Build test: [x]Passed [ ]Failed [ ]Skipped
2. Run test: [x]Passed [ ]Failed [ ]Skipped

Signed-off-by: Parichay Kapoor <pk.kapoor@samsung.com>
nntrainer/include/tensor_dim.h
nntrainer/src/tensor.cpp
nntrainer/src/tensor_dim.cpp
test/unittest/unittest_nntrainer_layers.cpp

index def186f8a5ba38299f16e852cb15a9fae74f83b4..5e5045f76b9aeddc5d22f3b633d6e484e21f0723 100644 (file)
@@ -29,13 +29,14 @@ class TensorDim {
 public:
   TensorDim() {
     for (int i = 0; i < MAXDIM; ++i) {
-      dim[i] = 1;
+      dim[i] = 0;
     }
-    len = 1;
-    feature_len = 1;
+    len = 0;
+    feature_len = 0;
   }
 
-  TensorDim(unsigned int b, unsigned int c, unsigned int h, unsigned int w) {
+  TensorDim(unsigned int b, unsigned int c, unsigned int h, unsigned int w) :
+    TensorDim() {
     setTensorDim(0, b);
     setTensorDim(1, c);
     setTensorDim(2, h);
index 7ae077461a7124aab0c8778f6a62ce0177da854e..ea1a63c33d449896399ddfafb9d8af304d5a950b 100644 (file)
@@ -66,7 +66,18 @@ Tensor::Tensor(const TensorDim &d, const float *buf) :
   dim(d),
   strides{{1, 2, 3}},
   is_contiguous(true),
-  data(new float[d.getDataLen()], std::default_delete<float[]>()) {
+  data(d.getDataLen() == 0
+         ? nullptr
+         : std::shared_ptr<float>(new float[d.getDataLen()],
+                                  std::default_delete<float[]>())) {
+  if (d.getDataLen() == 0) {
+    if (buf != nullptr) {
+      throw std::runtime_error(
+        "Tensor dimension and source buffer size mismatch");
+    }
+    return;
+  }
+
   // todo: initialize appropriate strides
   if (buf != nullptr) {
     float *data = getData();
index e38ae902ef1797a75f1810080ba90385df20b6ef..ffda4c2227a1feef9bbd8af6a626b8bcc5ae0b51 100644 (file)
@@ -34,7 +34,8 @@ TensorDim &TensorDim::operator=(TensorDim &&rhs) noexcept {
 }
 
 void TensorDim::swap(TensorDim &lhs, TensorDim &rhs) noexcept {
-  std::swap(lhs.dim, rhs.dim);
+  std::swap_ranges(std::begin(lhs.dim), std::begin(lhs.dim) + MAXDIM,
+                   std::begin(rhs.dim));
   std::swap(lhs.len, rhs.len);
   std::swap(lhs.feature_len, rhs.feature_len);
 }
@@ -50,6 +51,12 @@ void TensorDim::setTensorDim(unsigned int idx, unsigned int value) {
       "[TensorDim] Trying to assign value of 0 to tensor dim");
   }
 
+  if (len == 0) {
+    for (int i = 0; i < MAXDIM; ++i) {
+      dim[i] = 1;
+    }
+  }
+
   dim[idx] = value;
   resetLen();
 }
index 89e331e56f97af87bdac34ad70b08a9adc8f2d2d..314c44044e9d53a4e4e50ce75768a3802c34da35 100644 (file)
@@ -402,7 +402,7 @@ protected:
   }
 
   void matchLoss(const char *file) {
-    nntrainer::Tensor loss;
+    nntrainer::Tensor loss(1, 1, 1, 1);
     loadFile(file, loss);
     EXPECT_NEAR(layers.back()->getLoss(), *(loss.getData()), tolerance);
   }
@@ -1000,15 +1000,15 @@ protected:
       EXPECT_NEAR(out_ptr[i], golden[i], tolerance);
     }
   }
+
+  virtual void prepareLayer() { setInputDim("2:3:5:5"); }
 };
 
 TEST_F(nntrainer_Pooling2DLayer, setProperty_01_p) {
-  setInputDim("2:3:5:5");
   setProperty("pooling_size=2,2 | stride=1,1 | padding=0,0 | pooling=average");
 }
 
 TEST_F(nntrainer_Pooling2DLayer, setProperty_02_n) {
-  setInputDim("2:3:5:5");
   int status = layer.setProperty({"pooling_size="});
   EXPECT_EQ(status, ML_ERROR_INVALID_PARAMETER);
 }
@@ -1174,13 +1174,15 @@ TEST_F(nntrainer_Pooling2DLayer, backwarding_04_p) {
 }
 
 class nntrainer_FlattenLayer
-  : public nntrainer_abstractLayer<nntrainer::FlattenLayer> {};
+  : public nntrainer_abstractLayer<nntrainer::FlattenLayer> {
+protected:
+  virtual void prepareLayer() { setInputDim("1:2:4:4"); }
+};
 
 /**
  * @brief Flatten Layer
  */
 TEST_F(nntrainer_FlattenLayer, forwarding_01_p) {
-  setInputDim("1:2:4:4");
   reinitialize(false);
 
   EXPECT_EQ(out.getDim(), nntrainer::TensorDim(1, 1, 1, 32));
@@ -1212,7 +1214,6 @@ TEST_F(nntrainer_FlattenLayer, forwarding_02_p) {
  * @brief Flatten Layer
  */
 TEST_F(nntrainer_FlattenLayer, backwarding_01_p) {
-  setInputDim("1:2:4:4");
   reinitialize(false);
 
   EXPECT_EQ(out.getDim(), nntrainer::TensorDim(1, 1, 1, 32));
@@ -1272,11 +1273,17 @@ TEST(nntrainer_LossLayer, setProperty_01_n) {
   EXPECT_EQ(status, ML_ERROR_INVALID_PARAMETER);
 }
 
-TEST(nntrainer_ActivationLayer, init_01_1) {
+TEST(nntrainer_ActivationLayer, init_01_n) {
+  nntrainer::ActivationLayer layer;
+  EXPECT_THROW(layer.initialize(false), std::invalid_argument);
+}
+
+TEST(nntrainer_ActivationLayer, init_02_p) {
   int status = ML_ERROR_NONE;
   nntrainer::ActivationLayer layer;
-  status = layer.initialize(false);
 
+  layer.setInputDimension({1, 1, 1, 1});
+  status = layer.initialize(false);
   EXPECT_EQ(status, ML_ERROR_NONE);
 }