[Fix] fix lda, ldb param
authorJihoon Lee <jhoon.it.lee@samsung.com>
Fri, 11 Dec 2020 07:58:34 +0000 (16:58 +0900)
committerJijoong Moon <jijoong.moon@samsung.com>
Thu, 17 Dec 2020 04:47:22 +0000 (13:47 +0900)
**Changes proposed in this PR:**
- lda, ldb, ldc is for layout so it should be set in terms of memory
layout, this patch fixes the issue while adding a corresponding test

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

Signed-off-by: Jihoon Lee <jhoon.it.lee@samsung.com>
nntrainer/tensor/tensor.cpp
test/unittest/unittest_nntrainer_tensor.cpp

index 803f22f..fde2996 100644 (file)
@@ -564,7 +564,8 @@ Tensor Tensor::dot(Tensor const &m, bool trans, bool trans_m) const {
 /**
  * @note: This dot product flattens the fist 3 axis for the purpose of
  * computation. So, while performing, these matrices are behaving as 2-D
- * matrices. The dimensions are restored while returning back the tensor.
+ * matrices. The dimensions are restored while returning back the tensor
+ * in case of trans is false.
  */
 Tensor &Tensor::dot(Tensor const &m, Tensor &result, bool trans,
                     bool trans_m) const {
@@ -591,9 +592,7 @@ Tensor &Tensor::dot(Tensor const &m, Tensor &result, bool trans,
     K = mdim1; /** == dim2 */
     N = mdim2;
     M = dim1;
-    lda = K;
-    ldb = N;
-    CREATE_IF_EMPTY_DIMS(result, batch(), channel(), height(), mdim2);
+    CREATE_IF_EMPTY_DIMS(result, batch(), channel(), height(), N);
 
     // We are not set zero the result because of performnace reason.
     // However, result is not initialized properly. There might include garbage
@@ -607,9 +606,7 @@ Tensor &Tensor::dot(Tensor const &m, Tensor &result, bool trans,
     K = mdim2; /** == dim2 */
     N = mdim1;
     M = dim1;
-    lda = K;
-    ldb = K;
-    CREATE_IF_EMPTY_DIMS(result, batch(), channel(), height(), mdim1);
+    CREATE_IF_EMPTY_DIMS(result, batch(), channel(), height(), N);
   } else if (trans && !trans_m) {
     if (dim1 != mdim1)
       throw std::runtime_error(
@@ -617,9 +614,7 @@ Tensor &Tensor::dot(Tensor const &m, Tensor &result, bool trans,
     K = mdim1; /** == dim1 */
     N = mdim2;
     M = dim2;
-    lda = M;
-    ldb = N;
-    CREATE_IF_EMPTY_DIMS(result, 1, 1, dim2, mdim2);
+    CREATE_IF_EMPTY_DIMS(result, 1, 1, M, N);
   } else {
     if (dim1 != mdim2)
       throw std::runtime_error(
@@ -627,11 +622,11 @@ Tensor &Tensor::dot(Tensor const &m, Tensor &result, bool trans,
     K = mdim2; /** == dim1 */
     N = mdim1;
     M = dim2;
-    lda = M;
-    ldb = K;
-    CREATE_IF_EMPTY_DIMS(result, 1, 1, dim2, mdim1);
+    CREATE_IF_EMPTY_DIMS(result, 1, 1, M, N);
   }
-  ldc = N;
+  lda = dim2;
+  ldb = mdim2;
+  ldc = result.width();
 
   const float *data = getData();
   const float *mdata = m.getData();
index 91b08f9..85b2641 100644 (file)
@@ -1789,6 +1789,173 @@ end_dot_01_p:
   EXPECT_EQ(status, ML_ERROR_NONE);
 }
 
+TEST(nntrainer_Tensor, dot_transpose_p) {
+  {
+    float a_data[] = {0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, 11};
+    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 4), a_data);
+    float b_data[] = {0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11};
+    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 4, 3), b_data);
+    float answer_data[] = {20, 23,  26,  29,  56,  68,  80,  92,
+                           92, 113, 134, 155, 128, 158, 188, 218};
+    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 4), answer_data);
+    nntrainer::Tensor ret = a.dot(b, true, true);
+    EXPECT_EQ(ret, answer);
+  }
+  {
+    float a_data[] = {0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, 11};
+    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 4), a_data);
+    float b_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
+    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 4), b_data);
+    float answer_data[] = {20, 23,  26,  29,  56,  68,  80,  92,
+                           92, 113, 134, 155, 128, 158, 188, 218};
+    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 4), answer_data);
+    nntrainer::Tensor ret = a.dot(b, true, false);
+    EXPECT_EQ(ret, answer);
+  }
+  {
+    float a_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
+    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 4, 3), a_data);
+    float b_data[] = {0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11};
+    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 4, 3), b_data);
+    float answer_data[] = {20, 23,  26,  29,  56,  68,  80,  92,
+                           92, 113, 134, 155, 128, 158, 188, 218};
+    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 4), answer_data);
+    nntrainer::Tensor ret = a.dot(b, false, true);
+    EXPECT_EQ(ret, answer);
+  }
+  {
+    float a_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
+    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 4, 3), a_data);
+    float b_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
+    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 4), b_data);
+    float answer_data[] = {20, 23,  26,  29,  56,  68,  80,  92,
+                           92, 113, 134, 155, 128, 158, 188, 218};
+    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 4), answer_data);
+    nntrainer::Tensor ret = a.dot(b, false, false);
+    EXPECT_EQ(ret, answer);
+  }
+  {
+    float a_data[] = {0, 3, 1, 4, 2, 5};
+    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 2), a_data);
+    float b_data[] = {0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11};
+    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 4, 3), b_data);
+    float answer_data[] = {20, 23, 26, 29, 56, 68, 80, 92};
+    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 4), answer_data);
+    nntrainer::Tensor ret = a.dot(b, true, true);
+    EXPECT_EQ(ret, answer);
+  }
+  {
+    float a_data[] = {0, 3, 1, 4, 2, 5};
+    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 2), a_data);
+    float b_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
+    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 4), b_data);
+    float answer_data[] = {20, 23, 26, 29, 56, 68, 80, 92};
+    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 4), answer_data);
+    nntrainer::Tensor ret = a.dot(b, true, false);
+    EXPECT_EQ(ret, answer);
+  }
+  {
+    float a_data[] = {0, 1, 2, 3, 4, 5};
+    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 2, 3), a_data);
+    float b_data[] = {0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11};
+    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 4, 3), b_data);
+    float answer_data[] = {20, 23, 26, 29, 56, 68, 80, 92};
+    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 4), answer_data);
+    nntrainer::Tensor ret = a.dot(b, false, true);
+    EXPECT_EQ(ret, answer);
+  }
+  {
+    float a_data[] = {0, 1, 2, 3, 4, 5};
+    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 2, 3), a_data);
+    float b_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
+    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 4), b_data);
+    float answer_data[] = {20, 23, 26, 29, 56, 68, 80, 92};
+    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 4), answer_data);
+    nntrainer::Tensor ret = a.dot(b, false, false);
+    EXPECT_EQ(ret, answer);
+  }
+  {
+    float a_data[] = {0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, 11};
+    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 4), a_data);
+    float b_data[] = {0, 2, 4, 1, 3, 5};
+    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 2, 3), b_data);
+    float answer_data[] = {10, 13, 28, 40, 46, 67, 64, 94};
+    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 2), answer_data);
+    nntrainer::Tensor ret = a.dot(b, true, true);
+    EXPECT_EQ(ret, answer);
+  }
+  {
+    float a_data[] = {0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, 11};
+    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 4), a_data);
+    float b_data[] = {0, 1, 2, 3, 4, 5};
+    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 2), b_data);
+    float answer_data[] = {10, 13, 28, 40, 46, 67, 64, 94};
+    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 2), answer_data);
+    nntrainer::Tensor ret = a.dot(b, true, false);
+    EXPECT_EQ(ret, answer);
+  }
+  {
+    float a_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
+    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 4, 3), a_data);
+    float b_data[] = {0, 2, 4, 1, 3, 5};
+    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 2, 3), b_data);
+    float answer_data[] = {10, 13, 28, 40, 46, 67, 64, 94};
+    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 2), answer_data);
+    nntrainer::Tensor ret = a.dot(b, false, true);
+    EXPECT_EQ(ret, answer);
+  }
+  {
+    float a_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
+    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 4, 3), a_data);
+    float b_data[] = {0, 1, 2, 3, 4, 5};
+    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 2), b_data);
+    float answer_data[] = {10, 13, 28, 40, 46, 67, 64, 94};
+    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 4, 2), answer_data);
+    nntrainer::Tensor ret = a.dot(b, false, false);
+    EXPECT_EQ(ret, answer);
+  }
+  {
+    float a_data[] = {0, 3, 1, 4, 2, 5};
+    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 2), a_data);
+    float b_data[] = {0, 2, 4, 1, 3, 5};
+    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 2, 3), b_data);
+    float answer_data[] = {10, 13, 28, 40};
+    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 2), answer_data);
+    nntrainer::Tensor ret = a.dot(b, true, true);
+    EXPECT_EQ(ret, answer);
+  }
+  {
+    float a_data[] = {0, 3, 1, 4, 2, 5};
+    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 3, 2), a_data);
+    float b_data[] = {0, 1, 2, 3, 4, 5};
+    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 2), b_data);
+    float answer_data[] = {10, 13, 28, 40};
+    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 2), answer_data);
+    nntrainer::Tensor ret = a.dot(b, true, false);
+    EXPECT_EQ(ret, answer);
+  }
+  {
+    float a_data[] = {0, 1, 2, 3, 4, 5};
+    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 2, 3), a_data);
+    float b_data[] = {0, 2, 4, 1, 3, 5};
+    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 2, 3), b_data);
+    float answer_data[] = {10, 13, 28, 40};
+    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 2), answer_data);
+    nntrainer::Tensor ret = a.dot(b, false, true);
+    EXPECT_EQ(ret, answer);
+  }
+  {
+    float a_data[] = {0, 1, 2, 3, 4, 5};
+    nntrainer::Tensor a(nntrainer::TensorDim(1, 1, 2, 3), a_data);
+    float b_data[] = {0, 1, 2, 3, 4, 5};
+    nntrainer::Tensor b(nntrainer::TensorDim(1, 1, 3, 2), b_data);
+    float answer_data[] = {10, 13, 28, 40};
+    nntrainer::Tensor answer(nntrainer::TensorDim(1, 1, 2, 2), answer_data);
+    nntrainer::Tensor ret = a.dot(b, false, false);
+    EXPECT_EQ(ret, answer);
+  }
+}
+
 TEST(nntrainer_Tensor, transpose_01_p) {
   int status = ML_ERROR_NONE;
   int batch = 3;