in src/operator/mkl/mkl_convolution-inl.h [335:451]
virtual void Backward(const OpContext &ctx,
const std::vector<TBlob> &out_grad,
const std::vector<TBlob> &in_data,
const std::vector<TBlob> &out_data,
const std::vector<OpReqType> &req,
const std::vector<TBlob> &in_grad,
const std::vector<TBlob> &aux_args) {
using namespace mshadow;
if (param_.kernel.ndim() > 2) {
LOG(FATAL) << "Volume convolution is not implmented in mshadow";
}
CHECK_EQ(out_grad.size(), 1);
size_t expected = param_.no_bias == 0 ? 3 : 2;
CHECK(in_data.size() == expected && in_grad.size() == expected);
CHECK_EQ(req.size(), expected);
CHECK_EQ(in_data[conv::kWeight].CheckContiguous(), true);
Stream<xpu> *s = ctx.get_stream<xpu>();
Tensor<xpu, 4, DType> data =
mkl_experimental_direct_get<xpu, 4, DType>(in_data[conv::kData], s);
Shape<3> wmat_shape =
Shape3(param_.num_group,
param_.num_filter / param_.num_group,
data.shape_[1] / param_.num_group * param_.kernel[0] * param_.kernel[1]);
Tensor<xpu, 3, DType> wmat =
mkl_experimental_direct_get_with_shape<xpu, 3, DType>(
in_data[conv::kWeight], wmat_shape, s);
Tensor<xpu, 4, DType> grad =
mkl_experimental_direct_get<xpu, 4, DType>(out_grad[conv::kOut], s);
Tensor<xpu, 4, DType> gdata =
mkl_experimental_direct_get<xpu, 4, DType>(in_grad[conv::kData], s);
Tensor<xpu, 3, DType> gwmat =
mkl_experimental_direct_get_with_shape<xpu, 3, DType>(
in_grad[conv::kWeight], wmat_shape, s);
if (!init_mkldnn_) {
init_mkldnn_ = true;
LayerSetUp(data, grad);
}
int status;
if (req[0]) {
void *res_convolutionBwdData[dnnResourceNumber];
res_convolutionBwdData[dnnResourceDiffDst] =
bwdd_top_diff->get_converted_prv(grad.dptr_, true, out_grad[conv::kOut]);
res_convolutionBwdData[dnnResourceFilter] =
bwdd_filter_data->get_converted_prv(wmat.dptr_, false, in_data[conv::kWeight]);
Storage::Handle addtoWorkspace;
if (req[0] == kAddTo) {
// wait mkl support addto mode
AddToModeAllocAndStoreBuffer(gdata.dptr_, in_grad[conv::kData].Size(), &addtoWorkspace);
}
res_convolutionBwdData[dnnResourceDiffSrc] = bwdd_bottom_diff->get_output_ptr(gdata.dptr_,
bwdd_bottom_diff, in_grad[conv::kData]);
status = dnnExecute<DType>(convolutionBwdData, res_convolutionBwdData);
CHECK_EQ(status, 0) << "Backward Data conv failed with status " << status;
#if MKL_EXPERIMENTAL == 0
if (bwdd_bottom_diff->conversion_needed()) {
bwdd_bottom_diff->convert_from_prv(gdata.dptr_);
}
#endif
if (req[0] == kAddTo) {
if (bwdd_bottom_diff->conversion_needed()) {
bwdd_bottom_diff->convert_from_prv(gdata.dptr_);
}
AddToModeAddAndReleaseBuffer(&addtoWorkspace, gdata.dptr_, in_grad[conv::kData].Size());
}
}
if (req[1]) {
void *res_convolutionBwdFilter[dnnResourceNumber];
res_convolutionBwdFilter[dnnResourceDiffDst] =
bwdf_top_diff->get_converted_prv(grad.dptr_, true, out_grad[conv::kOut]);
res_convolutionBwdFilter[dnnResourceSrc] =
bwdf_bottom_data->get_converted_prv(data.dptr_, false,
in_data[conv::kData]);
Storage::Handle addtoWorkspace;
if (req[1] == kAddTo) {
// wait mkl support addto mode
AddToModeAllocAndStoreBuffer(gwmat.dptr_, in_grad[conv::kWeight].Size(), &addtoWorkspace);
}
res_convolutionBwdFilter[dnnResourceDiffFilter] = bwdf_filter_diff->get_output_ptr(
gwmat.dptr_, bwdf_filter_diff, in_grad[conv::kWeight]);
status = dnnExecute<DType>(convolutionBwdFilter, res_convolutionBwdFilter);
CHECK_EQ(status, 0) << "Backward Filter conv failed with status " << status;
#if MKL_EXPERIMENTAL == 0
if (bwdf_filter_diff->conversion_needed()) {
bwdf_filter_diff->convert_from_prv(gwmat.dptr_);
}
#endif
if (req[1] == kAddTo) {
if (bwdf_filter_diff->conversion_needed()) {
bwdf_filter_diff->convert_from_prv(gwmat.dptr_);
}
AddToModeAddAndReleaseBuffer(&addtoWorkspace, gwmat.dptr_, in_grad[conv::kWeight].Size());
}
}
if (!param_.no_bias) {
Tensor<xpu, 1, DType> gbias =
mkl_experimental_direct_get<xpu, 1, DType>(in_grad[conv::kBias], s);
void *res_convolutionBwdBias[dnnResourceNumber];
res_convolutionBwdBias[dnnResourceDiffDst] =
bwdb_top_diff->get_converted_prv(grad.dptr_, true, out_grad[conv::kOut]);
res_convolutionBwdBias[dnnResourceDiffBias] = bwdb_bias_diff->get_output_ptr(gbias.dptr_,
bwdb_bias_diff, in_grad[conv::kBias]);
status = dnnExecute<DType>(convolutionBwdBias, res_convolutionBwdBias);
CHECK_EQ(status, 0) << "Backward Bias failed with status " << status;
#if MKL_EXPERIMENTAL == 0
if (bwdb_bias_diff->conversion_needed()) {
bwdb_bias_diff->convert_from_prv(gbias.dptr_);
}
#endif
}
}