cuda矩阵相乘-02

本博文主要讲解下基于cuda的矩阵相乘,cuda特别擅长的就是矩阵乘法,而且也比较容易实现。通过矩阵乘法的实现,可以比较容易理解cuda的核心思想。网上也有很多基于cuda实现的矩阵乘法,但是感觉都不完成,要不就是有错,本文给出的代码都是经过验证可行的,希望能够帮助到大家。

矩阵乘法实现方式一:矩阵乘法的逐点实现方式,具体如下图所示

                           

对应实现代码:


   
   
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <cuda_runtime.h>
  4. __global__ void MatMul( int *M, int *N, int *P, int width)
  5. {
  6. int x = threadIdx.x;
  7. int y = threadIdx.y;
  8. float Pervalue = 0;
  9. float elem1 = 0.0,elem2 = 0.0,value = 0.0;
  10. for( int i = 0;i < width;i++)
  11. {
  12. elem1 = M[y * width + i]; //取M矩阵的一行
  13. elem2 = N[i * width + x]; //取N矩阵的一列
  14. value += elem1 * elem2; //求和
  15. }
  16. P[y * width + x] = value;
  17. }
  18. int main()
  19. {
  20. const int ND = 30;
  21. int a[ND][ND],b[ND][ND],c[ND][ND];
  22. int *M,*N,*P;
  23. int width = ND;
  24. int NUM = 900;
  25. dim3 blockSize(ND,ND);
  26. cudaEvent_t start,stop;
  27. float elapsedTime = 0;
  28. cudaEventCreate(&start);
  29. cudaEventCreate(&stop);
  30. //设备端内存分配
  31. cudaMalloc(( void**)&M,ND * ND * sizeof( int));
  32. cudaMalloc(( void**)&N,ND * ND * sizeof( int));
  33. cudaMalloc(( void**)&P,ND * ND * sizeof( int));
  34. //初始化
  35. for( int i = 0;i < ND;i++)
  36. {
  37. for( int j = 0;j < ND;j++)
  38. {
  39. a[i][j] = 2;
  40. b[i][j] = 3;
  41. }
  42. }
  43. int Size = ND * ND;
  44. //数据拷贝,主机到设备
  45. cudaMemcpy(M,a,Size * sizeof( int),cudaMemcpyHostToDevice);
  46. cudaMemcpy(N,b,Size * sizeof( int),cudaMemcpyHostToDevice);
  47. cudaEventRecord(start, 0);
  48. MatMul<<< 1,blockSize>>>(M,N,P,width); //调用核函数
  49. cudaThreadSynchronize();
  50. cudaEventRecord(stop, 0);
  51. cudaEventSynchronize(stop);
  52. cudaEventElapsedTime(&elapsedTime,start,stop);
  53. cudaMemcpy(c,P,Size * sizeof( int),cudaMemcpyDeviceToHost);
  54. printf( "c0 = %d \n",c[ 0][ 0]);
  55. //释放设备内存
  56. cudaFree(M);
  57. cudaFree(N);
  58. cudaFree(P);
  59. return 0;
  60. }

运行结果:

 

矩阵相乘实现方式二:矩阵乘法分块实现,具体如下图所示

                 

具体代码实现:


   
   
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <cuda_runtime.h>
  4. #define TILE_WIDTH 10
  5. //核函数的具体实现
  6. __ global__ void matmul(int *M,int *N,int *P,int width)
  7. {
  8. __shared__ float Mds[TILE_WIDTH][TILE_WIDTH];
  9. __shared__ float Nds[TILE_WIDTH][TILE_WIDTH];
  10. int bx = blockIdx.x;
  11. int by = blockIdx.y;
  12. int tx = threadIdx.x;
  13. int ty = threadIdx.y;
  14. int Col = bx * TILE_WIDTH + tx;
  15. int Row = by * TILE_WIDTH + ty;
  16. int Pervalue = 0;
  17. for( int i = 0;i < width / TILE_WIDTH;i++) //有多少个TILE_WIDTH,每个循环计算一个块的大小
  18. {
  19. Mds[ty][tx] = M[Row * width + (i * TILE_WIDTH + tx)];
  20. Nds[ty][tx] = N[Col + (i * TILE_WIDTH + ty) * width];
  21. __syncthreads();
  22. for( int k = 0;k < TILE_WIDTH;k++) //TILE_WIDTH相乘
  23. Pervalue += Mds[ty][k] * Nds[k][tx];
  24. __syncthreads();
  25. }
  26. P[Row * width + Col] = Pervalue;
  27. }
  28. int main()
  29. {
  30. const int Nd = 30;
  31. int Size = Nd * Nd;
  32. int *M,*N,*P;
  33. int width = Nd / 3;
  34. int a[Nd][Nd];
  35. int b[Nd][Nd];
  36. int c[Nd][Nd];
  37. //线程块以及线程的划分
  38. dim3 gridSize(Nd / width,Nd / width);
  39. dim3 blockSize(width,width);
  40. cudaEvent_t start,stop;
  41. float elapsedTime;
  42. cudaEventCreate(&start);
  43. cudaEventCreate(&stop);
  44. //设备内存分配
  45. cudaMalloc(( void**)&M,Size * sizeof( int));
  46. cudaMalloc(( void**)&N,Size * sizeof( int));
  47. cudaMalloc(( void**)&P,Size * sizeof( int));
  48. //初始化
  49. for( int i = 0;i < Nd;i++)
  50. {
  51. for( int j = 0;j < Nd;j++)
  52. {
  53. a[i][j] = 2;
  54. b[i][j] = 3;
  55. }
  56. }
  57. //数据拷贝,主机到设备
  58. cudaMemcpy(M,a,Size * sizeof( int),cudaMemcpyHostToDevice);
  59. cudaMemcpy(N,b,Size * sizeof( int),cudaMemcpyHostToDevice);
  60. cudaEventRecord(start, 0);
  61. matmul<<<gridSize,blockSize>>>(M,N,P,Nd); //调用核函数
  62. cudaThreadSynchronize();
  63. cudaEventRecord(stop, 0);
  64. cudaEventSynchronize(stop);
  65. cudaEventElapsedTime(&elapsedTime,start,stop);
  66. cudaMemcpy(c,P,Size * sizeof( int),cudaMemcpyDeviceToHost);
  67. printf( "c0 = %d\n",c[ 0][ 0]);
  68. cudaFree(M);
  69. cudaFree(N);
  70. cudaFree(P);
  71. return 0;
  72. }

运行结果:

本文也参考了网上的一些资料,主要是做了一定的修改以及程序的完备,图片就直接网上copy的,水平有限,有不当之处,请指教,谢谢!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值