cuDNN
cuDNN是英伟达提供的闭源库,对CUDA程序进行封装。cuDNN里面的前向传播和后向传播分别是独立的函数,不像利用python那样简单,只要搭建网络框架就好了。这里只介绍如何搭建前向传播模块,也就是载入我们用python程序训练好的参数进行预测。
代码链接 GitHub
cuDNN Operations for VGG16
下面程序是对 cuDNN 里面的卷积操作进行封装。cuDNN 每个 operation 基本都是要进行 descriptor、setdiscriptor、实例化 discriptor、以及内存,最后从 cpu 拷贝 到 gpu 进行底层的矩阵据计算。
void conv_foward_layer(
cudnnHandle_t& handle,
const int& batch_size,
const int& x_channels,
const int& x_height,
const int& x_width,
const void *x,
const int& kernel_size,
const void *kernel,
const void *bias,
const int& padding,
const int& stride,
const int& y_channels,
const int& y_height,
const int& y_width,
const size_t& y_bytes,
void *y,
int activate_type)
{
// 输入张量的描述
cudnnTensorDescriptor_t input_descriptor;
checkCUDNN(cudnnCreateTensorDescriptor(&input_descriptor));
checkCUDNN(cudnnSetTensor4dDescriptor(input_descriptor,
/*format=*/CUDNN_TENSOR_NHWC, // 注意是 NHWC,TensorFlow更喜欢以 NHWC 格式存储张量(通道是变化最频繁的地方,即 BGR),而其他一些更喜欢将通道放在前面
/*dataType=*/CUDNN_DATA_FLOAT,
/*batch_size=*/batch_size,
/*channels=*/x_channels,
/*image_height=*/x_height,
/*image_width=*/x_width));
// 卷积核的描述(形状、格式)
cudnnFilterDescriptor_t kernel_descriptor;
checkCUDNN(cudnnCreateFilterDescriptor(&kernel_descriptor));
checkCUDNN(cudnnSetFilter4dDescriptor(kernel_descriptor,
/*dataType=*/CUDNN_DATA_FLOAT,
/*format=*/CUDNN_TENSOR_NCHW, // 注意是 NCHW
///*format=*/CUDNN_TENSOR_NHWC, // 注意是 NHWC ?????????????
/*out_channels=*/y_channels,
/*in_channels=*/x_channels,
/*kernel_height=*/kernel_size,
/*kernel_width=*/kernel_s