CUDA阵列的双重检查和修复

时间:2016-03-25 18:56:56

标签: arrays cuda

我想在CUDA中创建随机int数组。我需要检查数组索引0-9,10-19的双重性......并修复它们。

任何想法,如何使它有效?我真的不想互相检查每个元素。

这是我的代码:

__global__ void generateP(int *d_p, unsigned long seed)
{
    int i = X * blockIdx.x + threadIdx.x * X;

    int buffer[X];

    curandState state;
    curand_init(seed, i, 0, &state);

    for (int j = 0; j < X; j++)
    {
        float random = HB + (curand_uniform(&state) * (LB - HB));
        buffer[j] = (int)truncf(random);
    }

    // TODO unique check and repair duplicity

    for (int k = 0; k < X; k++)
    {
        d_p[i] = buffer[k];
        i++;
    }   
}

CUDA中是否存在某种包含功能?谢谢你的帮助。

1 个答案:

答案 0 :(得分:1)

你真的在这里问错了问题。您应该寻找一种随机排序唯一值列表的方法,而不是通过重复搜索和替换重复项来尝试填充具有唯一随机数的列表,直到您拥有唯一列表。后者非常低效,并且不适合像CUDA这样的数据并行执行模型。

有一些简单,强大的算法可随机混洗值列表,这些算法只需要最多N次调用随机生成器,以便对一组N值进行混洗。 Fisher-Yates shuffle几乎普遍用于此。

我不打算对这段代码做太多评论,只是说它说明了这样做的一种方法,每个列表使用一个线程。它不是一个高效的,只是一个让你入门的教学示例。我认为它可能接近你的要求(更多的是基于你之前对这个问题的尝试而不是这个)。我建议你把它作为一个引导来编写你自己的实现,它可以做任何你想做的事情。

#include <ctime>
#include <iostream>
#include <curand_kernel.h>

struct source
{
    int baseval;
    __device__ source(int _b) : baseval(_b) {};
    __device__ int operator()(int v) { return baseval + v; };
};

__device__ int urandint(int minval, int maxval, curandState_t& state)
{
    float rval = curand_uniform(&state);
    rval *= (float(maxval) - float(minval) + 0.99999999f);
    rval += float(minval);
    return (int)truncf(rval);
}

template<int X>
__global__ void kernel(int* out, int N, unsigned long long seed)
{
    int tidx = threadIdx.x + blockIdx.x * blockDim.x;
    if (tidx < N) {
        curandState_t state;
        curand_init(seed, tidx, 0, &state);

        int seq[X];
        source vals(tidx * X);
        // Fisher Yeats Shuffle straight from Wikipedia
#pragma unroll
        for(int i=0; i<X; ++i) {
            int j = urandint(0, i, state);
            if (j != i)
                seq[i] = seq[j];
            seq[j] = vals(i);
        }

        // Copy local shuffled sequence to output array
        int* dest = &out[X * tidx];
        memcpy(dest, &seq[0], X * sizeof(int));
    }
}

int main(void) 
{
    const int X = 10;
    const int nsets = 200;

    int* d_result;
    size_t sz = size_t(nsets) * sizeof(int) * size_t(X);
    cudaMalloc((void **)&d_result, sz);
    int tpb = 32;
    int nblocks = (nsets/tpb) + ((nsets%tpb !=0) ? 1 : 0);
    kernel<X><<<nblocks, tpb>>>(d_result, nsets, std::time(0));

    int h_result[nsets][X];
    cudaMemcpy(&h_result[0][0], d_result, sz, cudaMemcpyDeviceToHost);

    for(int i=0; i<nsets; ++i) {
        std::cout << i << " : ";
        for(int j=0; j<X; ++j) {
            std::cout << h_result[i][j] << ",";
        }
        std::cout << std::endl;
    }

    cudaDeviceReset();
    return 0;
}