| | |
| | | |
| | | int convolutional_out_height(convolutional_layer l) |
| | | { |
| | | int h = l.h; |
| | | if (!l.pad) h -= l.size; |
| | | else h -= 1; |
| | | return h/l.stride + 1; |
| | | return (l.h + 2*l.pad - l.size) / l.stride + 1; |
| | | } |
| | | |
| | | int convolutional_out_width(convolutional_layer l) |
| | | { |
| | | int w = l.w; |
| | | if (!l.pad) w -= l.size; |
| | | else w -= 1; |
| | | return w/l.stride + 1; |
| | | return (l.w + 2*l.pad - l.size) / l.stride + 1; |
| | | } |
| | | |
| | | image get_convolutional_image(convolutional_layer l) |
| | |
| | | |
| | | size_t get_workspace_size(layer l){ |
| | | #ifdef CUDNN |
| | | size_t most = 0; |
| | | size_t s = 0; |
| | | cudnnGetConvolutionForwardWorkspaceSize(cudnn_handle(), |
| | | l.srcTensorDesc, |
| | | l.filterDesc, |
| | | l.convDesc, |
| | | l.dstTensorDesc, |
| | | l.fw_algo, |
| | | &s); |
| | | if (s > most) most = s; |
| | | cudnnGetConvolutionBackwardFilterWorkspaceSize(cudnn_handle(), |
| | | l.srcTensorDesc, |
| | | l.ddstTensorDesc, |
| | | l.convDesc, |
| | | l.dfilterDesc, |
| | | l.bf_algo, |
| | | &s); |
| | | if (s > most) most = s; |
| | | cudnnGetConvolutionBackwardDataWorkspaceSize(cudnn_handle(), |
| | | l.filterDesc, |
| | | l.ddstTensorDesc, |
| | | l.convDesc, |
| | | l.dsrcTensorDesc, |
| | | l.bd_algo, |
| | | &s); |
| | | if (s > most) most = s; |
| | | return most; |
| | | #else |
| | | if(gpu_index >= 0){ |
| | | size_t most = 0; |
| | | size_t s = 0; |
| | | cudnnGetConvolutionForwardWorkspaceSize(cudnn_handle(), |
| | | l.srcTensorDesc, |
| | | l.filterDesc, |
| | | l.convDesc, |
| | | l.dstTensorDesc, |
| | | l.fw_algo, |
| | | &s); |
| | | if (s > most) most = s; |
| | | cudnnGetConvolutionBackwardFilterWorkspaceSize(cudnn_handle(), |
| | | l.srcTensorDesc, |
| | | l.ddstTensorDesc, |
| | | l.convDesc, |
| | | l.dfilterDesc, |
| | | l.bf_algo, |
| | | &s); |
| | | if (s > most) most = s; |
| | | cudnnGetConvolutionBackwardDataWorkspaceSize(cudnn_handle(), |
| | | l.filterDesc, |
| | | l.ddstTensorDesc, |
| | | l.convDesc, |
| | | l.dsrcTensorDesc, |
| | | l.bd_algo, |
| | | &s); |
| | | if (s > most) most = s; |
| | | return most; |
| | | } |
| | | #endif |
| | | return (size_t)l.out_h*l.out_w*l.size*l.size*l.c*sizeof(float); |
| | | #endif |
| | | } |
| | | |
| | | #ifdef GPU |
| | |
| | | cudnnSetTensor4dDescriptor(l->srcTensorDesc, CUDNN_TENSOR_NCHW, CUDNN_DATA_FLOAT, l->batch, l->c, l->h, l->w); |
| | | cudnnSetTensor4dDescriptor(l->dstTensorDesc, CUDNN_TENSOR_NCHW, CUDNN_DATA_FLOAT, l->batch, l->out_c, l->out_h, l->out_w); |
| | | cudnnSetFilter4dDescriptor(l->filterDesc, CUDNN_DATA_FLOAT, CUDNN_TENSOR_NCHW, l->n, l->c, l->size, l->size); |
| | | int padding = l->pad ? l->size/2 : 0; |
| | | cudnnSetConvolution2dDescriptor(l->convDesc, padding, padding, l->stride, l->stride, 1, 1, CUDNN_CROSS_CORRELATION); |
| | | cudnnSetConvolution2dDescriptor(l->convDesc, l->pad, l->pad, l->stride, l->stride, 1, 1, CUDNN_CROSS_CORRELATION); |
| | | cudnnGetConvolutionForwardAlgorithm(cudnn_handle(), |
| | | l->srcTensorDesc, |
| | | l->filterDesc, |
| | |
| | | #endif |
| | | #endif |
| | | |
| | | convolutional_layer make_convolutional_layer(int batch, int h, int w, int c, int n, int size, int stride, int pad, ACTIVATION activation, int batch_normalize, int binary, int xnor) |
| | | convolutional_layer make_convolutional_layer(int batch, int h, int w, int c, int n, int size, int stride, int padding, ACTIVATION activation, int batch_normalize, int binary, int xnor) |
| | | { |
| | | int i; |
| | | convolutional_layer l = {0}; |
| | |
| | | l.batch = batch; |
| | | l.stride = stride; |
| | | l.size = size; |
| | | l.pad = pad; |
| | | l.pad = padding; |
| | | l.batch_normalize = batch_normalize; |
| | | |
| | | l.filters = calloc(c*n*size*size, sizeof(float)); |
| | |
| | | } |
| | | |
| | | #ifdef GPU |
| | | l.filters_gpu = cuda_make_array(l.filters, c*n*size*size); |
| | | l.filter_updates_gpu = cuda_make_array(l.filter_updates, c*n*size*size); |
| | | if(gpu_index >= 0){ |
| | | l.filters_gpu = cuda_make_array(l.filters, c*n*size*size); |
| | | l.filter_updates_gpu = cuda_make_array(l.filter_updates, c*n*size*size); |
| | | |
| | | l.biases_gpu = cuda_make_array(l.biases, n); |
| | | l.bias_updates_gpu = cuda_make_array(l.bias_updates, n); |
| | | l.biases_gpu = cuda_make_array(l.biases, n); |
| | | l.bias_updates_gpu = cuda_make_array(l.bias_updates, n); |
| | | |
| | | l.scales_gpu = cuda_make_array(l.scales, n); |
| | | l.scale_updates_gpu = cuda_make_array(l.scale_updates, n); |
| | | l.scales_gpu = cuda_make_array(l.scales, n); |
| | | l.scale_updates_gpu = cuda_make_array(l.scale_updates, n); |
| | | |
| | | l.delta_gpu = cuda_make_array(l.delta, l.batch*out_h*out_w*n); |
| | | l.output_gpu = cuda_make_array(l.output, l.batch*out_h*out_w*n); |
| | | l.delta_gpu = cuda_make_array(l.delta, l.batch*out_h*out_w*n); |
| | | l.output_gpu = cuda_make_array(l.output, l.batch*out_h*out_w*n); |
| | | |
| | | if(binary){ |
| | | l.binary_filters_gpu = cuda_make_array(l.filters, c*n*size*size); |
| | | } |
| | | if(xnor){ |
| | | l.binary_filters_gpu = cuda_make_array(l.filters, c*n*size*size); |
| | | l.binary_input_gpu = cuda_make_array(0, l.inputs*l.batch); |
| | | } |
| | | if(binary){ |
| | | l.binary_filters_gpu = cuda_make_array(l.filters, c*n*size*size); |
| | | } |
| | | if(xnor){ |
| | | l.binary_filters_gpu = cuda_make_array(l.filters, c*n*size*size); |
| | | l.binary_input_gpu = cuda_make_array(0, l.inputs*l.batch); |
| | | } |
| | | |
| | | if(batch_normalize){ |
| | | l.mean_gpu = cuda_make_array(l.mean, n); |
| | | l.variance_gpu = cuda_make_array(l.variance, n); |
| | | if(batch_normalize){ |
| | | l.mean_gpu = cuda_make_array(l.mean, n); |
| | | l.variance_gpu = cuda_make_array(l.variance, n); |
| | | |
| | | l.rolling_mean_gpu = cuda_make_array(l.mean, n); |
| | | l.rolling_variance_gpu = cuda_make_array(l.variance, n); |
| | | l.rolling_mean_gpu = cuda_make_array(l.mean, n); |
| | | l.rolling_variance_gpu = cuda_make_array(l.variance, n); |
| | | |
| | | l.mean_delta_gpu = cuda_make_array(l.mean, n); |
| | | l.variance_delta_gpu = cuda_make_array(l.variance, n); |
| | | l.mean_delta_gpu = cuda_make_array(l.mean, n); |
| | | l.variance_delta_gpu = cuda_make_array(l.variance, n); |
| | | |
| | | l.x_gpu = cuda_make_array(l.output, l.batch*out_h*out_w*n); |
| | | l.x_norm_gpu = cuda_make_array(l.output, l.batch*out_h*out_w*n); |
| | | } |
| | | l.x_gpu = cuda_make_array(l.output, l.batch*out_h*out_w*n); |
| | | l.x_norm_gpu = cuda_make_array(l.output, l.batch*out_h*out_w*n); |
| | | } |
| | | #ifdef CUDNN |
| | | cudnnCreateTensorDescriptor(&l.srcTensorDesc); |
| | | cudnnCreateTensorDescriptor(&l.dstTensorDesc); |
| | | cudnnCreateFilterDescriptor(&l.filterDesc); |
| | | cudnnCreateTensorDescriptor(&l.dsrcTensorDesc); |
| | | cudnnCreateTensorDescriptor(&l.ddstTensorDesc); |
| | | cudnnCreateFilterDescriptor(&l.dfilterDesc); |
| | | cudnnCreateConvolutionDescriptor(&l.convDesc); |
| | | cudnn_convolutional_setup(&l); |
| | | cudnnCreateTensorDescriptor(&l.srcTensorDesc); |
| | | cudnnCreateTensorDescriptor(&l.dstTensorDesc); |
| | | cudnnCreateFilterDescriptor(&l.filterDesc); |
| | | cudnnCreateTensorDescriptor(&l.dsrcTensorDesc); |
| | | cudnnCreateTensorDescriptor(&l.ddstTensorDesc); |
| | | cudnnCreateFilterDescriptor(&l.dfilterDesc); |
| | | cudnnCreateConvolutionDescriptor(&l.convDesc); |
| | | cudnn_convolutional_setup(&l); |
| | | #endif |
| | | } |
| | | #endif |
| | | l.workspace_size = get_workspace_size(l); |
| | | l.activation = activation; |