0

我正在尝试学习一些 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}

任务是对每个组中的向量 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
}

如果可能的话,谁能解释一下我该怎么做?

4

2 回答 2

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

于 2013-10-29T11:09:11.247 回答
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;
 }
于 2013-10-30T10:50:02.980 回答