使用CUDA生成排列

时间:2013-11-13 04:31:54

标签: c arrays cuda

我正在阅读有关CUDA的内容,我尝试实现一个简单的代码来创建array {a,b,c,d}的每个可能的排列,但我不知道如何实现CUDA方式(因为我读到的所有示例都是形式为a[blockIdx.x] = b[blockIdx.x] + c[blockIdx.x])。

任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:3)

下面是CUDA中并行置换生成器的一种有点天真的实现。该示例旨在生成ABCD的所有可能排列。

由于可以通过将第一个符号固定到X并附加剩余符号的所有可能排列来生成所有可能的排列,然后将第一个符号更改为,例如Y并执行在上面的过程中,代码背后的简单想法是指定4个线程来完成工作,每个线程都引用不同的初始符号。

第一个符号后面的排列是以规范的方式评估的,即递归。

显然,下面的代码可以更加通用,也许可以改进,但是它应该给你一个粗略的想法。

#include <stdio.h>

inline void GPUassert(cudaError_t code, char * file, int line, bool Abort=true)
{
    if (code != 0) {
        fprintf(stderr, "GPUassert: %s %s %d\n", cudaGetErrorString(code),file,line);
        if (Abort) exit(code);
    }       
}

#define GPUerrchk(ans) { GPUassert((ans), __FILE__, __LINE__); }

__host__ __device__ void swap(char *x, char *y)
{
    char temp;
    temp = *x;
    *x = *y;
    *y = temp;
}

__device__ void permute_device(char *a, int i, int n, int tid, int* count) 
{
    if (i == n) { 
        char b[4]; char* c = a - 1; 
        b[0] = c[0]; b[1] = c[1]; b[2] = c[2]; b[3] = c[3];
        printf("Permutation nr. %i from thread nr. %i is equal to %s\n", count[0], tid, c); count[0] = count[0] + 1; 
    }
    else
    {
        for (int j = i; j <= n; j++)
        {
            swap((a+i), (a+j));
            permute_device(a, i+1, n, tid, count);
            swap((a+i), (a+j)); //backtrack
        }
    }
} 

__global__ void permute_kernel(char* d_A, int size) {

    int tid = threadIdx.x + blockIdx.x * blockDim.x;
    int count[1]; count[0] = 0;

    char local_array[4];

    for (int i=0; i<size; i++) local_array[i] = d_A[i];

    swap(local_array+threadIdx.x,local_array);
    permute_device(local_array+1,0,2,tid,count);

}

int main()
{
    char h_a[] = "ABCD";

    char* d_a; cudaMalloc((void**)&d_a,sizeof(h_a));
    GPUerrchk(cudaMemcpy(d_a, h_a, sizeof(h_a), cudaMemcpyHostToDevice));

    printf("\n\n Permutations on GPU\n");
    permute_kernel<<<1,4>>>(d_a, 4);
    GPUerrchk(cudaPeekAtLastError());
    GPUerrchk(cudaDeviceSynchronize());

    getchar();
    return 0;
}

答案 1 :(得分:-2)

我想知道你的组合是否成对。

  1. 考虑数组的长度。(n)
  2. 想想组合情结。 (n ^ 2,成对)
  3. 选择并行计算的方法。 (使用块id作为添加偏移量,并将线程id作为基础值。例如,array(threadid)+ array(threadid + offset))
  4. 所以你的内核应该这样写:

    template<typename T>
    __global__ void 
    combination(T* in, T* out) {
      int tid = threadId.x;
      int bid = blockId.x+1;
      out[tid+bid*blockDim.x] = in[tid]+in[(tid+bid)%arrlen];     //0+1, 1+2,..., 0+2, 1+3
    }
    

    您可以使用gridDim(arrlen)blockDim(arrlen)调用内核。