| 72 | |
| 73 | template <typename T, typename Context> |
| 74 | void BatchNormGradKernel(const Context &dev_ctx, |
| 75 | const DenseTensor &x, |
| 76 | const optional<DenseTensor> &scale, |
| 77 | const optional<DenseTensor> &bias, |
| 78 | const optional<DenseTensor> &mean, |
| 79 | const optional<DenseTensor> &variance, |
| 80 | const DenseTensor &saved_mean, |
| 81 | const DenseTensor &saved_variance, |
| 82 | const optional<DenseTensor> &reserve_space, |
| 83 | const DenseTensor &y_grad, |
| 84 | float momentum, |
| 85 | float epsilon, |
| 86 | const std::string &data_layout, |
| 87 | bool is_test, |
| 88 | bool use_global_stats, |
| 89 | bool trainable_statistics, |
| 90 | DenseTensor *x_grad, |
| 91 | DenseTensor *scale_grad, |
| 92 | DenseTensor *bias_grad) { |
| 93 | if (x.numel() == 0) { |
| 94 | dev_ctx.template Alloc<T>(x_grad); |
| 95 | if (scale_grad) |
| 96 | Full<T, Context>(dev_ctx, scale_grad->dims(), 0, scale_grad); |
| 97 | if (bias_grad) Full<T, Context>(dev_ctx, bias_grad->dims(), 0, bias_grad); |
| 98 | return; |
| 99 | } |
| 100 | using XPUType = typename XPUTypeTrait<T>::Type; |
| 101 | const auto *d_y = &y_grad; |
| 102 | PADDLE_ENFORCE_EQ(data_layout == "NCHW" || data_layout == "NHWC", |
| 103 | true, |
| 104 | common::errors::InvalidArgument( |
| 105 | "The 'data_layout' attribute must be NCHW or NHWC. " |
| 106 | "But received 'data_layout' is [%s].", |
| 107 | data_layout)); |
| 108 | |
| 109 | const auto data_layout_val = StringToDataLayout(data_layout); |
| 110 | |
| 111 | use_global_stats = is_test || use_global_stats; |
| 112 | |
| 113 | // batch_norm with inplace as false will take X as grad input, which |
| 114 | // is same as cuDNN batch_norm backward calculation, batch_norm |
| 115 | // with inplace as true only take Y as input and X should be calculate |
| 116 | // by inverse operation of batch_norm on Y |
| 117 | bool is_inplace = false; |
| 118 | if (x_grad) { |
| 119 | PADDLE_ENFORCE_NE(x_grad, |
| 120 | d_y, |
| 121 | common::errors::InvalidArgument( |
| 122 | "X@GRAD and Y@GRAD inplaced in non-inplace mode")); |
| 123 | } |
| 124 | |
| 125 | const auto &x_dims = x.dims(); |
| 126 | PADDLE_ENFORCE_EQ( |
| 127 | x_dims.size() >= 2 && x_dims.size() <= 5, |
| 128 | true, |
| 129 | common::errors::InvalidArgument( |
| 130 | "The size of input's dimensions should be between 2 and 5. " |
| 131 | "But received: the size of input's dimensions is [%d]", |
nothing calls this directly
no test coverage detected