本博客主要參考cuBLAS 庫 詞條實現,與原文不同的是,本博客:
總的來說,本博客的代碼利用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