关闭

cublas库实现矩阵乘法(任意维数)

659人阅读 评论(1) 收藏 举报
分类:

话不多说,直接进入主题

cublas是CUDA上矩阵运算的库,可以在gpu上实现很高的效率。然而关于它的使用,并没有详细的中文资料

笔者,经过多次调试成功,分享一点儿心得

#include <iostream>
#include <cstdlib>
#include <cublas_v2.h>
// Multiply the arrays A and B on GPU and save the result in C
// C(m,n) = A(m,k) * B(k,n)
//计算过程
void gpu_blas_mmul(const float *A, const float *B, float *C, const int m, const int k, const int n) {
int lda=m,ldb=k,ldc=m;
const float alf = 1;
const float bet = 0;
const float *alpha = &alf;
const float *beta = &bet;


// Create a handle for CUBLAS
cublasHandle_t handle;
cublasCreate(&handle);


// Do the actual multiplication
cublasSgemm(handle, CUBLAS_OP_N, CUBLAS_OP_N, m, n, k, alpha, A, lda, B, ldb, beta, C, ldc);


// Destroy the handle
cublasDestroy(handle);
}


int main(){
int row1=5;
int column1 = 10;
int row2 = 10;
int column2 = 5;


int result[5][5];
//内存中分配内存空间
float *h_A = (float *)malloc(row1 * column1 * sizeof(float));
float *h_B = (float *)malloc(row2 * column2 * sizeof(float));
float *h_C = (float *)malloc(row1 * column2 * sizeof(float));
//实现内存中数组的复制
for(int i = 0; i < row1; i++){
for(int j = 0; j < column1; j++)
h_A[i*column1 + j]=i;


}


for(int i = 0; i < row2; i++){
for(int j = 0; j < column2; j++)
h_B[i*column2 + j]=j;


}


//打印数组
for(int i=0;i<row1;i++)
{for(int j=0;j<column1;j++)
printf("%.3f ",h_A[i*column1+j]);
printf("\n");
}


//打印数组
for(int i=0;i<row2;i++)
{for(int j=0;j<column2;j++)
printf("%.3f ",h_B[i*column2+j]);
printf("\n");
}
// Allocate 3 arrays on GPU
float *d_A, *d_B, *d_C;
cudaMalloc(&d_A,row1 * column1 * sizeof(float));
cudaMalloc(&d_B,row2 * column2 * sizeof(float));
cudaMalloc(&d_C,row1 * column2 * sizeof(float));




// If you already have useful values in A and B you can copy them in GPU:
cudaMemcpy(d_A,h_A,row1 * column1 * sizeof(float),cudaMemcpyHostToDevice);
cudaMemcpy(d_B,h_B,row2 * column2 * sizeof(float),cudaMemcpyHostToDevice);


gpu_blas_mmul(d_B, d_A, d_C, row1, row2, column2);


// Copy (and print) the result on host memory
cudaMemcpy(h_C,d_C,row1 * column2 * sizeof(float),cudaMemcpyDeviceToHost);
for(int i = 0; i < row1; i++){
for(int j = 0; j < column2; j++)
result[i][j] = (int)h_C[j * row1 + i];


}


//打印数组
for(int i=0;i<row1;i++)
{for(int j=0;j<column2;j++)
printf("%d ",result[i][j]);
printf("\n");
}


//Free GPU memory
cudaFree(d_A);
cudaFree(d_B);
cudaFree(d_C);


// Free CPU memory
free(h_A);
free(h_B);
free(h_C);
getchar();
return 0;
}


我是想用cublas实现任意维矩阵乘法运算。

cublasSgemm(handle, CUBLAS_OP_N, CUBLAS_OP_N, m, n, k, alpha, A, lda, B, ldb, beta, C, ldc);

cublasHandle_t handle用来分配句柄

第二个参数和第三个参数,用来说明,矩阵是否转置

在cuda中二维数组是按照列存储的,在c中二维数组按照行存储,在c语言中的一个矩阵(二维数组)A = M X K, B = N X K, C = A * Bt = M x N


对于cuda而言(列存储),看到的A矩阵是K x M, B 是 K x N, 计算的C = Bt * A = N x M

计算结果C矩阵在c语言看来就是按照行存储的 M x N

A(m x k)B(k x n)

至于lda,ldb,ldc代表什么呢,leading dimension a的缩写,分表代表,A,B,C的leading维,也就是他们的行数


另一个需要注意的地方,

 gpu_blas_mmul(d_B, d_A, d_C, row1, row2, column2);

要把d_B写在前边,因为cublas按列来存数数据,相当于对它转置了,最后得到的结果也是转置的,

切记,切记!

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:37697次
    • 积分:999
    • 等级:
    • 排名:千里之外
    • 原创:58篇
    • 转载:27篇
    • 译文:2篇
    • 评论:1条
    最新评论