服务器之家

服务器之家 > 正文

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

时间:2021-12-30 15:31     来源/作者:白水baishui

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

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

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

test.cpp

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#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矩阵加速运算内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/baishuiniyaonulia/article/details/120119380

标签:

相关文章

热门资讯

yue是什么意思 网络流行语yue了是什么梗
yue是什么意思 网络流行语yue了是什么梗 2020-10-11
背刺什么意思 网络词语背刺是什么梗
背刺什么意思 网络词语背刺是什么梗 2020-05-22
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
蜘蛛侠3英雄无归3正片免费播放 蜘蛛侠3在线观看免费高清完整
蜘蛛侠3英雄无归3正片免费播放 蜘蛛侠3在线观看免费高清完整 2021-08-24
2021年耽改剧名单 2021要播出的59部耽改剧列表
2021年耽改剧名单 2021要播出的59部耽改剧列表 2021-03-05
返回顶部