\copydoc Layer::Forward(int flag, const Tensor&)
| 26 | |
| 27 | /// \copydoc Layer::Forward(int flag, const Tensor&) |
| 28 | const Tensor OpenclConvolution::Forward(int flag, const Tensor &input) { |
| 29 | CHECK(buf_.empty()); |
| 30 | CHECK_EQ(input.device()->lang(), kOpencl); |
| 31 | CHECK_EQ(input.nDim(), 4u); |
| 32 | |
| 33 | if (flag & kTrain) buf_.push(input); |
| 34 | |
| 35 | auto batchsize = input.shape(0); |
| 36 | auto imagesize = input.Size() / batchsize; |
| 37 | auto data_type = input.data_type(); |
| 38 | auto device = input.device(); |
| 39 | |
| 40 | // TODO(wangwei) update the layer config if the input sample shape changes |
| 41 | CHECK(input.shape(1) == channels_ && input.shape(2) == height_ && |
| 42 | input.shape(3) == width_) << "input sample shape should not change"; |
| 43 | |
| 44 | Shape shape{batchsize, num_filters_, conv_height_, conv_width_}; |
| 45 | Tensor output(shape, device, data_type); |
| 46 | Tensor col_data(Shape{col_height_, col_width_}, device, data_type); |
| 47 | |
| 48 | for (size_t b = 0; b < batchsize; b++) { |
| 49 | int offset = b * imagesize; |
| 50 | |
| 51 | col_data.device()->Exec([input, offset, col_data, this](Context * ctx) mutable { |
| 52 | |
| 53 | this->Im2Col(input.block(), offset, |
| 54 | height_, width_, |
| 55 | kernel_h_, kernel_w_, |
| 56 | pad_h_, pad_w_, |
| 57 | stride_h_, stride_w_, |
| 58 | conv_height_, conv_width_, |
| 59 | 0, channels_, |
| 60 | col_data.block(), ctx); |
| 61 | }, |
| 62 | {input.block()}, |
| 63 | {col_data.block()}); |
| 64 | |
| 65 | Tensor each = Mult(weight_, col_data); |
| 66 | |
| 67 | if (bias_term_) { |
| 68 | AddColumn(bias_, &each); |
| 69 | } |
| 70 | |
| 71 | CopyDataToFrom(&output, each, each.Size(), b * each.Size()); |
| 72 | } |
| 73 | |
| 74 | return output; |
| 75 | } |
| 76 | |
| 77 | |
| 78 | /// \copydoc Layer::Backward(int, const Tensor&, const Tensor&); |
nothing calls this directly
no test coverage detected