CUDA与TensorRT(4)之cuBLAS&cuDNN

1. cuBLAS

cuBLAS背景:是一个BLAS在cuda中的实现,允许用户使用NVIDIA的GPU的计算资源。使用cuBLAS 的时候,应用程序应该分配矩阵或向量所需的GPU内存空间,并加载数据,调用所需的cuBLAS函数,然后从GPU的内存空间上传计算结果至主机,cuBLAS API也提供一些帮助函数来写或者读取数据从GPU中。

(1)基本特点
  • 列优先的数组,索引以1为基准
  • 头文件 include “cublas_v2.h”
  • 三类函数(向量标量、向量矩阵、矩阵矩阵)
  • 官方学习网站:cublas
(2)cuBLAS实现矩阵乘法
  • 准备矩阵A、B、C及其内存,以及使用的线程块及网格
  • 创建句柄:cublasHandle_t handle; cublasCreate(&handle)
  • 调用计算函数:cublasSgemm(handle, CUBLAS_OP_N, CUBLAS_OP_N, m, n, k, &alpha, *B, n, *A, k, &beta, *C, n);
  • 销毁句柄:cublasDestroy(handle);
  • 回收计算结果:(顺序可以和销毁句柄交换)

cuBLAS 辅助函数

• 句柄管理函数cublasCreate( ), cublasDestroy( )

• cublasStatus_t cublasCreate(cublasHandle_t *handle)

• cublasStatus_t cublasDestroy(cublasHandle_t handle)

• 初始化CUBLAS库,并为保存CUBLAS库上下文创建一个句柄。 它在主机和设备上分配硬件资源,并且
在进行任何其他CUBLAS库调用时必须使用它。 CUBLAS库上下文绑定到当前CUDA设备。要在多个设
备上使用该库, 需要为每个设备创建一个CUBLAS句柄。

• 创建句柄的函数 cublasCreate( ) 会返回一个 cublasStatus_t 类型的值,用来判断句柄是否创建成功

• 流管理函数cublasSetStream(), cublasGetStream()

• cublasStatus_t cublasSetStream(cublasHandle_t handle, cudaStream_t streamId)

• cublasStatus_t cublasGetStream(cublasHandle_t handle, cudaStream_t *streamId)

(3)Cublas level1函数:标量

• cublasStatus_t cublasIsamax(cublasHandle_t handle, int n, const float *x, int incx, int *result)

• cublasStatus_t cublasIsamin(cublasHandle_t handle, int n, const float *x, int incx, int *result)

• 实现功能: result = max/min( x )

• 参数意义

• Incx:x的存储间隔(如果是行存储,值就是行数,如果是列存储,那就是1)

(4)Cublas level2函数:矩阵向量

cublasStatus_t cublasSgemv(cublasHandle_t handle, cublasOperation_t trans, int m, int n, const float *alpha, const float *A, int lda, const float *x, int incx, const float *beta, float *y, int incy)

• 实现功能: y = alpha * op ( A ) * x + beta * y

• 参数意义

• Lda:A的leading dimension,若转置按行优先,则leading dimension为A的列数

• Incx/incy:x/y的存储间隔

(5)Cublas level3函数:矩阵矩阵

cublasStatus_t cublasSgemm(cublasHandle_t handle, cublasOperation_t transa, cublasOperation_t transb, int m, int n, int k,const float *alpha, const float *A, int lda, const float *B, int ldb, const float beta, floatC, int ldc)

• 实现功能: C = alpha * op ( A ) * op ( B ) + beta * C

• 参数意义

• alpha和beta是标量, A B C是以列优先存储的矩阵

• 如果 transa的参数是CUBLAS_OP_N 则op(A) = A ,如果是CUBLAS_OP_T 则op(A)=A的转置

• 如果 transb的参数是CUBLAS_OP_N 则op(B) = B ,如果是CUBLAS_OP_T 则op(B)=B的转置

• Lda/Ldb:A/B的leading dimension,若转置按行优先,则leading dimension为A/B的列数

• Ldc:C的leading dimension,C矩阵一定按列优先,则leading dimension为C的行数

具体的代码实现

float *d_A, *d_B, *d_C;
unsigned int size_C = ms.wc * ms.hc;
unsigned int mem_size_C = sizeof(float) * size_C;
float *h_CUBLAS = (float *) malloc(mem_size_C);
cudaMalloc((void **) &d_A, mem_size_A);
cudaMalloc((void **) &d_B, mem_size_B);
cudaMemcpy(d_A, h_A, mem_size_A, cudaMemcpyHostToDevice);
cudaMemcpy(d_B, h_B, mem_size_B, cudaMemcpyHostToDevice);
cudaMalloc((void **) &d_C, mem_size_C);
dim3 threads(1,1);
dim3 grid(1,1);

//cuBLAS代码(具体可以看实现代码)
const float alpha = 1.0f;
const float beta = 0.0f;
int m = A.row, n = B.col, k = A.col;
cublasHandle_t handle;
cublasCreate(&handle);
cublasSgemm(handle, CUBLAS_OP_N, CUBLAS_OP_N, n, m, k, &alpha, d_B, n, 
d_A, k, &beta, d_C, n);//C=AB->C_T=B_T*A_T
cublasDestroy(handle);
cudaMemcpy(h_CUBLAS, d_C, mem_size_C, cudaMemcpyDeviceToHost);
(6)其他矩阵计算相关函数

cublasStatus_t cublasSgemmBatched(cublasHandle_t handle, cublasOperation_t transa, cublasOperation_t transb, int m, int n, int k,const float alpha, const floatAarray[], int lda, const float *Barray[], int ldb, const float beta,floatCarray[], int ldc,int batchCount)

• 实现功能: C[i] = alpha * op ( A[i] ) * op ( B[i] ) + beta * C[i]

• 参数意义

• Lda/Ldb:A/B的leading dimension,若转置按行优先,则leading dimension为A/B的列数

• Ldc:C的leading dimension,C矩阵一定按列优先,则leading dimension为C的行数

• Batchcount:批处理数量


cublasStatus_t cublasSgemmStridedBatched(cublasHandle_t handle,cublasOperation_t transa, cublasOperation_t transb,int m, int n, int k,const float *alpha, const float *A, int lda, long long int strideA,const float *B, int ldb, long long int strideB, const float *beta,float *C, int ldc, long long int strideC,int batchCount)

• 实现功能: C +istrideC= alpha * op ( A+istrideA) * op ( B +istrideB) + beta * (C +istrideC)

• 参数意义

• alpha和beta是标量, A B C是以列优先存储的矩阵

• 如果 transa的参数是CUBLAS_OP_N 则op(A) = A ,如果是CUBLAS_OP_T 则op(A)=A的转置

• 如果 transb的参数是CUBLAS_OP_N 则op(B) = B ,如果是CUBLAS_OP_T 则op(B)=B的转置


cublasStatus_t cublasGemmEx(cublasHandle_t handle, cublasOperation_t transa, cublasOperation_t transb,
int m, int n, int k, const void *alpha, const void *A, cudaDataType_t Atype, int lda, const void *B, cudaDataType_t Btype, int ldb, const void *beta, void *C, cudaDataType_t Ctype, int ldc, cudaDataType_t computeType,
cublasGemmAlgo_t algo)

• 实现功能: C = alpha * op ( A ) * op ( B ) + beta * C

• 参数意义

• alpha和beta是标量, A B C是以列优先存储的矩阵

• 如果 transa的参数是CUBLAS_OP_N 则op(A) = A ,如果是CUBLAS_OP_T 则op(A)=A的转置

• 如果 transb的参数是CUBLAS_OP_N 则op(B) = B ,如果是CUBLAS_OP_T 则op(B)=B的转置


1.cuDNN

NVIDIA cuDNN是用于深度神经网络的GPU加速库。它强调性能、易用性和低内存开销,NVIDIA cuDNN可以集成到更高级别的机器学习框架中。

常用神经网络组件:

• 常用语前向后向卷积网络

• 前像后向pooling

• 前向后向softmax

• 前向后向神经元激活

• Rectified linear (ReLU)、Hyperbolic tangent (TANH)

• Tensor transformation functions

• LRN, LCN and batch normalization forward and backward

头文件 include "cudnn.h“
学习网站: https://docs.nvidia.com/deeplearning/cudnn/

(1)Cudnn实现卷积神经网络

创建cuDNN句柄
• cudnnStatus_t cudnnCreate(cudnnHandle_t *handle)

以Host方式调用在Device上运行的函数
• 比如卷积运算:cudnnConvolutionForward等

释放cuDNN句柄
• cudnnStatus_t cudnnDestroy(cudnnHandle_t handle)

将CUDA流设置&返回成cudnn句柄
• cudnnStatus_t cudnnSetStream( cudnnHandle_t handle, cudaStream_t streamId)
• cudnnStatus_t cudnnGetStream( cudnnHandle_t handle, cudaStream_t *streamId)

#include <iostream>
#include <cudnn.h>
int main(int argc, const char **argv){
cudnnStatus_t cudnn_re;
cudnnHandle_t h_cudnn;
cudnn_re = cudnnCreate(&h_cudnn);
if(cudnn_re != CUDNN_STATUS_SUCCESS){
std::cout << "创建cuDNN上下文失败!" << std::endl;
}
// =========================================cudnn操作

// 释放cuDNN
cudnnDestroy(h_cudnn);
}

使用的卷积神经网络函数

cudnnStatus_t cudnnConvolutionForward(
		cudnnHandle_t handle,								//
		const void *alpha, 											//  卷积相乘的权重 alpha
		const cudnnTensorDescriptor_t xDesc,//  x的描述
		const void *x,													//  输入张量x
		const cudnnFilterDescriptor_t wDesc,	//  卷积核对应描述
		const void *w,													//  卷积核
		const cudnnConvolutionDescriptor_t convDesc, //  卷积算法对应的描述
		cudnnConvolutionFwdAlgo_t algo,		//  卷积算法
		void *workSpace,											//  工作空间
		size_t workSpaceSizeInBytes,					//  工作空间大小
		const void *beta,											//  原始地址
		const cudnnTensorDescriptor_t yDesc,//输出tensor的描述
		void *y																	//输出结果的tensor张量
)

(2)Cudnn实现卷积神经网络–具体代码流程
void cudnn_conv(){
		cudnnStatus_t status; cudnnHandle_t h_cudnn; cudnnCreate(&h_cudnn);
		cudnnTensorDescriptor_t ts_in, ts_out; // 1. 定义一个张量对象
		status = cudnnCreateTensorDescriptor(&ts_in); // 2. 创建输入张量
		if(CUDNN_STATUS_SUCCESS == status){ std::cout << “创建输入张量成功!<< std::endl; }
		status = cudnnSetTensor4dDescriptor(// 3. 设置输入张量数据
				ts_in, // 张量对象
				CUDNN_TENSOR_NHWC, // 张量的数据布局
				CUDNN_DATA_FLOAT, // 张量的数据类型
				1, // 图像数量
				3, // 图像通道
				1080, // 图像高度
				1920 // 图像宽度);
		if(CUDNN_STATUS_SUCCESS == status) std::cout << "创建输出张量成功!" << std::endl;
		cudnnCreateTensorDescriptor(&ts_out); // 设置输出张量
		
		status = cudnnSetTensor4dDescriptor(ts_out, CUDNN_TENSOR_NHWC, CUDNN_DATA_FLOAT, 1, 3, 1080, 1920);
		cudnnFilterDescriptor_t kernel;
		cudnnCreateFilterDescriptor(&kernel); // 创建卷积核
		
		status = cudnnSetFilter4dDescriptor(kernel, CUDNN_DATA_FLOAT, CUDNN_TENSOR_NHWC, 3, 3, 3, 3);
		cudnnConvolutionDescriptor_t conv; // 创建卷积
		
		status = cudnnCreateConvolutionDescriptor(&conv); // 设置卷积
		
		status = cudnnSetConvolution2dDescriptor(conv, 1, 1, 1, 1, 1, 1, CUDNN_CROSS_CORRELATION, CUDNN_DATA_FLOAT);
		cudnnConvolutionFwdAlgo_t algo;
		status = cudnnGetConvolutionForwardAlgorithm(h_cudnn, ts_in, kernel, conv, ts_out, CUDNN_CONVOLUTION_FWD_PREFER_FASTEST, 0, &algo); // 设置算法
		size_t workspace_size = 0;
		status = cudnnGetConvolutionForwardWorkspaceSize(h_cudnn, ts_in, kernel, conv, ts_out, algo, 
		&workspace_size);
		void * workspace;
		cudaMalloc(&workspace, workspace_size);
		float alpha = 1.0f; float beta = -100.0f;
		status = cudnnConvolutionForward(// 卷积执行
				h_cudnn, &alpha, ts_in,
				img_gpu, // 输入
				kernel, 
				kernel_gpu, // 核
				conv, algo, workspace, workspace_size, &beta,
				ts_out, conv_gpu // 输出
		);
		cudnnDestroy(h_cudnn);
}
(3)Cudnn实现递归神经网络-RNN

在transformer未出来前,主流的三大神经网络为CNN、DNN、RNN
其中DNN可以使用cuBALS进行一个快速的前传,而CNN就是使用上面的方法,接下来就是cudnn实现RNN的前传

(4)Cudnn实现不同激活函数
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值