CUDA基本操作错误

时间:2011-10-29 11:31:05

标签: cuda gpu

我的全局功能如下:

__global__ void sort(float* D,  float* new_D)
{
        int  i  = threadIdx.x + blockIdx.x * blockDim.x ;   // i>=0 && i<N

        new_D[ 4*(i/4)+i%2]   = D[ 4*(i/4)+2*(i%2) ];
}

它被称为:

  

排序&LT;&LT;≤(N / threadperblock),threadperblock&GT;&GT;&GT;(d,new_D);

当我以单精度定义“N”超过2048时,该功能操作不正确, 当我得到错误答案时,双精度4096。出了什么问题?

2 个答案:

答案 0 :(得分:1)

绝对不可能说出为什么您可能无法从代码中获得预期结果。一个明显的错误来源是未初始化的内存。您的索引方案仅将值分配给new_D的一半,因此如果您没有采取有意的步骤将值分配给其他值,那么结果将包含未初始化的值以及GPU版本与之间的错误比较或意外值主机实施可能会发生。

为了说明我的观点,这里有一个完整的repro案例,可以在任何输入大小上正常工作,这是2的幂:

#include <stdlib.h>
#include <assert.h>
#include <stdio.h>

const int N = (2<<20);

__global__ void sort(float* D,  float* new_D)
{
    int  i  = threadIdx.x + blockIdx.x * blockDim.x ;   // i>=0 && i<N
    new_D[ 4*(i/4)+i%2]   = D[ 4*(i/4)+2*(i%2) ];
}

__host__ void host_sort(const float* D,  float* new_D)
{
    for(int i=0; i<N; i++)
        new_D[ 4*(i/4)+i%2]   = D[ 4*(i/4)+2*(i%2) ];
}

int main(void)
{

    const size_t dsize =sizeof(float) * size_t(N);

    float *D = (float *)malloc(dsize);  
    float *new_D = (float *)malloc(dsize);  
    for(int i=0; i<N; i++) {
        D[i] = (float)i;
        new_D[i] = -999.0f;
    }

    float *D_gpu, *new_D_gpu;
    assert( cudaMalloc((void**)&D_gpu, dsize) == cudaSuccess );
    assert( cudaMemcpy(D_gpu, D, dsize, cudaMemcpyHostToDevice) == cudaSuccess); 
    assert( cudaMalloc((void**)&new_D_gpu, dsize) == cudaSuccess );
    assert( cudaMemcpy(new_D_gpu, new_D, dsize, cudaMemcpyHostToDevice) == cudaSuccess); 
    dim3 blocksize = dim3(128,1,1);
    dim3 gridsize = dim3(N/blocksize.x,1,1);

    host_sort(D, new_D);

    sort<<< gridsize, blocksize >>>(D_gpu,new_D_gpu);
    assert( cudaPeekAtLastError() == cudaSuccess );
    assert( cudaThreadSynchronize() == cudaSuccess );

    float *new_D_host = (float *)malloc(dsize); 
    assert( cudaMemcpy(new_D_host, new_D_gpu, dsize, cudaMemcpyDeviceToHost) == cudaSuccess); 

    for(int i=0; i<N; i++) 
        assert( new_D_host[i] == new_D[i] );

    return 0;
}

您应该知道内核中有一半的线程正在有效地执行冗余分配,并因此不必要地烧掉内存带宽。

答案 1 :(得分:0)

threadperblock值是多少?当你在单一的精确和双重精确的工作时它会改变吗?

我要问的原因--- threadIdx.x,blockIdx.x和blockDim.x工作为unsigned short。他们可以容纳的最大值是65535,直到您将其转换为int。如果你超过这个值,那么在进行数学运算时,你会得到非常奇怪的结果。

试试这个:

int i=blockDim.x;
i=i*blockIdx.x+threadIdx.x