C++使用cuBLAS加速矩阵乘法运算的实现代码

本博客主要参考cuBLAS 库 词条实现,与原文不同的是,本博客:

  1. 将cuBLAS库的乘法运算进行了封装,方便了算法调用;
  2. 将原文的结果转置实现为了不转置,这样可以直接使用计算结果;
  3. 测试并更改了乘法参数,解决了原文中更改矩阵大小时报错的问题。

总的来说,本博客的代码利用cuBLAS库实现了两个矩阵相乘,提高了矩阵乘法的计算速度。

test.cpp

#include "cuda_runtime.h"
#include "cublas_v2.h"
#include <time.h>
#include <iostream>

using namespace std;

// cuBLAS实现矩阵乘法
int **matMult_cuBLAS(int **A, int **B, int rowSizeA, int colSizeA, int colSizeB, cublasHandle_t cuHandle){
    // 结果矩阵
    int** C = new int*[rowSizeA];
    for(int i = 0; i < rowSizeA; i++){
        C[i] = new int[colSizeB];
    }
    for (int i = 0; i < rowSizeA; i++){
        for (int j = 0; j < colSizeB; j++){
            C[i][j] = 0;
        }
    }

    // 在内存中为将要计算的矩阵开辟空间
    float *h_A = (float*)malloc (rowSizeA * colSizeA * sizeof(float));
    float *h_B = (float*)malloc (colSizeA * colSizeB * sizeof(float));
    float *h_C = (float*)malloc (rowSizeA * colSizeB * sizeof(float));

    // 初始化计算矩阵h_A和h_B
    for (int i = 0; i < rowSizeA; i++) {
        for (int j = 0; j < colSizeA; j++) {
            h_A[i * colSizeA + j] = (float)A[i][j];
        }
    }
    for (int i = 0; i < colSizeA; i++) {
        for (int j = 0; j < colSizeB; j++) {
            h_B[i * colSizeB + j] = (float)B[i][j];
        }
    }

    // 在显存中为将要计算矩阵与结果矩阵开辟空间
    float *d_A, *d_B, *d_C;
    cudaMalloc (
        (void**)&d_A,    // 指向开辟的空间的指针
        rowSizeA * colSizeA * sizeof(float)    // 需要开辟空间的字节数
    );
    cudaMalloc (
        (void**)&d_B,
        colSizeA * colSizeB * sizeof(float)
    );
    cudaMalloc (
        (void**)&d_C,
        rowSizeA * colSizeB * sizeof(float)
    );

    // 将矩阵数据传递进显存中已经开辟好了的空间
    cublasSetVector (
        rowSizeA * colSizeA,    // 要存入显存的元素个数
        sizeof(float),    // 每个元素大小
        h_A,    // 主机端起始地址
        1,    // 连续元素之间的存储间隔
        d_A,    // GPU 端起始地址
        1    // 连续元素之间的存储间隔
    );
    cublasSetVector (colSizeA * colSizeB, sizeof(float), h_B, 1, d_B, 1);

    // 传递进矩阵相乘函数中的参数,具体含义请参考函数手册.
    float a=1; float b=0;
    // 矩阵相乘.该函数必然将数组解析成列优先数组
    cublasSgemm (
        cuHandle,    // blas 库对象
        CUBLAS_OP_T,    // 矩阵 A 属性参数
        CUBLAS_OP_T,    // 矩阵 B 属性参数
        rowSizeA,    // A, C 的行数
        colSizeB,    // B, C 的列数
        colSizeA,    // A 的列数和 B 的行数
        &a,    // 运算式的 \alpha 值
        d_A,    // A 在显存中的地址
        colSizeA,    // lda
        d_B,    // B 在显存中的地址
        colSizeB,    // ldb
        &b,    // 运算式的 \beta 值
        d_C,    // C 在显存中的地址(结果矩阵)
        rowSizeA    // ldc
    );

    // 从 显存 中取出运算结果至 内存中去
    cublasGetVector (
        rowSizeA * colSizeB,    //  要取出元素的个数
        sizeof(float),    // 每个元素大小
        d_C,    // GPU 端起始地址
        1,    // 连续元素之间的存储间隔
        h_C,    // 主机端起始地址
        1    // 连续元素之间的存储间隔
    );

    for (int i = 0; i < rowSizeA; i++) {
        for (int j = 0; j < colSizeB; j++) {
            C[i][j] = (int)h_C[j * rowSizeA + i];
        }
    }

    // 清理掉使用过的内存
    free (h_A); free (h_B); free (h_C); cudaFree (d_A);
    cudaFree (d_B); cudaFree (d_C);

    return C;
}

// 构造一个随机二维数组(矩阵)
int** uniformMat(int rowSize, int colSize, int minValue, int maxValue) {
    int** mat = new int* [rowSize];
    for (int i = 0; i < rowSize; i++)
        mat[i] = new int[colSize];

    // srand(1024);
    srand((unsigned)time(NULL));  //随机数种子采用系统时钟
    for (int i = 0; i < rowSize; i++) {
        for (int j = 0; j < colSize; j++) {
            mat[i][j] = (int)(rand() % (maxValue - minValue + 1)) + minValue;
        }
    }

    return mat;
}

int main(void)
{
    // 创建并初始化 CUBLAS 库对象
    // 若是CUBLAS对象在主函数中初始化,cuBLAS方法在其他函数中调用,需要将cuHandle传入该函数,并在该函数内创建status对象
    cublasHandle_t cuHandle;
    cublasStatus_t status = cublasCreate(&cuHandle);
    if (status != CUBLAS_STATUS_SUCCESS)
    {
        if (status == CUBLAS_STATUS_NOT_INITIALIZED) {
            cout << "CUBLAS 对象实例化出错" << endl;
        }
        getchar ();
        return EXIT_FAILURE;
    }

    // 矩阵大小定义
    int rowSizeA = 3; // 矩阵A的行数
    int colSizeA = 4; // 矩阵A的列数和矩阵B的行数
    int colSizeB = 2; // 矩阵B的列数

    // 构造一个3行4列的矩阵A,矩阵元素在(0,4)内随机选取
    int **A = uniformMat(rowSizeA, colSizeA, 0, 4);
    // 构造一个4行2列的矩阵B,矩阵元素在(5,9)内随机选取
    int **B = uniformMat(colSizeA, colSizeB, 5, 9);

    // 输出矩阵A和B
    cout << "矩阵 A :" << endl;
    for (int i = 0; i < rowSizeA; i++) {
        for (int j = 0; j < colSizeA; j++) {
            cout << A[i][j] << " ";
        }
        cout << endl;
    }
    cout << endl;

    cout << "矩阵 B :" << endl;
    for (int i = 0; i < colSizeA; i++) {
        for (int j = 0; j < colSizeB; j++) {
            cout << B[i][j] << " ";
        }
        cout << endl;
    }
    cout << endl;

    // 使用cuBLAS进行矩阵乘法运算:C = A * B
    int **C = matMult_cuBLAS(A, B, rowSizeA, colSizeA, colSizeB, cuHandle);

    // 输出矩阵C,即运算结果
    cout << "矩阵 C :" << endl;
    for (int i = 0; i < rowSizeA; i++) {
        for (int j = 0; j < colSizeB; j++) {
            cout << C[i][j] << " ";
        }
        cout << endl;
    }
    cout << endl;

    // 释放 CUBLAS 库对象
    cublasDestroy (cuHandle);
    return 0;
}

在终端输入:

nvcc -lcublas test.cpp -o t
./t

运算结果:

矩阵 A :
1 3 2 0
2 1 2 1
4 3 2 4

矩阵 B :
6 8
7 5
7 6
7 6

矩阵 C :
41 35
40 39
87 83

到此这篇关于C++使用cuBLAS加速矩阵乘法运算的文章就介绍到这了,更多相关C++ cuBLAS矩阵加速运算内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++矩阵运算的实现简单

    利用C++实现矩阵的构造,通过运算符的重载实现矩阵的乘法.加法等.并且实现矩阵形状的打印,矩阵的打印. #include<iostream> #include<memory> #include<assert.h> #include<stdlib.h> using namespace std; class Matrix{ public: Matrix(int row, int col); //构造函数 Matrix(int row, int col, int

  • C++稀疏矩阵的各种基本运算并实现加法乘法

    代码: #include <iostream> #include<malloc.h> #include<cstdio> using namespace std; #define M 4 #define N 4 #define MaxSize 100 typedef int ElemType; typedef struct { int r; int c; ElemType d;///元素值 } TupNode; ///三元组定义 typedef struct { int

  • C++ 中重载和运算符重载加号实现矩阵相加实例代码

     C++ 重载+运算符重载加号 实现矩阵相加 学习C++ 基础知识,这里实现简单的实例,记录下自己学习生活,很简单,大家一起看看吧! 实例代码: #include<iostream> #include<iomanip> using namespace std; class Complex { private: int i,j,n,a[2][3]; public: Complex(); Complex operator+(Complex &c); void display()

  • C++使用cuBLAS加速矩阵乘法运算的实现代码

    本博客主要参考cuBLAS 库 词条实现,与原文不同的是,本博客: 将cuBLAS库的乘法运算进行了封装,方便了算法调用: 将原文的结果转置实现为了不转置,这样可以直接使用计算结果: 测试并更改了乘法参数,解决了原文中更改矩阵大小时报错的问题. 总的来说,本博客的代码利用cuBLAS库实现了两个矩阵相乘,提高了矩阵乘法的计算速度. test.cpp #include "cuda_runtime.h" #include "cublas_v2.h" #include &

  • C++ 利用硬件加速矩阵乘法的实现

    一.矩阵乘法定义 矩阵 A x × y 和 矩阵 B u × v 相乘的前提条件是 y = = u ,并且相乘后得到的矩阵为 C x × v(即 A 的行和 B 的列构成了矩阵 C的行列): 二.矩阵类封装 我们用 C++ 封装了一个 n × m 的矩阵类,用二维数组来存储数据,定义如下: #define MAXN 1000 #define LL __int64 class Matrix { private: int n, m; LL** pkData; public: Matrix() : n

  • Python使用迭代器打印螺旋矩阵的思路及代码示例

    思路 螺旋矩阵是指一个呈螺旋状的矩阵,它的数字由第一行开始到右边不断变大,向下变大, 向左变大,向上变大,如此循环. 螺旋矩阵用二维数组表示,坐标(x,y),即(x轴坐标,y轴坐标). 顺时针螺旋的方向是->右,下,左,上,用数值表示即是x加1格(1,0),y加1格(0,1),x减1格(-1,0),y减1格(0,-1). 坐标从(0,0)开始行走,当超出范围或遇到障碍时切换方向. 螺旋矩阵的打印首先要对n*n的数组进行赋值,根据规律可以看出,每一层都是按照右->下->左->上的顺序

  • 杨氏矩阵查找的JS代码

    复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="

  • C语言解决螺旋矩阵算法问题的代码示例

    赶集网校招就采用了螺旋输出矩阵作为程序题,要求将矩阵螺旋输出如: 图中6*6矩阵线条所示为输出顺序,如果输出正确的话应该输出1~36有序数字.  我想的是这么做的: #include <stdio.h> //#define LEN 1 //#define LEN 2 //#define LEN 3 #define LEN 4 void printClock(int a[][LEN]){//输出函数 int t; int i = 0, m = 0; int j = LEN, n = LEN; w

  • C/C++实现矩阵的转置(示例代码)

    废话不多说,直接上代码 复制代码 代码如下: #include <iostream>using namespace std; const int N = 5; int matrix[5][5] ={    1,2,3,4,5,    1,2,3,4,5,    1,2,3,4,5,    1,2,3,4,5,    1,2,3,4,5}; void swap(int &a,int &b){    a=a^b;    b=a^b;    a=a^b;}void matrix_tr

  • 安装OpenMPI来配合C语言程序进行并行计算

    安装OPENMPI 由于是实验,也不进行多机的配置了,只在虚拟机里安装吧.多个机器的配置可以参考此文 最简单的方法,apt安装 sudo apt-get install libcr-dev mpich2 mpich2-doc 测试 hello.c /* C Example */ #include <mpi.h> #include <stdio.h> int main (int argc, char* argv[]) { int rank, size; MPI_Init (&

  • python中np.multiply()、np.dot()和星号(*)三种乘法运算的区别详解

    为了区分三种乘法运算的规则,具体分析如下: import numpy as np 1. np.multiply()函数 函数作用 数组和矩阵对应位置相乘,输出与相乘数组/矩阵的大小一致 1.1数组场景 A = np.arange(1,5).reshape(2,2) A array([[1, 2],        [3, 4]]) B = np.arange(0,4).reshape(2,2) B array([[0, 1],        [2, 3]]) np.multiply(A,B) #数

  • pytorch中常用的乘法运算及相关的运算符(@和*)

    目录 前言 1.torch.mm 2.torch.bmm 3.torch.mul 4.torch.mv 5.torch.matmul 6.@运算符 7.*运算符 附:二维矩阵乘法 总结 前言 这里总结一下pytorch常用的乘法运算以及相关的运算符(@.*). 总结放前面: torch.mm : 用于两个矩阵(不包括向量)的乘法.如维度为(l,m)和(m,n)相乘 torch.bmm : 用于带batch的三维向量的乘法.如维度为(b,l,m)和(b,m,n)相乘 torch.mul : 用于两

  • Python实现求解斐波那契第n项的解法(包括矩阵乘法+快速幂)

    斐波那契数列 首先我们来定义一下斐波那契数列: 即数列的第0项: 算法一:递归 递归计算的节点个数是O(2ⁿ)的级别的,效率很低,存在大量的重复计算. 比如: f(10) = f(9) + f(8) f(9) = f(8) + f(7) 重复 8 f(8) = f(7) + f(6) 重复 7 时间复杂度是O(2ⁿ),极慢 def F1(n): if n <= 1: return max(n, 0) # 前两项 return F1(n-1)+F1(n-2) # 递归 算法二:记忆化搜索 开一个大

随机推荐