virtual void Backward()

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
    }
  }