1 #include "caffe2/operators/conv_transpose_op.h" 2 #include "caffe2/ideep/operators/conv_transpose_unpool_base_op.h" 3 #include "caffe2/ideep/operators/operator_fallback_ideep.h" 8 bool need_type_zero_pad(
const mkldnn_memory_desc_t *pd) {
13 for (
int i = 0; i < pd->ndims; i++) {
15 p2 *= pd->layout_desc.blocking.padding_dims[i];
24 USE_IDEEP_DEF_ALIASES();
25 USE_IDEEP_CONV_TRANSPOSE_UNPOOL_BASE_FUNCTIONS();
33 OperatorBase::GetSingleArgument<int>(
"training_mode", 0)),
34 fallback_(operator_def, ws) {
35 OPERATOR_NEEDS_FEATURE(
36 pad_l() == pad_r() && pad_t() == pad_b(),
37 "Uneven padding not supported.");
41 bool RunOnDeviceWithOrderNCHW()
override {
42 const auto& X = Input(INPUT);
43 const auto& filter = Input(FILTER);
44 auto* Y = Output(OUTPUT);
45 CAFFE_ENFORCE_EQ(X.ndims(), 4);
46 CAFFE_ENFORCE_EQ(filter.ndims(), 4);
47 CAFFE_ENFORCE_EQ(filter.get_dim(2), kernel_h());
48 CAFFE_ENFORCE_EQ(filter.get_dim(3), kernel_w());
50 ideep::tensor::dims Y_dims;
51 const bool pre_converted = filter.get_public_format() == ideep::format::iohw;
54 filter.get_dim(0), X.get_dim(1),
55 "filter number must be equal to input channel number");
57 Y_dims = CalcOutputDims(X, filter.get_dim(1));
59 ideep::tensor::dims filter_dims_mkldnn {filter.get_dim(1), filter.get_dim(0),
60 filter.get_dim(2), filter.get_dim(3)};
61 auto expected_descriptor =
62 ideep::convolution_transpose_forward::expected_weights_descriptor(
64 filter.get_data_type(),
68 const bool weights_changed =
69 (cached_weights_descriptor_ != filter.get_descriptor());
70 if (weights_changed) {
71 cached_weights_descriptor_ = filter.dup_descriptor();
74 if (training_mode_ || weights_changed) {
75 auto filter_in = filter;
78 filter_in.set_public_format(ideep::format::iohw);
79 filter_.init(expected_descriptor);
80 ideep::reorder::compute(filter_in, filter_);
85 if (need_type_zero_pad(filter_.get_mkldnn_memory_desc_t())) {
86 return fallback_.Run(0);
90 filter.get_dim(1), X.get_dim(1),
91 "filter number must be equal to input channel number");
95 if (need_type_zero_pad(filter.get_mkldnn_memory_desc_t())) {
96 return fallback_.Run(0);
99 Y_dims = CalcOutputDims(X, filter.get_dim(0));
102 if (InputSize() > BIAS) {
103 const auto& bias = Input(BIAS);
104 CAFFE_ENFORCE_EQ(bias.ndims(), 1,
"bias must be 1D tensor");
106 bias.get_dim(0), pre_converted ? filter.get_dim(0) : filter.get_dim(1),
107 "bias dimension must be equal to output channel number");
109 ideep::convolution_transpose_forward::compute(
110 X, pre_converted ? filter : filter_, bias, Y_dims, *Y, stride_, pad_tl(), pad_br());
112 ideep::convolution_transpose_forward::compute(
113 X, pre_converted ? filter : filter_, Y_dims, *Y, stride_, pad_tl(), pad_br());
119 INPUT_TAGS(INPUT, FILTER, BIAS);
122 const bool training_mode_;
123 ideep::tensor filter_;
124 ideep::tensor::descriptor cached_weights_descriptor_;
133 USE_IDEEP_DEF_ALIASES();
134 USE_IDEEP_CONV_TRANSPOSE_UNPOOL_BASE_FUNCTIONS();
141 no_bias_(OperatorBase::GetSingleArgument<int>(
"no_bias",
false)),
142 fallback_(operator_def, ws) {
143 OPERATOR_NEEDS_FEATURE(
144 pad_l() == pad_r() && pad_t() == pad_b(),
145 "Uneven padding not supported.");
147 !(no_bias_ && OutputSize() == 3),
148 "If bias is not present, you should not have 3 grad output.");
150 OperatorBase::GetSingleArgument<int>(
"training_mode", 0),
151 "In order to backward propagate weights correctly, " 152 "please set training_mode=1");
156 bool RunOnDeviceWithOrderNCHW()
override {
157 const auto& X = Input(INPUT);
158 const auto& filter = Input(FILTER);
159 const auto& dY = Input(OUTPUT_GRAD);
160 auto* dfilter = Output(FILTER_GRAD);
164 auto filter_in = filter;
166 itensor::dims oihw_dims {filter.get_dim(1), filter.get_dim(0),
167 filter.get_dim(2), filter.get_dim(3)};
168 const bool pre_converted = (filter.get_public_format() == ideep::format::iohw);
169 if (!pre_converted) {
170 auto expected_descriptor =
171 ideep::convolution_transpose_forward::expected_weights_descriptor(
173 filter.get_data_type(),
179 filter_in.set_public_format(ideep::format::iohw);
180 filter_.init(expected_descriptor);
181 ideep::reorder::compute(filter_in, filter_);
185 if (((filter_in.get_dim(0) % 8 != 0) && (stride_[0] * stride_[1] != 1)) ||
186 need_type_zero_pad(filter_.get_mkldnn_memory_desc_t())) {
187 return fallback_.Run(0);
192 if (((filter_in.get_dim(0) % 8 != 0) && (stride_[0] * stride_[1] != 1)) ||
193 need_type_zero_pad(filter.get_mkldnn_memory_desc_t())) {
194 return fallback_.Run(0);
199 ideep::convolution_transpose_backward_weights::compute(
200 X, dY, pre_converted ? filter.get_dims() : oihw_dims,
201 pre_converted ? *dfilter : dfilter_, stride_, pad_tl(), pad_br());
203 auto* dbias = Output(BIAS_OR_INPUT_GRAD);
204 ideep::convolution_transpose_backward_weights::compute(
207 pre_converted ? filter.get_dims() : oihw_dims,
208 pre_converted ? *dfilter : dfilter_,
215 if (!pre_converted) {
218 dfilter_.set_public_format(ideep::format::iohw);
219 dfilter->reinit(filter.get_descriptor());
220 dfilter_.to_public(dfilter->get_data_handle());
222 dfilter->set_public_format(ideep::format::iohw);
225 if (OutputSize() == 3 || (no_bias_ && (OutputSize() == 2))) {
226 auto* dX = Output(no_bias_ ? BIAS_OR_INPUT_GRAD : INPUT_GRAD);
227 ideep::convolution_transpose_backward_data::compute(
228 dY, pre_converted ? filter : filter_, X.get_dims(), *dX, stride_, pad_tl(), pad_br());
240 INPUT_TAGS(INPUT, FILTER, OUTPUT_GRAD);
241 OUTPUT_TAGS(FILTER_GRAD, BIAS_OR_INPUT_GRAD, INPUT_GRAD);
Workspace is a class that holds all the related objects created during runtime: (1) all blobs...
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...
A templated class to allow one to wrap a CPU operator as an IDEEP operator.