不修改CUDA内核函数输出变量

时间:2014-11-11 12:40:51

标签: c++ object cuda

我正在尝试将对象传递给内核。该对象基本上有两个变量,一个作为输入,另一个作为内核的输出。但是当我启动内核时,输出变量不会改变。但是当我向内核添加另一个变量并将输出值分配给这个变量时,它突然适用于它们。

我在另一个线程(While loop fails in CUDA kernel)中读到,如果内核没有产生任何输出,编译器可以将内核评估为空以进行优化。

因此,我作为唯一内核参数传递的输入/输出对象可能不会被编译器识别为输出?如果这是真的。是否有一种优雅的方式(我想避免添加另一个内核参数),例如编译可以防止这种情况的选项?

这是此对象的类。

class Replica
{
    public :
        signed char gA[1024];
        int MA;
    __device__ __host__ Replica(){
    }   
};

这就是内核基本上是减少总和。

__global__ void sumKerA(Replica* Rd) 
{
    int t = threadIdx.x;
    int b = blockIdx.x;

    __shared__ signed short gAs[1024];
    gAs[t] = Rd[b].gA[t];

    for (unsigned int stride = 1024 >> 1; stride > 0; stride >>= 1){
        __syncthreads();
        if (t < stride){
            gAs[t] += gAs[t + stride];
        }
    }
    __syncthreads();

    if (t == 0){
        Rd[b].MA = gAs[0];
    }
}

最后是我的主持人代码。

int main ()
{
    // replicas - array of objects
    Replica R[128];
    for (int i = 0; i < 128; ++i){
        for (int j = 0; j < 1024; ++j){
            R[i].gA[j] = 2*(rand() % 2) - 1;
        }
        R[i].MA = 0;
    }

    Replica* Rd;

    cudaSetDevice(0);

    cudaMalloc((void **)&Rd,128*sizeof(Replica));
    cudaMemcpy(Rd,R,128*sizeof(Replica),cudaMemcpyHostToDevice);

    dim3 DimBlock(1024,1,1);
    dim3 DimGridA(128,1,1);

    sumKerA <<< DimBlock, DimGridA >>> (Rd);
    cudaThreadSynchronize();

    cudaMemcpy(&R,Rd,128*sizeof(Replica),cudaMemcpyDeviceToHost);
    // cudaMemcpy(&M,Md,128*sizeof(int),cudaMemcpyDeviceToHost);
    for (int i = 0; i < 128; ++i){
        cout << R[i].MA << " ";
    }

    cudaFree(Rd);

    return 0;
}

1 个答案:

答案 0 :(得分:0)

根据您的缩减代码,您似乎打算每个块启动1024个线程。

在这种情况下,这是不正确的:

dim3 DimBlock(1024,1,1);
dim3 DimGridA(128,1,1);

sumKerA <<< DimBlock, DimGridA >>> (Rd);

第一个内核配置参数是网格的。第二个参数是threadblock的维度。如果你想要每个块1024个线程,同时启动128个块,你的内核启动应如下所示:

sumKerA <<< DimGridA, DimBlock >>> (Rd);

如果在代码中添加proper cuda error checking,我预计你会看到内核启动失败,因为使用块变量(blockIdx.x)索引到128个元素的Rd数组会索引超出数组末尾,在原始情况下。

如果修改内核中Rd所指向的副本对象,这是外部可见状态,那么修改这些对象的任何代码都不能被优化掉#34;由编译器。

另请注意,cudaThreadSynchronize()已弃用,而不是cudaDeviceSynchronize()(它们具有相同的行为。)