CUBLAS 和 CUDNN

news2024/11/24 10:38:49

文章目录

  • 一、什么是CUBLAS
    • CUBLAS实现矩阵乘法
    • CUBLAS中的Leading Dimension
    • CUBLAS LEVEL3函数 : 矩阵矩阵
    • CUBLAS实现矩阵乘法
  • 二、cuDNN
    • 使用CuDNN实现卷积神经网络
  • 四、CUBLAS和CUDNN实践


一、什么是CUBLAS

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

在使用cuBLAS的时候,cuBLAS使用的是列优先的数组,索引以1为基准。
相关头文件为 “cublas_v2.h”
其包含三类函数(向量标量,向量矩阵,矩阵矩阵)

CUBLAS实现矩阵乘法

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中的Leading Dimension

在CUBLAS中,矩阵可以以行主序(row-major order)或列主序(column-major order)存储。了解leading dimension对于理解CUBLAS函数的参数传递和性能优化至关重要。

对于二维矩阵,leading dimension是矩阵的行数(row-major order)或列数(column-major order)。

列主序(column-major order,也称为Fortran顺序):在这种顺序中,矩阵的列按连续内存地址存储。对于列主序矩阵,leading dimension是矩阵的行数。
例如,对于一个大小为MxN的列主序矩阵A,A(i, j)的内存位置可以通过以下计算得出:

location = i + j * M
其中i表示行索引,j表示列索引(从0开始)。

行主序(row-major order,也称为C顺序):在这种顺序中,矩阵的行按连续内存地址存储。对于行主序矩阵,leading dimension是矩阵的列数。
例如,对于一个大小为MxN的行主序矩阵A,A(i, j)的内存位置可以通过以下计算得出:

location = i * N + j
其中i表示行索引,j表示列索引(从0开始)。

在使用CUBLAS函数时,需要指定leading dimension,以便库可以正确解释矩阵数据。例如,在CUBLAS的cublasDgemm函数中,用于矩阵乘法的参数lda、ldb和ldc分别表示输入矩阵A、B和输出矩阵C的leading dimensions。

在实践中,CUBLAS主要使用列主序(Fortran顺序)存储矩阵。在调用CUBLAS函数时,请确保矩阵以正确的顺序存储,并正确设置leading dimension。

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的行数

CUBLAS实现矩阵乘法

请添加图片描述

CUBLAS实现Batch版本矩阵乘法,如下图,最终结果是 [[c1,c2],[c3,c4]]矩阵请添加图片描述

请添加图片描述

请添加图片描述

二、cuDNN

对于一些比较高级的算子,比如卷积算子,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/

使用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)

除此之外,cudnn还可以很方便地实现RNN,Softmax,Batch Normalization, ReLU, Sigmoid,Layer Normalization等等

四、CUBLAS和CUDNN实践

使用CUBLAS实现矩阵乘法:

#include<bits/stdc++.h>
#include "cublas_v2.h"
#include "cuda_runtime.h"
#include "device_launch_parameters.h" 
using namespace std;
void checkResult(vector<double> h_C,vector<double> h_C_cpu){
  double epsilon = 5;
  bool match = 1;
  for(size_t i = 0;i < h_C.size();i++){
    if(abs(h_C[i] - h_C_cpu[i]) > epsilon){
      match = 0;
      cout<<"Arrays do not match!"<<endl;
      cout<<"h_C["<<i<<"] = "<<h_C[i]<<", h_C_cpu["<<i<<"] = "<<h_C_cpu[i]<<endl;
      break;
    }
  }
  if(match) cout<<"Arrays match."<<endl;
}
vector<double> matrixMulOnHost(vector<double> &A,vector<double> &B,int n){
  vector<double> C(n * n);
  for(size_t i = 0;i < n;i++){
    for(size_t j = 0;j < n;j++){
      double sum = 0;
      for(size_t k = 0;k < n;k++){
        double a = A[i + k * n];
        double b = B[k + n * j];
        sum += a * b;
      }
      C[i + n * j] = sum;
    }
  }
  return C;
}
int main(int argc,char *argv[]){
    int n = atoi(argv[1]);
    vector<double> h_A(n * n);
    vector<double> h_B(n * n);
    for(size_t i = 0;i< n ;i++){
      for(size_t j = 0; j < n ; j++){
      h_A[i + j * n] = static_cast<double>(rand()) / 100;
      h_B[i + j * n] = static_cast<double>(rand()) / 100;
    }
    }

    //Allocate Device Memory for matrix A and B and C 
    double *d_A,*d_B,*d_C; 
    cudaMalloc(&d_A,n * n * sizeof(double));
    cudaMalloc(&d_B,n * n * sizeof(double));
    cudaMalloc(&d_C,n * n * sizeof(double)); 


    
    //copy matrix A and B from host to the device 
    cudaMemcpy(d_A,h_A.data(),n * n * sizeof(double),cudaMemcpyHostToDevice);
    cudaMemcpy(d_B,h_B.data(),n * n * sizeof(double),cudaMemcpyHostToDevice); 

    //Create a CUBLAS handle 
    cublasHandle_t handle; 
    cublasCreate(&handle); 

    //Setup alpha and beta 
    double alpha = 1.0;
    double beta = 0.0; 


    cudaEvent_t start,stop;
    cudaEventCreate(&start);
    cudaEventCreate(&stop);
    cudaEventRecord(start,0);
    //Perform matrix multiplication (d_C = alpha * d_A * d_B + beta * d_C) using CUBLAS 
    //d_A : [m,k], d_B : [k,n], d_C : [m,n]
    cublasDgemm(
      handle,
      CUBLAS_OP_N, // No Transition
      CUBLAS_OP_N, // No Transition
      n, // m
      n, // n
      n, // k
      &alpha, // alpha 
      d_A, // d_A
      n, // lda 
      d_B, // d_B
      n, // ldb
      &beta, // beta
      d_C, // d_C
      n // ldc
    );
    
    //Allocate host memory for the result matrix C and copy it from device to host memory 
    
    cudaEventRecord(stop,0);
    cudaEventSynchronize(stop);
    float elapsedTime;
    cudaEventElapsedTime(&elapsedTime,start,stop);
    cout<<"Time taken for matrix multiplication of "<<n<<" * "<<n<<" matrix is "<<elapsedTime<<" ms"<<endl;

    vector<double> h_C(n * n); 
    cudaMemcpy(h_C.data(),d_C,n * n * sizeof(double),cudaMemcpyDeviceToHost); 
    vector<double> h_C_host = matrixMulOnHost(h_A,h_B,n);
    checkResult(h_C,h_C_host);
    //Free device memory 
    cudaFree(d_A);
    cudaFree(d_B);
    cudaFree(d_C);

    //Destroy the CUBLAS handle 
    cublasDestroy(handle);
    return 0;

}

这段代码的运行结果是:
Time taken for matrix multiplication of 1024 * 1024 matrix is 5.38173 ms


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/489668.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解决C语言的缺陷【C++】

文章目录 命名空间展开了命名空间域指定访问命名空间域域作用限定符命名空间定义 C输入&输出缺省参数全缺省参数半缺省参数缺省参数应用 函数重载参数类型不同参数个数不同参数类型顺序不同 引用引用的特性引用在定义时必须初始化一个变量可以有多个引用引用一旦引用一个实…

基于Radon-分数傅里叶变换对消器的海杂波弱目标检测

海面微弱目标检测面临的主要困难来自&#xff1a; 慢速小目标回波微弱&#xff1b;空时变海杂波异常复杂&#xff0c;海杂波特性认知难度大&#xff1b;目标模型难以建立&#xff1b;目标、海杂波类别非平衡。 ARU效应 是由于海面波浪的起伏和涟漪引起的。在雷达回波信号中&am…

nodejs开发 | 安全工具端口扫描器

今天分享一个nodejs的demo&#xff0c;可以扫描出指定IP的端口开放情况。 简单的说 Node.js 就是运行在服务端的 JavaScript。 Node.js 是一个基于 Chrome JavaScript 运行时建立的一个平台。 Node.js 是一个事件驱动 I/O 服务端 JavaScript 环境&#xff0c;基于 Google 的 V8…

[笔记]Python计算机视觉编程《一》 基本的图像操作和处理

文章目录 前言环境搭建 计算机视觉简介Python和NumPy第一章 基本的图像操作和处理1.1 PIL&#xff1a;Python图像处理类库1.1.1 转换图像格式1.1.2 创建缩略图1.1.3 复制和粘贴图像区域1.1.4 调整尺寸和旋转 1.2 Matplotlib1.2.1 绘制图像、点和线 前言 今天&#xff0c;图…

python基础实战6-python字符串

1字符串的表达方式 字符串是 Python 中最常用的数据类型。我们可以使用引号 ( 或 " ) 来创建字符串。 字符串表达方式 a " I m Tom" #一对双引号 b ’Tom said:" I am Tom" #一对单引号 c ‘Tom said: " I\m Tom" #转义字符 d T…

python库,科学计算与数据可视化基础,知识笔记(numpy+matplotlib)

文章目录 1、numpyndarray对象&#xff0c;数组指定形状创建&#xff08;要会&#xff09;数组的索引&#xff0c;切片与遍历&#xff08;要会&#xff09;数组的相加&#xff0c;转置&#xff0c;展开&#xff08;要会&#xff09;数组元素增删改查&#xff08;最好会&#xf…

当CRM遇见ChatGPT,AI如何帮销售打造“最强大脑”

导读&#xff1a;这一轮AI浪潮将对CRM企业带来哪些新机遇&#xff1f; ChatGPT诞生至今不过100多天&#xff0c;但它已经对很多行业产生了巨大影响。 企业直面市场的一线战场——销售、营销、客服等领域也是如此。以ChatGPT为代表的人工智能技术热潮正在改变着传统营销、销售的…

MySQL--group by--聚合函数--内置函数--0415 22

目录 1.聚合函数 1.1 count 1.2 sum 1.3 avg 1.4 max 和 min 2. group by 2.1 group by 的条件筛选——having 2.2 总结 3.日期函数 4.字符串函数 concat replace substring 以首字母大写&#xff0c;其余字母小写的方式显示员工的姓名 5.数学函数 format rand()…

C plus plus ——【继承与派生】

系列文章目录 C plud plus ——【面向对象编程】 C plus plus ——【继承与派生】 文章目录 系列文章目录前言一、继承1.1 类的继承1.2 继承后可访问性1.3 构造函数访问顺序1.4 子类隐藏父类的成员函数 二、重载运算符2.1重载运算符的必要性2.2重载运算的形式与规则2.3 转换运…

数字信号处理学习1

基本上算是没怎么学过数字信号处理这门课&#xff0c;因为本科的时候&#xff0c;专业方向用不上&#xff0c;现在没法子了&#xff0c;专业使然&#xff0c;只能自己自学了&#xff0c;但是我又不知道该从何学起&#xff0c;就买了一本现代数字信号处理&#xff0c;结果发现人…

数据结构/队列实现栈

前言 在学习数据结构的过程当中&#xff0c;我们会学到栈和队列&#xff0c;在本篇文章中&#xff0c;重点讲解的是队列实现栈&#xff0c;在上篇文章中已经简单介绍过栈和队列的使用说明&#xff0c;以及栈实现队列。(2条消息) 数据结构/栈实现队列_Y君的进化史的博客-CSDN博客…

吴恩达ChatGPT网课笔记Prompt Engineering——训练ChatGPT前请先训练自己

吴恩达ChatGPT网课笔记Prompt Engineering——训练ChatGPT前请先训练自己 主要是吴恩达的网课&#xff0c;还有部分github的prompt-engineering-for-developers项目&#xff0c;以及部分自己的经验。 一、常用使用技巧 prompt最好是英文的&#xff0c;如果是中文的prompt&am…

Day961.老城区前端改造 -遗留系统现代化实战

老城区前端改造 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于老城区前端改造的内容。 什么是“改造老城区”。改造老城区模式 是指对遗留系统内部的模块进行治理&#xff0c;让模块内部结构合理、模块之间职责清晰的一系列模式。 也就是说&#xff0c;在遗留系统…

【Redis】聊一下Redis基础架构

我们知道学习一个技术&#xff0c;最好的方式就是从全局观出发&#xff0c;然后针对不同的点进行拆分&#xff0c;一个个破解。既可以将学到的和已有的知识联系起来&#xff0c;又可以有一定的深度和目的性。 Redis基础架构 对于一个中间件来说&#xff0c;一个是使用层面&…

GO数组切片-线性数据结构

数据结构 类型 什么是类型 &#xff1f; 内存中的二进制数据本身没有什么区别&#xff0c;就是一串0或1的组合。 内存中有一个字节内容是0x63&#xff0c;他究竟是深恶 字符串?字符&#xff1f;还是整数&#xff1f; 本来0x63表示数字 但是文字必须编码成为0和1的组合 才能记…

【C++】红黑树源码剖析

目录 概述 算法 调整策略 源码 RBTree.h test.cpp 概述 红黑树&#xff0c;是一种二叉搜索树&#xff0c;每一个节点上有一个存储位表示节点的颜色&#xff0c;可以是Red或Black。 通过对任何一条从根到叶子的路径上各个节点着色方式的限制&#xff0c;红黑树确保没有一…

ChatGPT、文心一言、New Bing到底哪个更AI?

Hello 各位小伙伴&#xff0c;要说今年最火爆的 IP 有哪些&#xff0c;那一定少不了人工智能&#xff08;AI&#xff09;&#xff0c;市面上已经相继出现了我们熟知的 ChatGPT&#xff08;OpenAI&#xff09;、ChatGPT 国外镜像网站、文心一言&#xff08;百度&#xff09;、Ne…

MySQL --- DDL图形化工具表结构操作

一. 图形化工具 1. 介绍 前面我们讲解了DDL中关于数据库操作的SQL语句&#xff0c;在我们编写这些SQL时&#xff0c;都是在命令行当中完成的。大家在练习的时候应该也感受到了&#xff0c;在命令行当中来敲这些SQL语句很不方便&#xff0c;主要的原因有以下 3 点&#xff1a;…

redis的介绍和安装

文章目录 一、redis的介绍和安装1.1 初识redis1.1.1 redis是什么&#xff1f;1.1.2 redis能做什么&#xff1f; 1.2 redis的安装配置 一、redis的介绍和安装 1.1 初识redis 1.1.1 redis是什么&#xff1f; Redis是一个开源的内存数据存储系统&#xff0c;也可以被用作数据库、…

阿里云服务器vCPU和CPU有区别吗?

阿里云服务器vCPU是什么&#xff1f;vCPU和CPU有什么区别&#xff1f;CPU是指云服务器的中央处理器&#xff0c;一个CPU可以包含若干个物理核&#xff0c;一台云服务器ECS实例的CPU选项由CPU物理核心数和每核线程数决定&#xff0c;通过超线程HT&#xff08;Hyper-Threading&am…