| 286 | #ifdef WITH_CUDNN |
| 287 | template<typename T> |
| 288 | Array<T> data_gradient_cudnn(const Array<T> &incoming_gradient, |
| 289 | const Array<T> &original_signal, |
| 290 | const Array<T> &original_filter, |
| 291 | const Array<T> &convolved_output, af::dim4 stride, |
| 292 | af::dim4 padding, af::dim4 dilation) { |
| 293 | UNUSED(convolved_output); |
| 294 | auto cudnn = nnHandle(); |
| 295 | |
| 296 | dim4 sDims = original_signal.dims(); |
| 297 | dim4 fDims = original_filter.dims(); |
| 298 | |
| 299 | cudnnDataType_t cudnn_dtype = getCudnnDataType<T>(); |
| 300 | |
| 301 | // create x descriptor |
| 302 | auto dx_descriptor = toCudnn<cudnnTensorDescriptor_t>(original_signal); |
| 303 | auto dy_descriptor = toCudnn<cudnnTensorDescriptor_t>(incoming_gradient); |
| 304 | |
| 305 | // create output filter gradient descriptor |
| 306 | auto w_descriptor = make_handle<cudnnFilterDescriptor_t>(); |
| 307 | |
| 308 | CUDNN_CHECK(cuda::cudnnSetFilter4dDescriptor(w_descriptor, cudnn_dtype, |
| 309 | CUDNN_TENSOR_NCHW, fDims[3], |
| 310 | fDims[2], fDims[1], fDims[0])); |
| 311 | |
| 312 | // create convolution descriptor |
| 313 | auto convolution_descriptor = make_handle<cudnnConvolutionDescriptor_t>(); |
| 314 | |
| 315 | CUDNN_CHECK(cuda::cudnnSetConvolution2dDescriptor( |
| 316 | convolution_descriptor, padding[1], padding[0], stride[1], stride[0], |
| 317 | dilation[1], dilation[0], CUDNN_CONVOLUTION, cudnn_dtype)); |
| 318 | |
| 319 | cudnnConvolutionBwdDataAlgo_t bwd_data_convolution_algorithm; |
| 320 | if ((dilation[0] == 1 && dilation[1] == 1) || is_same<T, half>::value) { |
| 321 | bwd_data_convolution_algorithm = CUDNN_CONVOLUTION_BWD_DATA_ALGO_1; |
| 322 | } else { |
| 323 | bwd_data_convolution_algorithm = CUDNN_CONVOLUTION_BWD_DATA_ALGO_0; |
| 324 | } |
| 325 | |
| 326 | // figure out scratch space memory requirements |
| 327 | size_t workspace_bytes; |
| 328 | CUDNN_CHECK(cuda::cudnnGetConvolutionBackwardDataWorkspaceSize( |
| 329 | cudnn, w_descriptor, dy_descriptor, convolution_descriptor, |
| 330 | dx_descriptor, bwd_data_convolution_algorithm, &workspace_bytes)); |
| 331 | |
| 332 | dim4 odims(sDims[0], sDims[1], sDims[2], sDims[3]); |
| 333 | Array<T> out = createEmptyArray<T>(odims); |
| 334 | |
| 335 | auto workspace_buffer = memAlloc<char>(workspace_bytes); |
| 336 | |
| 337 | // perform convolution |
| 338 | auto alpha = scalar<scale_type<T>>(1.0); |
| 339 | auto beta = scalar<scale_type<T>>(0.0); |
| 340 | |
| 341 | CUDNN_CHECK(cuda::cudnnConvolutionBackwardData( |
| 342 | cudnn, &alpha, w_descriptor, original_filter.get(), dy_descriptor, |
| 343 | incoming_gradient.get(), convolution_descriptor, |
| 344 | bwd_data_convolution_algorithm, (void *)workspace_buffer.get(), |
| 345 | workspace_bytes, &beta, dx_descriptor, out.device())); |
nothing calls this directly
no test coverage detected