用CUDA求和两个完整的向量

时间:2013-10-29 10:00:13

标签: vector cuda parallel-processing

我正在尝试学习一些cuda,我无法弄清楚如何解决以下情况:

考虑两组G1和G2:

  1. G1有2个向量,每个元素有3个元素a1 = {2,5,8},b1 = {8,4,6}
  2. G2有2个向量,每个元素有3个元素a2 = {7,3,1}     和b2 = {4,2,9}
  3. 任务是对每个组中的向量a和b求和并返回一个已排序的c向量,所以:

    G1 will give c1 = {10,9,14) => (sort algorithm) =>  c1 = {9,10,14}
    G2 will give c2 = {11,5,10) => (sort algorithm) =>  c1 = {5,10,11}
    

    如果我有一个拥有92个cuda核心的gforce,我想创建92个G组并将所有总和并行,所以

    core 1-> G1 -> c1 = a1 + b1 -> sort c1 -> return c1
    core 2-> G2 -> c2 = a2 + b2 -> sort c2 -> return c2
    
    ....
    core 92-> G92 -> c92 = a92 + b92 -> sort c92 -> return c92
    

    下面的内核并行地将两个向量相加并返回另一个向量:

    __global__ void add( int*a, int*b, int*c )
    {
       c[blockIdx.x] = a[blockIdx.x] + b[blockIdx.x];
    }
    

    我无法理解的是如何让内核处理整个向量而不仅仅是一个 向量的元素,它们返回一个完整的向量。

    这样的事情:

    __global__ void add( int*a, int*b, int*c, int size )
    {
        for (int i = 0; i < size ; i++)
    
        c[i] = a[i] + b[i];
    
        //sort c
    }
    

    有人可以解释我是否有可能以及怎么做?

2 个答案:

答案 0 :(得分:1)

92个3-D向量可以看作1 276-D向量,然后你可以使用单向量添加内核来添加它们。推动将是一种更简单的方法。

更新

如果您的矢量只是3-D,您可以使用顺序方法在计算后立即对元素进行排序。

如果您的向量具有更高的维度,则可以考虑使用cub::BlockRadixSort。我们的想法是首先为每个线程/块添加一个向量,然后使用cub::BlockRadixSort对块内的向量进行排序。

http://nvlabs.github.io/cub/classcub_1_1_block_radix_sort.html

答案 1 :(得分:1)

这是一个小例子。它使用cudaMallocPitchcudaMemcpy2D。我希望它能为您提供解决特定问题的指导原则:

#include<stdio.h>
#include<cuda.h>
#include<cuda_runtime.h>
#include<device_launch_parameters.h>
#include<conio.h>

#define N 92
#define M 3

__global__ void test_access(float** d_a,float** d_b,float** d_c,size_t pitch1,size_t pitch2,size_t pitch3)
{
    int idx = threadIdx.x;

    float* row_a = (float*)((char*)d_a + idx*pitch1);
    float* row_b = (float*)((char*)d_b + idx*pitch2);
    float* row_c = (float*)((char*)d_c + idx*pitch3);

    for (int i=0; i<M; i++) row_c[i] = row_a[i] + row_b[i];

    printf("row %i column 0 value %f \n",idx,row_c[0]);
    printf("row %i column 1 value %f \n",idx,row_c[1]);
    printf("row %i column 2 value %f \n",idx,row_c[2]);

}

/********/
/* MAIN */
/********/

int main()
{
    float a[N][M], b[N][M], c[N][M];
    float **d_a, **d_b, **d_c;

    size_t pitch1,pitch2,pitch3; 
    cudaMallocPitch(&d_a,&pitch1,M*sizeof(float),N);
    cudaMallocPitch(&d_b,&pitch2,M*sizeof(float),N);
    cudaMallocPitch(&d_c,&pitch3,M*sizeof(float),N);

    for (int i=0; i<N; i++)
        for (int j=0; j<M; j++) {
            a[i][j] = i*j;
            b[i][j] = -i*j+1;
            }

     cudaMemcpy2D(d_a,pitch1,a,M*sizeof(float),M*sizeof(float),N,cudaMemcpyHostToDevice);
     cudaMemcpy2D(d_b,pitch2,b,M*sizeof(float),M*sizeof(float),N,cudaMemcpyHostToDevice);

     test_access<<<1,N>>>(d_a,d_b,d_c,pitch1,pitch2,pitch3);

     cudaMemcpy2D(c,M*sizeof(float),d_c,pitch3,M*sizeof(float),N,cudaMemcpyDeviceToHost);

    for (int i=0; i<N; i++)
         for (int j=0; j<M; j++) printf("row %i column %i value %f\n",i,j,c[i][j]);

    getch();
    return 0;
 }