栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

cublas cudnn优化笔记

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

cublas cudnn优化笔记

文章目录

前言cublas 常用API

数据格式cublasGemmEx & cublasLtMatmul cuDNN 常用API

cudnnConvolutionForward


前言

cublas。
官方指南:https://docs.nvidia.com/cuda/cublas/
头文件 cublas_v2.h
官方例子:https://github.com/NVIDIA/CUDALibrarySamples/

cuDNN。
cuDNN官方指南:https://docs.nvidia.com/deeplearning/cudnn/developer-guide/index.html
入门例子:http://www.goldsborough.me/cuda/ml/cudnn/c++/2017/10/01/14-37-23-convolutions_with_cudnn/ (API已过时,看个思路就好)


cublas 常用API 数据格式

cuBLAS library uses column-major storage, and 1-based indexing.
c++ 对接cublas需要把二维数组转置。一般c++的矩阵都是 0-based indexing,也就是row-major storage。可以用Sgeam的api,m * n 的矩阵,转置。

cublasSgeam(cublas_handle, CUBLAS_OP_T, CUBLAS_OP_N, m, n, &alpha, in_addr, n, &beta, out_addr, m, out_addr, m)

但是,如果后面的操作带cublasOperation_t的对输入的操作的话,不用单独先转置。
比如,可以直接调用matmul:

const int lda = k;
const int ldb = n;
const int ldc = m;
cublasGemmEx(cublas_handle, CUBLAS_OP_T, CUBLAS_OP_T, m, n, k, &alpha, a_addr, type_a, lda, b_addr, type_b, ldb, &beta, c_addr, type_c, ldc, type_compute, CUBLAS_GEMM_DEFAULT_TENSOR_OP))
cublasGemmEx & cublasLtMatmul

测下来什么都默认的情况,这俩性能差不错,所以用简单的cublasGemmEx。输入是fp32的数据,cublasComputeType_t 设置为CUBLAS_COMPUTE_32F_FAST_16F有将近50%的性能提升,精度差别也只是从0.01%降到0.1%。alpha和beta的数据类型需要跟input一样。CublasGemmAlgo_t 用 CUBLAS_GEMM_DEFAULT_TENSOR_OP。


cuDNN 常用API cudnnConvolutionForward

cudnnConvolutionForward API

构图阶段可以做的一次性操作

// kernel_descriptor_ 和convolution_descriptor_ 可以重复使用,对于动态batchsize的算子,这俩永远固定的
CUDNN_CHECK(cudnnCreateFilterDescriptor(&kernel_descriptor_));
CUDNN_CHECK(cudnnSetFilter4dDescriptor(kernel_descriptor_, CUDNN_DATA_FLOAT, CUDNN_TENSOR_NHWC, n, k, h, w));

CUDNN_CHECK(cudnnCreateConvolutionDescriptor(&convolution_descriptor_));
CUDNN_CHECK(cudnnSetConvolution2dDescriptor(convolution_descriptor_, pad_h, pad_w, u, v, dilation_h, dilation_w, CUDNN_CONVOLUTION, CUDNN_DATA_FLOAT));

runtime的操作

// 因为动态batchsize,只有runtime才能知道具体的dim信息,需要重新set descriptor
cudnnTensorDescriptor_t runtime_input_descriptor{nullptr};
cudnnTensorDescriptor_t runtime_output_descriptor{nullptr};
CUDNN_CHECK(cudnnCreateTensorDescriptor(&runtime_input_descriptor));
CUDNN_CHECK(cudnnCreateTensorDescriptor(&runtime_output_descriptor));
CUDNN_CHECK(
  cudnnSetTensor4dDescriptor(runtime_input_descriptor, CUDNN_TENSOR_NHWC, CUDNN_DATA_FLOAT, n, c, h, w));
CUDNN_CHECK(
  cudnnSetTensor4dDescriptor(runtime_output_descriptor, CUDNN_TENSOR_NHWC, CUDNN_DATA_FLOAT, n, c, h, w));
int returned_algo_count = 0;
// 1是因为只取最优的算法即可
CUDNN_CHECK(cudnnGetConvolutionForwardAlgorithm_v7(cudnn_handle_, runtime_input_descriptor, kernel_descriptor_,
                                                   convolution_descriptor_, runtime_output_descriptor, 1,
                                                   &returned_algo_count, cudnn_algos_));
// cudnn_algos_[0].memory 最优算法需要的workspace
// cudnn_algos_[0].alog 最优算法


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/744463.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号