zoukankan      html  css  js  c++  java
  • CUDA学习之一:二维矩阵加法

      今天忙活了3个小时,竟然被一个苦恼的CUDA小例程给困住了,本来是参照Rachal zhang大神的CUDA学习笔记来一个模仿,结果却自己给自己糊里糊涂,最后还是弄明白了一些。

      RZ大神对CUDA关于kernel,memory的介绍还是蛮清楚,看完决定写一个二维数组的加法。如果是C++里的加法,那就简单了,用C[i][j] = A[i][j] +B[i][j]就可以。

    1 void CppMatAdd(int A[M][N],int B[M][N],int C[M][N]){
    2     for(int i=0;i<M;i++)
    3         for(int j=0;j<N;j++)
    4             C[i][j] = A[i][j] + B[i][j];
    5 }
    1 int main()
    2 {
    3     int a[M][N] = {1,2,3,4,5,6,7,8,9,10,11,12};
    4     int b[M][N] = {1,2,3,4,5,6,7,8,9,10,11,12};
    5     int c[M][N] ;
    6         CppMatAdd(a,b,c);
    7     std::cout<<c[0][0];
    8 } 

    运行上面代码,就可以实现二维矩阵(也就是数组)的加法运算。

    但是CUDA计算是在GPU上实现的,要划分出专门的内存区域给GPU做运算,结果就是,我们必须划分出主机内存、设备内存分别供CPU、GPU访问。

    对于一维的情况,我们设置好主机变量,设备变量即可。具体可以参找RZ的博客。

    但是二维的情况麻烦就来了,最一开始我也是设置出主机变量,设备变量,一一对应的分配内存,拷贝数据,GPU运算,最后考出结果。但是发现怎么调试结果都不对,最主要的原因是c++的二维数组实际上是一维数组的指针,所以,无法按照一位数组的模式去拷贝数据,结果相映的写法就麻烦许多,其实说到底还是还原成一维数组的方法去做的加法运算,代码如下,具体就不想赘述了,代码能力有限,慢慢来吧,今天算是把指针弄的更清楚了。

    /*--------------------------------------------
    * Date:2015-3-18 
    * Author:李根
    * FileName:.cpp        
    * Description:CUDA二维数组加法
    ------------------------------------------------*/ 
    #include "cuda_runtime.h"
    #include "device_launch_parameters.h"
    #include <iostream>
    #include <stdio.h>
    
    static const int M = 4;
    static const int N = 3;
    
    //矩阵加法的kernel
    __global__ void addMat(int **A,int **B,int **C)
    {
        int i = blockIdx.x * blockDim.x + threadIdx.x;
        int j = blockIdx.y * blockDim.y + threadIdx.y;
        if(i < M && j < N)
            C[i][j] = A[i][j] + B[i][j];
    }
    
    int main()
    {int **A = (int **)malloc(M*sizeof(int *));  //host memory
        int **B = (int **)malloc(M*sizeof(int *));  //host memory
        int **C = (int **)malloc(M*sizeof(int *));  //host memory
        int *dataA =(int *)malloc(M*N*sizeof(int )); //host memory data
        int *dataB = (int *)malloc(M*N*sizeof(int )); //host memory data
        int *dataC =(int *)malloc(M*N*sizeof(int )); //host memory data
    
        int **dev_A ;  //device memory
        int **dev_B ;  //device memory
        int **dev_C ;  //device memory
        int *dev_dataA ;  //device memory  data
        int *dev_dataB ;  //device memory  data
        int *dev_dataC ;  //device memory  data
    
        cudaMalloc((void**)(&dev_A), M*sizeof(int*)); 
        cudaMalloc((void**)(&dev_dataA), M*N*sizeof(int));
        cudaMalloc((void**)(&dev_B), M*sizeof(int*)); 
        cudaMalloc((void**)(&dev_dataB), M*N*sizeof(int));
        cudaMalloc((void**)(&dev_C), M*sizeof(int*)); 
        cudaMalloc((void**)(&dev_dataC), M*N*sizeof(int));
    
        for(int i=0;i<M*N;i++)
        {
            dataA[i] = i;
            dataB[i] = i+1;
            dataC[i] =0;
        }
        
        cudaMemcpy((void*)(dev_dataA), (void*)(dataA), M*N*sizeof(int*), cudaMemcpyHostToDevice);
        cudaMemcpy((void*)(dev_dataB), (void*)(dataB), M*N*sizeof(int*), cudaMemcpyHostToDevice);
    
    
        for(int i=0;i<M;i++)
        {
            A[i] = dev_dataA + N*i;
            B[i] = dev_dataB + N*i;
            C[i] = dev_dataC + N*i;
        }
                
        
        cudaMemcpy((void*)(dev_A), (void*)(A), M*sizeof(int*), cudaMemcpyHostToDevice);
        cudaMemcpy((void*)(dev_B), (void*)(B), M*sizeof(int*), cudaMemcpyHostToDevice);
        cudaMemcpy((void*)(dev_C), (void*)(C), M*sizeof(int*), cudaMemcpyHostToDevice);
            
        dim3 threadPerBlock(16,16);
        dim3 numBlocks((N+threadPerBlock.x-1)/(threadPerBlock.x), (M+threadPerBlock.y-1)/(threadPerBlock.y));  
        addMat<<<numBlocks,threadPerBlock>>>(dev_A,dev_B,dev_C);
        cudaMemcpy((void*)(dataC), (void*)(dev_dataC), M*N*sizeof(int), cudaMemcpyDeviceToHost);
        for(int i=0;i<M*N;i++)        
            std::cout<<dataC[i]<<" ";
        cudaFree((void*)dev_dataC);  
        cudaFree((void*)dev_C);  
        free(C);  
        free(dataC);  
        cudaFree((void*)dev_dataB);  
        cudaFree((void*)dev_B);  
        free(B);  
        free(dataB); 
        cudaFree((void*)dev_dataA);  
        cudaFree((void*)dev_A);  
        free(A);  
        free(dataA); 
        getchar();
    }

     博客恢复更新,慢慢的积累吧

  • 相关阅读:
    struts2的核心和工作原理
    Java操作redis【二十】
    优化【十九】
    管线【十八】
    服务器管理【十七】
    虚拟内存【十六】
    Eclipse:使用findBugs预先检测错误
    linux命令学习(1)
    Android中Linux suspend/resume流程
    Ubuntu12.04下eclipse提示框黑色背景色的修改方法
  • 原文地址:https://www.cnblogs.com/jugg1024/p/4349243.html
Copyright © 2011-2022 走看看