我的全局功能如下:
__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。出了什么问题?
答案 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