C++使用cuBLAS加速矩陣乘法運算的實現代碼
更新時間:2021年09月07日 10:50:47 作者:白水baishui
這篇文章主要介紹了C++使用cuBLAS加速矩陣乘法運算,將cuBLAS庫的乘法運算進行了封裝,方便了算法調用,具體實現代碼跟隨小編一起看看吧
本博客主要參考cuBLAS 庫 詞條實現,與原文不同的是,本博客:
- 將cuBLAS庫的乘法運算進行了封裝,方便了算法調用;
- 將原文的結果轉置實現為了不轉置,這樣可以直接使用計算結果;
- 測試并更改了乘法參數,解決了原文中更改矩陣大小時報錯的問題。
總的來說,本博客的代碼利用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) // 需要開辟空間的字節(jié)數
);
cudaMalloc (
(void**)&d_B,
colSizeA * colSizeB * sizeof(float)
);
cudaMalloc (
(void**)&d_C,
rowSizeA * colSizeB * sizeof(float)
);
// 將矩陣數據傳遞進顯存中已經開辟好了的空間
cublasSetVector (
rowSizeA * colSizeA, // 要存入顯存的元素個數
sizeof(float), // 每個元素大小
h_A, // 主機端起始地址
1, // 連續(xù)元素之間的存儲間隔
d_A, // GPU 端起始地址
1 // 連續(xù)元素之間的存儲間隔
);
cublasSetVector (colSizeA * colSizeB, sizeof(float), h_B, 1, d_B, 1);
// 傳遞進矩陣相乘函數中的參數,具體含義請參考函數手冊.
float a=1; float b=0;
// 矩陣相乘.該函數必然將數組解析成列優(yōu)先數組
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, // 連續(xù)元素之間的存儲間隔
h_C, // 主機端起始地址
1 // 連續(xù)元素之間的存儲間隔
);
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)
{
// 創(chuàng)建并初始化 CUBLAS 庫對象
// 若是CUBLAS對象在主函數中初始化,cuBLAS方法在其他函數中調用,需要將cuHandle傳入該函數,并在該函數內創(chuàng)建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矩陣加速運算內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C++實現CreatThread函數主線程與工作線程交互的方法
這篇文章主要介紹了C++實現CreatThread函數主線程與工作線程交互的方法,是Windows應用程序設計中非常實用的方法,需要的朋友可以參考下2014-10-10

