You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@singa.apache.org by wa...@apache.org on 2018/07/05 03:10:04 UTC

[09/18] incubator-singa git commit: SINGA-371 Implement functional operations in c++ for autograd

SINGA-371 Implement functional operations in c++ for autograd

- implement autograd convolution operation's support functions for CPU part.

- these functions have been tested and almostly passed unit tests.


Project: http://git-wip-us.apache.org/repos/asf/incubator-singa/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-singa/commit/dfe4478d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-singa/tree/dfe4478d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-singa/diff/dfe4478d

Branch: refs/heads/master
Commit: dfe4478d330a919107936968f85eea4dea91fc19
Parents: 5c8504a
Author: xuewanqi <xu...@outlook.com>
Authored: Tue Jun 26 01:52:48 2018 +0000
Committer: xuewanqi <xu...@outlook.com>
Committed: Tue Jun 26 08:24:40 2018 +0000

----------------------------------------------------------------------
 src/api/model_operation.i          |  16 ++++
 src/model/convolution_functions.cc | 160 ++++++++++++++++++++++++++++++++
 src/model/convolution_functions.h  |  28 ++++++
 3 files changed, 204 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/dfe4478d/src/api/model_operation.i
----------------------------------------------------------------------
diff --git a/src/api/model_operation.i b/src/api/model_operation.i
index a74ec5e..20f112e 100644
--- a/src/api/model_operation.i
+++ b/src/api/model_operation.i
@@ -9,6 +9,8 @@ struct ConvHandle{};
 
 struct CudnnConvHandle{size_t batchsize;};
 
+struct CpuConvHandle{};
+
 ConvHandle SetupConv(
     const size_t kernel_h_, const size_t kernel_w_,
     const size_t pad_h_, const size_t pad_w_,
@@ -28,4 +30,18 @@ Tensor CudnnConvBackwardb(const Tensor &dy, const Tensor &b, const CudnnConvHand
 
 Tensor CudnnConvBackwardx(const Tensor &dy, const Tensor &W, const Tensor &x, const CudnnConvHandle cch);
 
+
+CpuConvHandle InitCpuHandle(const Tensor &input, const ConvHandle ch);
+
+Tensor CpuConvForward(const Tensor &x, Tensor &W,  Tensor &b,
+                        const ConvHandle ch, const CpuConvHandle cch);
+
+Tensor CpuConvBackwardx(const Tensor &dy, Tensor &W, const Tensor &x, 
+    const ConvHandle ch, const CpuConvHandle cch);
+
+Tensor CpuConvBackwardW(const Tensor &dy, const Tensor &x, const Tensor &W, 
+    const ConvHandle ch, const CpuConvHandle cch);
+
+Tensor CpuConvBackwardb(const Tensor &dy, const Tensor &b, const ConvHandle ch, const CpuConvHandle cch);
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/dfe4478d/src/model/convolution_functions.cc
----------------------------------------------------------------------
diff --git a/src/model/convolution_functions.cc b/src/model/convolution_functions.cc
index 7ff399a..6e4b195 100644
--- a/src/model/convolution_functions.cc
+++ b/src/model/convolution_functions.cc
@@ -4,6 +4,7 @@
 //#include "./layer/cudnn_utils.h"
 //#include "singa/utils/logging.h"
 #include "./convolution_functions.h"
+#include "./layer/convolution.h"
 #include<iostream>
 namespace singa{
 
@@ -292,6 +293,165 @@ Tensor CudnnConvBackwardx(const Tensor &dy, const Tensor &W, const Tensor &x, co
     return dx;
 };
 
+CpuConvHandle InitCpuHandle(const Tensor &input, const ConvHandle ch){
+    size_t height_;
+    size_t width_;
+    size_t conv_height_;
+    size_t conv_width_;    
+    size_t batchsize;
+    size_t channels_;
+
+    size_t col_height_;
+    size_t col_width_;
+
+    batchsize = input.shape(0);
+    channels_ = input.shape(1);
+    height_ = input.shape(2);
+    width_ = input.shape(3);
+
+    CHECK(channels_ == ch.channels_)<<"the number of input channels mismatched.";
+
+    conv_height_ = 1;
+    if (ch.stride_h_ > 0)
+        conv_height_ = (height_ + 2 * ch.pad_h_ - ch.kernel_h_) / ch.stride_h_ + 1;
+    conv_width_ = (width_ + 2 * ch.pad_w_ - ch.kernel_w_) / ch.stride_w_ + 1;
+
+    col_height_ = ch.channels_ * ch.kernel_w_ * ch.kernel_h_;
+    col_width_ = conv_height_ * conv_width_;
+
+    return CpuConvHandle{
+        height_,
+        width_,
+        conv_height_,
+        conv_width_,
+        batchsize,
+
+        col_height_,
+        col_width_
+    };
+};
+
+Convolution C;
+
+Tensor CpuConvForward(const Tensor &x, Tensor &W,  Tensor &b,
+                        const ConvHandle ch, const CpuConvHandle cch){
+    CHECK_EQ(x.device()->lang(), kCpp);
+    CHECK_EQ(x.nDim(), 4u);
+    CHECK_EQ(x.shape()[0],cch.batchsize);
+    CHECK_EQ(x.shape()[1],ch.channels_);
+    CHECK_EQ(x.shape()[2],cch.height_);
+    CHECK_EQ(x.shape()[3],cch.width_);
+
+    size_t imagesize = x.Size() / cch.batchsize;
+
+    Shape w_shape= W.shape();
+    Shape b_shape= b.shape();
+
+    W.Reshape(Shape{ch.num_filters_, cch.col_height_});
+    if (ch.bias_term_)
+      b.Reshape(Shape{ch.num_filters_});
+
+    DataType dtype = x.data_type();
+    auto dev = x.device();
+    Shape shape{cch.batchsize, ch.num_filters_, cch.conv_height_, cch.conv_width_};
+    Tensor output(shape, dev, dtype);
+
+    Tensor col_data(Shape{cch.col_height_, cch.col_width_});//broadcasted image
+
+    float *data_col = new float[cch.col_height_ * cch.col_width_];
+    auto in_data = x.data<float>();
+    for (size_t num = 0; num < cch.batchsize; num++) {
+      C.Im2col(in_data + num * imagesize, ch.channels_, cch.height_, cch.width_, ch.kernel_h_,
+            ch.kernel_w_, ch.pad_h_, ch.pad_w_, ch.stride_h_, ch.stride_w_, data_col);
+      col_data.CopyDataFromHostPtr(data_col, cch.col_height_ * cch.col_width_);
+      Tensor each = Mult(W, col_data);
+      if (ch.bias_term_) {
+          AddColumn(b, &each);
+        }
+      CopyDataToFrom(&output, each, each.Size(), num * each.Size());
+  }
+  W.Reshape(w_shape);
+  b.Reshape(b_shape);
+  return output;
+}; 
+
+Tensor CpuConvBackwardx(const Tensor &dy, Tensor &W, const Tensor &x, 
+    const ConvHandle ch, const CpuConvHandle cch){
+    CHECK_EQ(dy.device()->lang(), kCpp);
+    CHECK_EQ(dy.nDim(), 4u);
+
+    Shape w_shape= W.shape();
+    W.Reshape(Shape{ch.num_filters_, cch.col_height_});
+
+    Tensor dx;
+    dx.ResetLike(x);
+    
+    size_t imagesize = x.Size() / cch.batchsize;
+    float *dx_b = new float[imagesize];
+
+    for (size_t num = 0; num < cch.batchsize; num++) {
+      Tensor grad_b(Shape{ch.num_filters_, cch.conv_height_ * cch.conv_width_});
+      CopyDataToFrom(&grad_b, dy, grad_b.Size(), 0, num * grad_b.Size());
+      Tensor dcol_b = Mult(W.T(), grad_b);
+      auto dcol_data = dcol_b.data<float>();
+      C.Col2im(dcol_data, ch.channels_, cch.height_, cch.width_, ch.kernel_h_, ch.kernel_w_, ch.pad_h_,
+           ch.pad_w_, ch.stride_h_, ch.stride_w_, dx_b);
+      dx.CopyDataFromHostPtr(dx_b, imagesize, num * imagesize);
+    }
+  W.Reshape(w_shape); 
+  return dx;
+};
+
+Tensor CpuConvBackwardW(const Tensor &dy, const Tensor &x, const Tensor &W, 
+    const ConvHandle ch, const CpuConvHandle cch){
+    CHECK_EQ(dy.device()->lang(), kCpp);
+    CHECK_EQ(dy.nDim(), 4u);
+
+    size_t imagesize = x.Size() / cch.batchsize;
+
+    Tensor dW;
+    dW.ResetLike(W);
+    dW.SetValue(0.0f);
+    
+    Shape w_shape= W.shape();
+    dW.Reshape(Shape{ch.num_filters_, cch.col_height_});
+
+    Tensor col_data(Shape{cch.col_height_, cch.col_width_});//broadcasted image
+
+    float *data_col = new float[cch.col_height_ * cch.col_width_];
+    auto in_data = dy.data<float>();
+    for (size_t num = 0; num < cch.batchsize; num++) {
+      C.Im2col(in_data + num * imagesize, ch.channels_, cch.height_, cch.width_, ch.kernel_h_,
+            ch.kernel_w_, ch.pad_h_, ch.pad_w_, ch.stride_h_, ch.stride_w_, data_col);
+      col_data.CopyDataFromHostPtr(data_col, cch.col_height_ * cch.col_width_);
+      Tensor grad_b(Shape{ch.num_filters_, cch.conv_height_ * cch.conv_width_});
+      CopyDataToFrom(&grad_b, dy, grad_b.Size(), 0, num * grad_b.Size());
+      dW += Mult(grad_b, col_data.T());
+    }
+   dW.Reshape(w_shape);
+    //dW.Reshape(Shape{ch.num_filters_,ch.channels_ , ch.kernel_w_ , ch.kernel_h_});
+   return dW;
+};
+
+Tensor CpuConvBackwardb(const Tensor &dy, const Tensor &b, const ConvHandle ch, const CpuConvHandle cch){
+    CHECK_EQ(dy.device()->lang(), kCpp);
+    CHECK_EQ(dy.nDim(), 4u);
+
+    Tensor db;
+    db.ResetLike(b);
+
+    auto tmpshp = Shape{cch.batchsize * ch.num_filters_, dy.Size() / (cch.batchsize * ch.num_filters_)};
+    Tensor tmp1 = Reshape(dy, tmpshp);
+
+    Tensor tmp2(Shape{cch.batchsize * ch.num_filters_});
+    SumColumns(tmp1, &tmp2);
+    Tensor tmp3 = Reshape(tmp2, Shape{cch.batchsize, ch.num_filters_});
+
+    SumRows(tmp3, &db);
+
+    return db;
+};
+
 } //namespace_singa
 
 

http://git-wip-us.apache.org/repos/asf/incubator-singa/blob/dfe4478d/src/model/convolution_functions.h
----------------------------------------------------------------------
diff --git a/src/model/convolution_functions.h b/src/model/convolution_functions.h
index e34423f..1b90941 100644
--- a/src/model/convolution_functions.h
+++ b/src/model/convolution_functions.h
@@ -43,6 +43,20 @@ struct CudnnConvHandle{
     size_t batchsize;
 };
 
+struct CpuConvHandle{
+    size_t height_;
+    size_t width_;
+    size_t conv_height_;
+    size_t conv_width_;
+    size_t batchsize;
+
+    size_t col_height_;
+    size_t col_width_;
+
+};
+
+    
+
 ConvHandle SetupConv(
     const size_t kernel_h_, const size_t kernel_w_,
     const size_t pad_h_, const size_t pad_w_,
@@ -64,4 +78,18 @@ Tensor CudnnConvBackwardb(const Tensor &dy, const Tensor &b, const CudnnConvHand
 
 Tensor CudnnConvBackwardx(const Tensor &dy, const Tensor &W, const Tensor &x, const CudnnConvHandle cch);
 
+
+CpuConvHandle InitCpuHandle(const Tensor &input, const ConvHandle ch);
+
+Tensor CpuConvForward(const Tensor &x, Tensor &W,  Tensor &b,
+                        const ConvHandle ch, const CpuConvHandle cch);
+
+Tensor CpuConvBackwardx(const Tensor &dy, Tensor &W, const Tensor &x, 
+    const ConvHandle ch, const CpuConvHandle cch);
+
+Tensor CpuConvBackwardW(const Tensor &dy, const Tensor &x, const Tensor &W, 
+    const ConvHandle ch, const CpuConvHandle cch);
+
+Tensor CpuConvBackwardb(const Tensor &dy, const Tensor &b, const ConvHandle ch, const CpuConvHandle cch);
+
 }