NIVIDIA高性能计算CUDA笔记(二)—cuBLAS库简介
NIVIDIA高性能计算CUDA笔记(二)—cuBLAS库简介
1.什么是cuBLAS?
\(cuBLAS\) 是NIVIDIA提供的GPU加速线性代数库,基于CUDA实现BLAS(基本线性代数子程序),广泛应用于科学计算、机器学习、工程仿真等领域。本笔记调研cuBLAS库的基本情况,将详细介绍产品的功能、算子列表及API列表。
\(cuBLAS\) 具备以下特点:
- 高性能优化:高度优化、底层使用\(Tensor \space Core\)、共享内存、流水调度等技术进行深度优化;
- 完整性:完整支持\(BLAS\) Level 1/2/3接口,覆盖所有标准BLAS例程(152个);
- 易用性: 提供与表征\(BLAS\) 兼容的接口,开发者可以轻松从CPU实现迁移到GPU端,支持主机端调用,适合与现有框架集成;
- 支持多种数据类型:FP32、FP64、FP16、BF16、INT8等;
- 灵活性:支持流(stream)、异步执行、Tensor Core运算等高级特性;提供扩展功能(BLAS-Extension),支持混合精度和批处理操作;
\(cuBLAS\) 适用场景:
- 深度学习:加速神经网络中的矩阵乘法(GEMM),如卷积神经网络(CNN)和 变换器(Transformer);
- 科学计算:处理物理模拟、量子化学等需要密集线性代数计算领域;
- 高性能计算(HPC):在GPU集群中执行大规模矩阵运算;
- 通用线性代数:适用于需要标准 BLAS 功能的任何应用。
2.cuBLAS分级概述
| 分类 | 算子个数 | API个数 |
|---|---|---|
| Level-1算子 | 13 | 54 |
| Level-2算子 | 16 | 58 |
| Level-3算子 | 5 | 34 |
| Extension 算子 | 23 | 48 |
| helpfer function | / | 22 |
| 总计 | 57 | 216 |
大多数用于计算的\(cuBLAS\)函数名字内都包含了数据类型,表明这个函数专门用于处理float、double还是什么数据类型。
| 处理的数据类型 | 标识符号 | 含义 |
|---|---|---|
| float | ‘s’ or ‘S’ | 单浮点精度实数(real-single-precision) |
| double | ‘d’ or ‘D’ | 双浮点精度实数 (real-Double-precision) |
| cuComplex | ‘c’ or ‘C’ | 单浮点精度复数 (complex-single-precision) |
| cuDoubleComplex | 'z' or 'Z' | 双浮点精度复数 (complex-Double-precision) |
2.1 算子列表
(1) Level-1 算子(向量-向量操作):这些算子处理向量之间的基本操作。
| Level-1 算子 | 描述 | API |
|---|---|---|
| axpy | 向量加法,将标量乘以向量并加到另一个向量 | cublasSaxpy, cublasDaxpy, cublasCaxpy, cublasZaxpy |
| copy | 向量复制,将一个向量复制到另一个向量 | cublasScopy, cublasDcopy, cublasCcopy, cublasZcopy |
| dot | 点积,计算两个向量的点积(复数区分共轭/非共轭) | cublasSdot, cublasDdot, cublasCdotu, cublasCdotc, cublasZdotu, cublasZdotc |
| nrm2 | 欧几里得范数,计算向量的二范数 | cublasSnrm2, cublasDnrm2, cublasScnrm2, cublasDznrm2 |
| asum | 绝对值和,计算向量元素绝对值之和 | cublasSasum, cublasDasum, cublasScasum, cublasDzasum |
| iamax | 最大绝对值索引,返回绝对值最大元素的索引 | cublasIsamax, cublasIdamax, cublasIcamax, cublasIzamax |
| iamin | 最小绝对值索引,返回绝对值最小元素的索引 | cublasIsamin, cublasIdamin, cublasIcamin, cublasIzamin |
| rot | 应用Givens旋转,对两个向量应用旋转变换 | cublasSrot, cublasDrot, cublasCrot, cublasCsrot, cublasZrot, cublasZdrot |
| rotg | 构造 Givens 旋转,生成旋转参数 | cublasSrotg, cublasDrotg, cublasCrotg, cublasZrotg |
| rotm | 应用修改后的 Givens 旋转,使用预定义参数执行旋转 | cublasSrotm, cublasDrotm |
| rotmg | 构造修改后的 Givens 旋转,生成修改后的旋转参数 | cublasSrotmg, cublasDrotmg |
| scal | 缩放,将向量乘以标量 | cublasSscal, cublasDscal, cublasCscal, cublasCsscal, cublasZscal, cublasZdscal |
| swap | 交换向量 | cublasSswap, cublasDswap, cublasCswap, cublasZswap |
(2)Level-2 算子(矩阵-向量操作):这些算子涉及矩阵与向量之间的操作
| 算子 | 描述 | API |
|---|---|---|
| gemv | 一般矩阵-向量乘法,矩阵与向量乘法加向量 | cublasSgemv, cublasDgemv, cublasCgemv, cublasZgemv |
| gbmv | 带状矩阵-向量乘法 | cublasSgbmv, cublasDgbmv, cublasCgbmv, cublasZgbmv |
| ger | 秩-1更新,用于向量外积更新矩阵 | cublasSger, cublasDger, cublasCgeru, cublasCgerc, cublasZgeru, cublasZgerc |
| sbmv | 对称带状矩阵-向量乘法,对称带状矩阵与向量乘法 | cublasSsbmv, cublasDsbmv |
| spmv | 对称压缩矩阵-向量乘法,压缩格式对称矩阵与向量乘法 | cublasSspmv, cublasDspmv |
| spr | 对称压缩秩-1 更新,压缩格式对称矩阵更新 | cublasSspr, cublasDspr |
| spr2 | 对称压缩秩-2 更新,压缩格式对称矩阵秩-2 更新 | cublasSspr2, cublasDspr2 |
| symv | 对称矩阵-向量乘法,对称矩阵与向量乘法 | cublasSsymv, cublasDsymv, cublasChemv, cublasZhemv |
| syr | 对称秩-1 更新,对称矩阵的秩-1 更新 | cublasSsyr, cublasDsyr, cublasCsyr, cublasZsyr, cublasCher, cublasZher |
| syr2 | 对称秩-2 更新,对称矩阵的秩-2 更新 | cublasSsyr2, cublasDsyr2, cublasCsyr2, cublasZsyr2, cublasCher2, cublasZher2 |
| tbmv | 三角带状矩阵-向量乘法,三角带状矩阵与向量乘法 | cublasStbmv, cublasDtbmv, cublasCtbmv, cublasZtbmv |
| tbsv | 三角带状矩阵求解,三角带状矩阵系统求解 | cublasStbsv, cublasDtbsv, cublasCtbsv, cublasZtbsv |
| tpmv | 三角压缩矩阵-向量乘法,压缩格式三角矩阵与向量乘法 | cublasStpmv, cublasDtpmv, cublasCtpmv, cublasZtpm |
| tpsv | 三角压缩矩阵求解,压缩格式三角矩阵系统求解 | cublasStpsv, cublasDtpsv, cublasCtpsv, cublasZtpsv |
| trmv | 三角矩阵-向量乘法,三角矩阵与向量乘法 | cublasStrmv, cublasDtrmv, cublasCtrmv, cublasZtrm |
| trsv | 三角矩阵求解,三角矩阵系统求解 | cublasStrsv, cublasDtrsv, cublasCtrsv, cublasZtrsv |
(3)Level-3算子(矩阵-矩阵操作):这些算子处理矩阵与矩阵之间的操作,包括处理的变体
| 算子 | 描述 | API |
|---|---|---|
| gemm | 一般矩阵-矩阵乘法,矩阵乘法加矩阵,包括批处理版本 | cublasSgemm, cublasDgemm, cublasCgemm, cublasZgemm, cublasSgemmBatched, cublasDgemmBatched, cublasCgemmBatched, cublasZgemmBatched |
| syrk | 对称秩-k 更新,对称矩阵的秩-k 更新 | cublasSsyrk, cublasDsyrk, cublasCsyrk, cublasZsyrk, cublasCherk, cublasZherk |
| syr2k | 对称秩-2k 更新,对称矩阵的秩-2k 更新 | cublasSsyr2k, cublasDsyrk, cublasCsyr2k, cublasZsyr2k, cublasCher2k, cublasZher2k |
| trmm | 三角矩阵-矩阵乘法,三角矩阵与矩阵乘法 | cublasStrmm, cublasDtrmm, cublasCtrmm, cublasZtrmm |
| trsm | 三角求解,三角矩阵系统求解,包括批处理版本 | cublasStrsm, cublasDtrsm, cublasCtrsm, cublasZtrsm, cublasStrsmBatched, cublasDtrsmBatched, cublasCtrsmBatched, cublasZtrsmBatched |
(4)BLAS-like算子列表
| 算子 | 描述 | API |
|---|---|---|
| geam | 矩阵加法或转置加法,将两个矩阵相加,支持转置选项 | cublasSgeam, cublasDgeam, cublasCgeam, cublasZgeam |
| dgmm | 对角矩阵乘法,将对角矩阵与一般矩阵相乘 | cublasSdgmm, cublasDdgmm, cublasCdgmm, cublasZdgmm |
| getrfBatched | 批处理 LU分解,对多个矩阵执行 LU 分解 | cublasSgetrfBatched, cublasDgetrfBatched, cublasCgetrfBatched, cublasZgetrfBatched |
| getrsBatched | 批处理线性系统求解,使用 LU 分解结果求解多个线性系统 | cublasSgetrsBatched, cublasDgetrsBatched, cublasCgetrsBatched, cublasZgetrsBatched |
| getriBatched | 批处理矩阵求逆,使用 LU 分解结果求多个矩阵的逆 | cublasSgetriBatched, cublasDgetriBatched, cublasCgetriBatched, cublasZgetriBatched |
| matinvBatched | 批处理矩阵求逆,直接求多个矩阵的逆 | cublasSmatinvBatched, cublasDmatinvBatched, cublasCmatinvBatched, cublasZmatinvBatched |
| geqrfBatched | 批处理 QR分解,对多个矩阵执行 QR 分解 | cublasSgeqrfBatched, cublasDgeqrfBatched, cublasCgeqrfBatched, cublasZgeqrfBatched |
| gelsBatched | 批处理最小二乘,求解多个最小二乘问题 | cublasSgelsBatched, cublasDgelsBatched, cublasCgelsBatched, cublasZgelsBatched |
| tpttr | 三角矩阵打包,将三角矩阵打包为压缩格式 | cublasStpttr, cublasDtpttr, cublasCtpttr, cublasZtpttr |
| gemmEx | 混合精度矩阵乘法,支持多种输入和输出数据类型 | cublasGemmEx |
| gemmBatchedEx | 批处理混合精度矩阵乘法,对多个矩阵执行混合精度计算 | cublasGemmBatchedEx |
| gemmStridedBatchedEx | 带步幅的批处理混合精度矩阵乘法,支持步幅参数的批处理 | cublasGemmStridedBatchedEx |
| csyrkEx | 混合精度对称秩-k 更新,更新对称矩阵 | cublasCsyrkEx |
| csyrk3mEx | 混合精度对称秩-k 更新,优化为三倍精度计算 | cublasCsyrk3mEx |
| nrm2Ex | 混合精度欧几里得范数,计算向量的二范数 | cublasSnrm2Ex, cublasDnrm2Ex |
| axpyEx | 混合精度向量加法,将标量乘以向量并加到另一向量上 | cublasSaxpyEx, cublasDaxpyEx |
| dotEx | 混合精度点积,计算两个向量的点积 | cublasSdotEx, cublasDdotEx |
| rotEx | 混合精度 Givens 旋转,对两个向量应用旋转变换 | cublasSrotEx, cublasDrotEx |
| scalEx | 混合精度缩放,将向量乘以标量 | cublasSscalEx, cublasDscalEx |
注意:cublasGemmEx 已经覆盖了 cublas<t>gemmEx
(5)Helper API 列表:
算子 API 已在上文的算子列表中详细列出,共包括 Level-1、Level-2、Level-3 和扩展算子的所有变体,总数约为 180+ 个(因数据类型变体繁多)。以下是 Helper API 根据官方文档的功能分类,分为以下类别:
库管理(Library Management)
| API | 说明 |
|---|---|
| cublasCreate | 创建 cuBLAS 句柄,用于初始化库 |
| cublasDestroy | 销毁 cuBLAS 句柄,释放资源 |
| cublasGetVersion | 获取 cuBLAS 库的版本号 |
| cublasSetStream | 设置 cuBLAS 句柄关联的 CUDA 流 |
| cublasGetStream | 获取 cuBLAS 句柄当前关联的 CUDA 流 |
| cublasSetWorkspace | 设置工作空间内存,用于某些操作 |
| cublasSetPointerMode | 设置指针模式(主机或设备),影响参数传递方式 |
| cublasGetPointerMode | 获取当前指针模式 |
| cublasSetMathMode | 设置数学模式(如启用张量核心加速) |
| cublasGetMathMode | 获取当前数学模式 |
数据传输(Data Transfer)
| API | 说明 |
|---|---|
| cublasSetVector | 将向量数据从主机传输到设备 |
| cublasGetVector | 将向量数据从设备传输到主机 |
| cublasSetMatrix | 将矩阵数据从主机传输到设备 |
| cublasGetMatrix | 将矩阵数据从设备传输到主机 |
| cublasSetVectorAsync | 异步将向量数据从主机传输到设备 |
| cublasGetVectorAsync | 异步将向量数据从设备传输到主机 |
| cublasSetMatrixAsync | 异步将矩阵数据从主机传输到设备 |
| cublasGetMatrixAsync | 异步将矩阵数据从设备传输到主机 |
日志配置(Logging)
| API | 说明 |
|---|---|
| cublasLoggerConfigure | 配置 cuBLAS 的日志记录功能 |
| cublasSetLoggerCallback | 设置用户定义的日志回调函数 |
| cublasGetLoggerCallback | 获取当前日志回调函数 |
属性查询(Property Queries)
| API | 说明 |
|---|---|
| cublasGetProperty | 查询 cuBLAS 库的属性(如版本号) |
2.2 cublas的矩阵乘法案例
在本小节中,我们给出一个代码中以矩阵乘法为例来展示如何使用cuBLAS库进行矩阵乘法运算,CUBLAS的库的使用步骤如下:
- Step one:定义CUBLAS库对象;
- Step two: 在显存中为待运算的数据以及需要存放结果的变量开辟显存空间;(
cudaMalloc函数实现) - Step three:将待运算的数据传输进显存;(
cudaMemcpy,cublasSetVecotor等函数实现) - Step four: 调用CUBLAS的处理函数;(根据 CUBLAS 手册调用需要的函数)
- Step five: 从显存中获取结果变量;(
cudaMemcpy,cublasGetVector等函数实现) - Step six: 释放申请的显存空间以及CUBLAS库的对象;(cudaFree 及 cublasDestroy 函数实现 )
如下程序使用 CUBLAS 库进行矩阵乘法运算,请仔细阅读注释,尤其是 API 的参数说明:
// CUDA runtime 库 + CUBLAS 库
#include "cuda_runtime.h"
#include "cublas_v2.h"
#include <time.h>
#include <iostream>
using namespace std;
// 定义测试矩阵的维度
int const M = 5;
int const N = 10;
int main()
{
// 定义状态变量
cublasStatus_t status;
// 在 内存 中为将要计算的矩阵开辟空间
float *h_A = (float*)malloc (N*M*sizeof(float));
float *h_B = (float*)malloc (N*M*sizeof(float));
// 在 内存 中为将要存放运算结果的矩阵开辟空间
float *h_C = (float*)malloc (M*M*sizeof(float));
// 为待运算矩阵的元素赋予 0-10 范围内的随机数
for (int i=0; i<N*M; i++) {
h_A[i] = (float)(rand()%10+1);
h_B[i] = (float)(rand()%10+1);
}
// 打印待测试的矩阵
cout << "矩阵 A :" << endl;
for (int i=0; i<N*M; i++){
cout << h_A[i] << " ";
if ((i+1)%N == 0) cout << endl;
}
cout << endl;
cout << "矩阵 B :" << endl;
for (int i=0; i<N*M; i++){
cout << h_B[i] << " ";
if ((i+1)%M == 0) cout << endl;
}
cout << endl;
/*
** GPU 计算矩阵相乘
*/
// 创建并初始化 CUBLAS 库对象
cublasHandle_t handle;
status = cublasCreate(&handle);
if (status != CUBLAS_STATUS_SUCCESS)
{
if (status == CUBLAS_STATUS_NOT_INITIALIZED) {
cout << "CUBLAS 对象实例化出错" << endl;
}
getchar ();
return EXIT_FAILURE;
}
float *d_A, *d_B, *d_C;
// 在 显存 中为将要计算的矩阵开辟空间
cudaMalloc (
(void**)&d_A, // 指向开辟的空间的指针
N*M * sizeof(float) // 需要开辟空间的字节数
);
cudaMalloc (
(void**)&d_B,
N*M * sizeof(float)
);
// 在 显存 中为将要存放运算结果的矩阵开辟空间
cudaMalloc (
(void**)&d_C,
M*M * sizeof(float)
);
// 将矩阵数据传递进 显存 中已经开辟好了的空间
cublasSetVector (
N*M, // 要存入显存的元素个数
sizeof(float), // 每个元素大小
h_A, // 主机端起始地址
1, // 连续元素之间的存储间隔
d_A, // GPU 端起始地址
1 // 连续元素之间的存储间隔
);
cublasSetVector (
N*M,
sizeof(float),
h_B,
1,
d_B,
1
);
// 同步函数
cudaThreadSynchronize();
// 传递进矩阵相乘函数中的参数,具体含义请参考函数手册。
float a=1; float b=0;
// 矩阵相乘。该函数必然将数组解析成列优先数组
cublasSgemm (
handle, // blas 库对象
CUBLAS_OP_T, // 矩阵 A 属性参数
CUBLAS_OP_T, // 矩阵 B 属性参数
M, // A, C 的行数
M, // B, C 的列数
N, // A 的列数和 B 的行数
&a, // 运算式的 α 值
d_A, // A 在显存中的地址
N, // lda
d_B, // B 在显存中的地址
M, // ldb
&b, // 运算式的 β 值
d_C, // C 在显存中的地址(结果矩阵)
M // ldc
);
// 同步函数
cudaThreadSynchronize();
// 从 显存 中取出运算结果至 内存中去
cublasGetVector (
M*M, // 要取出元素的个数
sizeof(float), // 每个元素大小
d_C, // GPU 端起始地址
1, // 连续元素之间的存储间隔
h_C, // 主机端起始地址
1 // 连续元素之间的存储间隔
);
// 打印运算结果
cout << "计算结果的转置 ( (A*B)的转置 ):" << endl;
for (int i=0;i<M*M; i++){
cout << h_C[i] << " ";
if ((i+1)%M == 0) cout << endl;
}
// 清理掉使用过的内存
free (h_A);
free (h_B);
free (h_C);
cudaFree (d_A);
cudaFree (d_B);
cudaFree (d_C);
// 释放 CUBLAS 库对象
cublasDestroy (handle);
getchar();
return 0;
}
输出结果:

3.总 结
cuBLAS 主库是一个功能全面、高性能的线性代数库,覆盖所有标准 BLAS 例程,适用于深度学习、科学计算和高性能计算等场景。它通过 GPU 加速和 Tensor Core 优化提供高效计算能力,是 cuBLAS 家族中最通用的组件。开发者可以结合官方文档和示例,利用 CUDA Toolkit 集成 cuBLAS 主库。

浙公网安备 33010602011771号