Cuda矩阵运算库cuBLAS介绍

2023-11-13

简介

cuBLAS库用于进行矩阵运算,它包含两套API,一个是常用到的cuBLAS API,需要用户自己分配GPU内存空间,按照规定格式填入数据,;还有一套CUBLASXT API,可以分配数据在CPU端,然后调用函数,它会自动管理内存、执行计算。既然都用cuda了,其实还是用第一套API多一点。
官方文档参考
最初,为了尽可能地兼容Fortran语言环境,cuBLAS库被设计成列优先存储的数据格式,不过C/C++是行优先的,我们比较好理解的也是行优先的格式,所以需要费点心思在数据格式上。
在这里插入图片描述

cuBLAS库新特性

现在装好cuda会自带cuBLAS库的,只要include 头文件“cublas_v2.h”就可以调用它了。相比与之前的旧库,现在的cuBLAS矩阵运算库有些新特性:

  1. handle更加可控,更加适用于多GPU或CPU多进程。handle是cuBLAS库上下文的句柄,可以把数据、函数等等连接在一起,就想Cuda的stream一样。现在,新版本的cuBLAS可以用简单的函数创建句柄,然后把它绑定到不同的函数、数据上去;非常方便。
  2. 所有的函数都可以返回错误标识符cublasStatus_t了。可以更加方便调试,发现代码的具体错误原因。
  3. 函数cublasAlloc() and cublasFree()被摒弃了。

cuBLAS代码热身

官方手册在结束introduction后就来了一段简单的代码。

cublasSetMatrix()

先看个函数cublasSetMatrix()

cublasSetMatrix(int rows, int cols, int elemSize, const void *A, 
int lda, void *B, int ldb)

这个函数可以把CPU上的矩阵A拷贝到GPU上的矩阵B,两个矩阵都是列优先存储的格式。lda是A的leading dimension ,既然是列优先,那么就是A的行数(A的一列有多少个元素);ldb同理。
cublasGetMatrix()作用与之相反。

cudaMalloc()

分配GPU内存的函数

    float* devPtrA;
	cudaStat = cudaMalloc ((void**)&devPtrA, M*N*sizeof(*a));

为什么第一个参数是二级指针呢?
因为devPtrA是一个CPU上的指针,我现在分配了一块GPU内存空间,假设这个空间的首地址是 #0024,我想要修改devPtrA的值怎么办呢?C语言的基础告诉我们,函数想要修改一个变量的值,就得把他的指针穿进去,而不是仅仅作为形参传过去。所以这里是二级指针,因为我要把一级指针的值修改为 #0024。

cublasSscal()

传入矩阵x,总大小为n,每隔incx个数,就乘以alpha。

cublasSscal(cublasHandle_t handle, int n,const float *alpha,
float *x, int incx)

很简单的函数,纯粹为了演示。

源代码

来看一下:

//Example. Application Using C and CUBLAS: 0-based indexing
//-----------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <cuda_runtime.h>
#include "cublas_v2.h"
#define M 6 //6行
#define N 5 //5列
#define IDX2C(i,j,ld) (((j)*(ld))+(i))
/*一个把坐标(i, j)转化为cublas数据格式坐标的函数;
假设一个点位于第i行第j列,每一列的长度为ld,
则计算出来的列优先坐标就是 j*ld+i */

static __inline__ void modify (cublasHandle_t handle, float *m, int ldm, int n, int p, int q, float alpha, float beta){
    cublasSscal (handle, n-q, &alpha, &m[IDX2C(p,q,ldm)], ldm);
    cublasSscal (handle, ldm-p, &beta, &m[IDX2C(p,q,ldm)], 1);
}

int main (void){
    cudaError_t cudaStat;    
    cublasStatus_t stat;
    cublasHandle_t handle; //管理一个cublas上下文的句柄
    int i, j;
    float* devPtrA;
    float* a = 0;
    a = (float *)malloc (M * N * sizeof (*a));
    if (!a) {
        printf ("host memory allocation failed");
        return EXIT_FAILURE;
    }
    for (j = 0; j < N; j++) {
        for (i = 0; i < M; i++) {
            a[IDX2C(i,j,M)] = (float)(i * M + j + 1);
        }
    }
    cudaStat = cudaMalloc ((void**)&devPtrA, M*N*sizeof(*a));
    if (cudaStat != cudaSuccess) {
        printf ("device memory allocation failed");
        return EXIT_FAILURE;
    }
    stat = cublasCreate(&handle);
    if (stat != CUBLAS_STATUS_SUCCESS) {
        printf ("CUBLAS initialization failed\n");
        return EXIT_FAILURE;
    }
    stat = cublasSetMatrix (M, N, sizeof(*a), a, M, devPtrA, M);
    if (stat != CUBLAS_STATUS_SUCCESS) {
        printf ("data download failed");
        cudaFree (devPtrA);
        cublasDestroy(handle);
        return EXIT_FAILURE;
    }
    modify (handle, devPtrA, M, N, 1, 2, 16.0f, 12.0f);
    stat = cublasGetMatrix (M, N, sizeof(*a), devPtrA, M, a, M);
    if (stat != CUBLAS_STATUS_SUCCESS) {
        printf ("data upload failed");
        cudaFree (devPtrA);
        cublasDestroy(handle);
        return EXIT_FAILURE;
    }
    cudaFree (devPtrA);
    cublasDestroy(handle);
    for (j = 0; j < N; j++) {
        for (i = 0; i < M; i++) {
            printf ("%7.0f", a[IDX2C(i,j,M)]);
        }
        printf ("\n");
    }
    free(a);
    return EXIT_SUCCESS;
}

cuBLAS 辅助函数

上下文管理

使用cuBLAS库函数,必须初始化一个句柄来管理cuBLAS上下文。函数为cublasCreate(),销毁的函数为cublasDestroy()。这些操作全部需要显式的定义,这样用户同时创建多个handle,绑定到不同的GPU上去,执行不同的运算,这样多个handle之间的计算工作就可以互不影响。

cublasCreate(cublasHandle_t *handle)

官方手册建议尽可能少的创建handle,并且在运行任何cuBLAS库函数之前创建好handle。handle会和当前的device(当前的GPU显卡)绑定,如果有多块GPU,你可以为每一块GPU创建一个handle。或者只有一个GPU,你也可以创建多个handle与之绑定。

cublasDestroy(cublasHandle_t handle)

销毁handle时,会隐性调用同步阻塞函数cublasDeviceSynchronize()

复制矩阵

cublasSetVector(int n, int elemSize,
const void *x, int incx, void *y, int incy)

类似与前面的cublasSetMatrix(),这个函数也是把数据从CPU复制到GPU。CPU上包含n个元素的向量x,数据复制到GPU矩阵y上,每个元素的字节数为elemSize,incx是x的主维的长度,如果是列优先格式,那么就是x的行数,incy同理。

数据类型标示

大多数用于计算的cuBLAS函数名字里都包含数据类型信息,表明这个函数专门用于处理float、double还是什么数据类型的。
在这里插入图片描述

cuBLAS 运算函数

这部分函数被官方分为了3个等级,Level-1、Level-2、Level-3处理的情境逐渐变得复杂,功能变得强大。Level-1里求最大最小值,求和,旋转等等。Level-3就全是矩阵与矩阵间运算的函数了,矩阵相乘就在这里面。

矩阵相乘

下面是Level-3函数cublasSgemm(),处理float数,还有cublasDgemm()也是矩阵相乘,处理的是double。

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,
float *C, int ldc)

函数求: C = α ∗ A ∗ B + β ∗ C C=\alpha *A*B+\beta *C C=αAB+βC,令 α = 1 \alpha = 1 α=1 β = 0 \beta = 0 β=0,就可以求A*B。
第二、三个参数cublasOperation_t类型,可以等于CUBLAS_OP_T表示需要转置后运算,或者不需要CUBLAS_OP_N
m: A有多少行;
n: B有多少列;
k: A的列数,也是B的行数;
其他的不用多说了,都提到过。注意还是列优先。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Cuda矩阵运算库cuBLAS介绍 的相关文章

  • TensorRT 多线程

    我正在尝试使用 python API 来使用 TensorRt 我试图在多个线程中使用它 其中 Cuda 上下文与所有线程一起使用 在单个线程中一切正常 我使用 docker 和 tensorrt 20 06 py3 图像 onnx 模型和
  • 如何运行和理解CUDA Visual Profiler?

    我已经设置了 CUDA 5 0 并且我的 CUDA 项目运行良好 但我不知道如何使用 Visual Profiler 分析我的 CUDA 项目 如何运行它 我还需要安装更多吗 又该如何做呢 我的电脑使用Window 7 64位 CUDA 5
  • cuda-gdb 错误消息

    我尝试使用 cuda gdb 调试我的 CUDA 应用程序 但遇到了一些奇怪的错误 我设置了选项 g G O0构建我的应用程序 我可以在没有 cuda gdb 的情况下运行我的程序 但没有得到正确的结果 因此我决定使用 cuda gdb 但
  • 有条件减少 CUDA

    我需要总结一下100000值存储在数组中 但带有条件 有没有办法在 CUDA 中做到这一点以快速产生结果 任何人都可以发布一个小代码来做到这一点吗 我认为 要执行条件约简 您可以直接将条件引入为乘法0 假 或1 真 加数 换句话说 假设您希
  • CUDA NSight 未随 Windows 8 上的 CUDA 5.0 安装文件一起安装? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 据我所知 Nvidia 网站上没有 Nsight Eclipse 的下载链接 它说它将由 CUDA 5 安装本机安装 但并没有随CUDA安装一起安装
  • C 中的 CUDA:如何使用 cudaMemcpyAsync 修复错误 11

    我目前正在尝试使用 CUDA 运行一个简单的多 GPU 程序 它的基本作用是将一个包含一些虚拟数据的大型数组复制到 GPU GPU 进行一些数学计算 然后将结果数组复制回来 我在 VS2017 的输出中没有收到任何错误 但我设置的一些错误消
  • CUDA 添加矩阵的行

    我试图将 4800x9600 矩阵的行加在一起 得到一个 1x9600 的矩阵 我所做的是将 4800x9600 分成 9 600 个矩阵 每个矩阵长度为 4800 然后我对 4800 个元素进行缩减 问题是 这真的很慢 有人有什么建议吗
  • 使用 GPU 进行 Matlab 卷积

    我用gpuArray尝试了matlab的卷积函数conv2 convn 例如 convn gpuArray rand 100 100 10 single gpuArray rand 5 single 并将其与 cpu 版本 convn ra
  • Cuda:最小二乘求解,速度较差

    最近 我使用Cuda编写了一个名为 正交匹配追踪 的算法 在我丑陋的 Cuda 代码中 整个迭代需要 60 秒 而 Eigen lib 只需 3 秒 在我的代码中 矩阵 A 是 640 1024 y 是 640 1 在每一步中 我从 A 中
  • 在 CUDA 中的设备内存上分配 2D 数组

    如何在 Cuda 中的设备内存中分配和传输 往返于主机 2D 数组 我找到了解决这个问题的方法 我不必展平阵列 内置的cudaMallocPitch 函数完成了这项工作 我可以使用以下命令将阵列传输到设备或从设备传输阵列cudaMemcpy
  • CUDA 和 Eigen 的成员“已声明”错误

    我只是 CUDA 和 Nsight 的初学者 希望利用出色的 GPU 性能进行线性代数运算 例如 CUBLAS 我在以下人员的帮助下编写了很多自定义代码Eigen http eigen tuxfamily org index php tit
  • 使用推力来处理 CUDA 类中的向量?

    我对 C 类的推力的适用性有疑问 我正在尝试实现一个类对象 该对象接收顶点的 x y z 坐标作为 ver1 ver2 和 ver3 然后 分配给一个三角形并计算面积和法向量 然而 我不太明白如何创建一类推力向量 这是我从文件中读取的顶点坐
  • 无法编译cuda_ndarray.cu:libcublas.so.7.5:无法打开共享对象文件

    我正在尝试在 aws 实例中导入 theano 库以使用 GPU 我已经使用 boto 编写了一个 python 脚本来自动执行 aws 设置 该脚本本质上会从我的本地计算机对实例执行 ssh 然后启动一个 bash 脚本 其中我执行 py
  • 如何降级cuda版本

    我目前使用的是 cuda 版本 4 2 但我需要将其更改为 3 1 是否可以卸载当前版本 4 2 版 然后安装以前的版本 3 1 版 编辑 请参阅我的操作系统是linux ubuntu 10 04 64位 编辑 我找到了如何获取 3 1 版
  • CUDA cutil.h 在哪里?

    有谁知道包含 cutil h 的 SDK 工具包在哪里 我尝试了 CUDA toolkits3 2 和 toolkits5 0 我知道这个版本已经不支持 cutil h 我还注意到一些提到的如何在 Linux 中包含 cutil h htt
  • 为什么在 CUDA 中启动 32 倍数的线程?

    我参加了 CUDA 并行编程课程 并且看到了许多 CUDA 线程配置的示例 其中通常将所需的线程数四舍五入到最接近的 32 倍数 我知道线程被分组为 warp 并且如果您启动 1000 个线程 GPU 无论如何都会将其四舍五入到 1024
  • CUDA 中的原子操作失败

    由于计算能力为2 1 atomicAdd and atomicMax操作不支持双精度 那么我根据堆栈溢出的一些答案定义这两个函数 奇怪的是atomicAdd功能运行良好 但atomicMax不起作用 这是我的代码 我的代码的测试是在每个块上
  • fork后CUDA初始化错误

    调用 fork 后出现 初始化错误 如果我在没有 fork 的情况下运行相同的程序 则一切正常 if fork 0 cudaMalloc 什么会导致这种情况呢 下面是一个完整的示例 如果我注释掉 cudaGetDeviceCount 调用
  • 针对 openpose 将 GCC 9.3.0 降级到 7 后,cuda_compile_1_ generated_batch_norm_layer.cu.o.Release.cmake 出现 CMake 错误

    你知道我该如何解决以下错误吗 这是在我使用以下命令从 GCC 9 3 0 降级到 7 后发生的 使用以前版本的 GCC 我收到此错误 CMake 不支持的 GNU 版本 不支持高于 8 的 gcc 版本 https stackoverflo
  • CUDA双指针内存复制[重复]

    这个问题在这里已经有答案了 我这样写了我的示例代码 int d ptr cudaMalloc void d ptr sizeof int N int tmp ptr N for int i 0 i

随机推荐

  • python数组初始化_python怎么初始化数组

    因为画图中x轴与y轴的数据通常为数组格式的数据 所以先总结一下如何初始化数组 1 list得到数组 通过array函数传递list对象 L 1 2 3 4 5 6 a np array L 若传递的是多层嵌套的list 将创建多维数组 b
  • 【爬虫】一、BeautifulSoup库

    文档内容为本人观看北京理工大学嵩天老师公开课的听课笔记与实践总结 图片为从该课程下载资料的截图 感谢嵩老师 Key point 网页内容提取实际上是对标签的内容进行提取 其关键是标签的获取和标签感兴趣内容的提取 获取标签用beautiful
  • win10计算机设备感叹号,win10网络适配器出现感叹号的解决方法

    Win10系统仍然在不断完善 所以用户在使用过程中总会遇到一些陌生的问题 比如 有位用户在新装或重装的Win10系统中 就碰到了网卡不能安装 或安装出错 安装好网卡不能加载等等各种网卡驱动问题 今天小编就为大家简单的介绍一下Win10系统安
  • vtk光照、颜色、相机、坐标系统及空间变换

    1 vtkLight常的方法有 SetColor 设置光照的颜色 以RGB的形式指定颜色 SetPosition 设置光照位置 SetFocalPoint 设置光照焦点 SetIntensity 设置光照的强度 SetSwitch Swit
  • jsrender的基本使用

    1 什么是jsrender 一个JavaScript库 允许您定义一次样板结构并重复使用它来动态生成HTML JsRender为HTML5开发带来了一个新的模板库 它具有无代码标记语法和高性能 不依赖于jQuery 也不依赖于文档对象模型
  • Go-新手速成-流程语句

    1if Go的if不建议写 over if条件判断 age 16 if age lt 18 fmt Println 未成年 2for循环 Go摈弃了while和do while 循环 因为他做到了极简 也不要括号 这么写可以 total 0
  • Pandas知识点-reset_index,reindex,reindex_like,你分得清吗?

    Pandas知识点 reset index reindex reindex like 你分得清吗 reset index 用法详解 reset index 是pandas中将索引重置成自然数的方法 不会改变原始数据的内容和排列顺序 Data
  • 2023年第五届清洁能源与智能电网国际会议(CCESG 2023)

    2023年第五届清洁能源与智能电网国际会议 CCESG 2023 重要信息 会议网址 www ccesg org 会议时间 2023年11月3 5日 召开地点 广西 南宁 截稿时间 2023年10月3日 录用通知 投稿后2周内 收录检索 E
  • Python3基础入门

    文章目录 前言 基础说明 Python安装 Windows Ubuntu 开发环境 程序编写 模块和包 模块 module 包 package pip和换源 总结 前言 Python是目前非常流行的编程语言 这篇文章将对其相关入门内容进行说
  • JS判断数据类型的5种方法

    我们先来了解一下JS中数据类型有哪些 基本数据类型 值类型 String Number boolean null undefined symbol es6新增的 引用数据类型 引用类型 object 包含 Function Array Da
  • CSS line-height概念与举例

    本文同时发表在https github com zhangyachen zhangyachen github io issues 37 定义 两行文字基线之间的距离 基线的大体位置 基线的位置可以看成x字母下边缘的位置 不同字体的基线位置会
  • 微信公众号H5音频视频自动播放(安卓,苹果)

    我们都知道音频视频的自动播放被浏览器或者微信给限制了 必须用户跟页面交互才可以播放音视频 解决办法就是引入微信的jssdk 然后监听 WeixinJSBridgeReady 来实现自动播放 引入jssdk 音频或视频自动播放 documen
  • 查看运行的java程序的几种方式

    windows 任务管理器可以查看进程和线程数 也可以用来杀死进程 tasklist 查看进程 tasklist 杀死进程 linux ps ef 查看所有进程 ps ft p 查看某个进程 PID 的所有线程 kill 杀死进程 top
  • 【转载】手把手教你用 “三步法” 快速实现 4K+ 超高分辨率满细节出图

    手把手教你用 三步法 快速实现 4K 超高分辨率满细节出图 https ngabbs com read php tid 35888357 rand 488 准备工作 如果你的显存不足以直出你期望的最终分辨率 请先按照你习惯的方式安装 切片扩
  • uniapp - Map地图组件属性示例

    目录 1 markers 点标记 用于在地图上显示标记的位置 2 点聚合 3 polygons 4 include points 可以实现自动缩放展示视图内所有的点标记 5 polyline 线 map uni app官网 1 marker
  • littleVGL学习笔记5——lv_obj 基础对象

    1 介绍 littleVGL 是以对象为概念的 而其最核心的基础对象是 lv obj 控件 其他的所有专用控件 比如按钮 标签 列表等 都是在此 lv obj 对象的基础上衍生出来的 所有的控件对象都具有一些共同的属性 如下所示 位置 Po
  • JUC 十二. ReentrantReadWriteLock 与 StampedLock

    目录 一 基础 二 ReentrantReadWriteLock 的锁降级 三 StampedLock 邮戳票据锁 一 基础 ReentrantReadWriteLock 可以看为读读共享 读写 写写依然互斥 总结一句话 读写互斥 读读共享
  • 数字化时代-26:不要做数字空间的难民

    网络是人们新的生存空间 年轻人出生后就存在的空间 与人类社会原先的现实空间并存的人与人交流的空间 在这个空间中 没有自己位置的人 将成为未来社会的难民 年轻人 特别是毕业后的年轻人 需要思考 个人在数字空间中的落脚点和位置 数字原住民 在数
  • Ubuntu 20.04-NVIDIA显卡驱动-安装和卸载-解决黑屏问题

    这一步很重要 202300704更新 黑屏问题主要由linux内核更新导致 一定要保持当前的内核 也就是安装 NVIDIA 驱动时用的内核 sudo apt mark hold linux image generic linux heade
  • Cuda矩阵运算库cuBLAS介绍

    文章目录 简介 cuBLAS库新特性 cuBLAS代码热身 cublasSetMatrix cudaMalloc cublasSscal 源代码 cuBLAS 辅助函数 上下文管理 复制矩阵 数据类型标示 cuBLAS 运算函数 矩阵相乘