Cuda 大型阵列的前缀扫描
我想使用GPUgem中的指令为大型数组编写前缀扫描,这是我并行类的家庭作业。我确实遵循了书中的所有步骤,但我的代码仍然不起作用。我让它适用于4096大小的阵列,但不适用于更大的阵列。这是我的密码:Cuda 大型阵列的前缀扫描,cuda,gpgpu,Cuda,Gpgpu,我想使用GPUgem中的指令为大型数组编写前缀扫描,这是我并行类的家庭作业。我确实遵循了书中的所有步骤,但我的代码仍然不起作用。我让它适用于4096大小的阵列,但不适用于更大的阵列。这是我的密码: #include <stdio.h> #include <sys/time.h> #define THREADS 1024 typedef int mytype; __global__ void phaseI(mytype *g_odata, mytype *g_idata,
#include <stdio.h>
#include <sys/time.h>
#define THREADS 1024
typedef int mytype;
__global__ void phaseI(mytype *g_odata, mytype *g_idata, int n, mytype *aux)
{
__shared__ mytype temp[THREADS];
const int tid1 = threadIdx.x;
int offset = 1;
temp[2*tid1] = g_idata[2*tid1]; // load input into shared memory
temp[2*tid1+1] = g_idata[2*tid1+1];
for (int d = THREADS>>1; d > 0; d >>= 1) // build sum in place up the tree
{
__syncthreads();
if (tid1 < d)
{
int ai = offset*(2*tid1+1)-1;
int bi = offset*(2*tid1+2)-1;
temp[bi] += temp[ai];
}
offset *= 2;
}
__syncthreads();
if (tid1 == 0) {
aux[blockIdx.x] = temp[THREADS - 1];
temp[THREADS - 1] = 0;
}
for (int d = 1; d < THREADS; d *= 2) // traverse down tree & build scan
{
offset >>= 1;
__syncthreads();
if (tid1 < d)
{
int ai = offset*(2*tid1+1)-1;
int bi = offset*(2*tid1+2)-1;
mytype t = temp[ai];
temp[ai] = temp[bi];
temp[bi] += t;
}
}
__syncthreads();
g_odata[2*thid] = temp[2*thid]; // write results to device memory
g_odata[2*thid+1] = temp[2*thid+1];
}
__global__ void phaseII(mytype *g_odata, mytype *aux, int n)
{
const int tid1 = threadIdx.x;
const int B = (n / THREADS);
int offset = 1;
for (int d = B>>1; d > 0; d >>= 1) // build sum in place up the tree
{
__syncthreads();
if (tid1 < d)
{
int ai = offset*(2*tid1+1)-1;
int bi = offset*(2*tid1+2)-1;
temp[bi] += temp[ai];
}
offset *= 2;
}
__syncthreads();
if (tid1 == 0 && blockIdx.x == 0) {
aux[B - 1] = 0;
}
for (int d = 1; d < B; d *= 2) // traverse down tree & build scan
{
offset >>= 1;
__syncthreads();
if (tid1 < d)
{
int ai = offset*(2*tid1+1)-1;
int bi = offset*(2*tid1+2)-1;
mytype t = temp[ai];
temp[ai] = temp[bi];
temp[bi] += t;
}
}
__syncthreads();
g_odata[2*thid] += aux[blockIdx.x];
g_odata[2*thid+1] += aux[blockIdx.x];
}
int main(int argc, char *argv[])
{
if (argc != 2) {
printf("usage: %s n\n", argv[0]);
return -1;
}
const int n = atoi(argv[1]);
mytype *h_i, *d_i, *h_o, *d_o, *d_temp;
const int size = n * sizeof(mytype);
h_i = (mytype *)malloc(size);
h_o = (mytype *)malloc(size);
if ((h_i == NULL) || (h_o == NULL)) {
printf("malloc failed\n");
return -1;
}
for (int i = 0; i < n; i++) {
h_i[i] = i;
h_o[i] = 0;
}
cudaMalloc(&d_i, size);
cudaMalloc(&d_temp, (n / THREADS) );
cudaMalloc(&d_o, size);
cudaMemset(d_o, 0, size);
cudaMemset(d_temp, 0, (n / THREADS));
cudaMemcpy(d_i, h_i, size, cudaMemcpyHostToDevice);
int blocks = n / THREADS;
phaseI<<<blocks, THREADS / 2 >>>(d_o, d_i, n, d_temp);
phaseII<<<blocks, THREADS / 2>>>(d_o, d_temp, n);
cudaThreadSynchronize();
cudaMemcpy(h_o, d_o, size, cudaMemcpyDeviceToHost);
printf("\n");
for (int i = 0; i < n ; i++) {
printf(" %d", h_o[i]);
}
printf("\n\n");
return 0;
}
#包括
#包括
#定义线程1024
typedef int-mytype;
__全局无效阶段(mytype*g\U odata、mytype*g\U idata、int n、mytype*aux)
{
__共享的_uuuMyType临时[线程];
const int tid1=threadIdx.x;
int offset=1;
temp[2*tid1]=g_idata[2*tid1];//将输入加载到共享内存中
温度[2*tid1+1]=g_idata[2*tid1+1];
for(int d=THREADS>>1;d>0;d>>=1)//在树上就地构建sum
{
__同步线程();
如果(tid1>=1;
__同步线程();
如果(tid1>1;d>0;d>>=1)//在树上就地构建sum
{
__同步线程();
如果(tid1>=1;
__同步线程();
如果(tid1
有人知道我做错了什么吗?我在您的代码中看到的一个可能错误如下:
aux[thid] = temp[THREADS];
如果您的temp
数组是temp[1024]
,正如您所说,并且每个块有1024个线程,那么如果线程是1024个,temp[threads]将访问您的共享内存数组,超出范围(一个超出范围)。1024个元素的数组只有从0到1023的有效索引
除此之外,您似乎在询问如何从共享内存数组(temp
)中取出最后一个元素,并将其放置在(可能是全局的)aux
数组中的某个位置,该数组中每个块有一个元素
下面是一个充分发挥作用的示例:
$ cat t831.cu
#include <stdio.h>
#define THREADS 1024
#define BLOCKS 20
__global__ void kernel(int *aux){
__shared__ int temp[THREADS];
temp[threadIdx.x] = threadIdx.x + blockIdx.x;
__syncthreads();
if (threadIdx.x == 0)
aux[blockIdx.x] = temp[THREADS-1];
}
int main(){
int *h_data, *d_data;
const int dsize = BLOCKS*sizeof(int);
h_data=(int *)malloc(dsize);
cudaMalloc(&d_data, dsize);
memset(h_data, 0, dsize);
cudaMemset(d_data, 0, dsize);
kernel<<<BLOCKS, THREADS>>>(d_data);
cudaMemcpy(h_data, d_data, dsize, cudaMemcpyDeviceToHost);
for (int i = 0; i < BLOCKS; i++) printf("%d, ", h_data[i]);
printf("\n");
return 0;
}
$ nvcc -o t831 t831.cu
$ cuda-memcheck ./t831
========= CUDA-MEMCHECK
1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042,
========= ERROR SUMMARY: 0 errors
$
$cat t831.cu
#包括
#定义线程1024
#定义块20
__全局无效内核(int*aux){
__共享_uu; int temp[线程];
temp[threadIdx.x]=threadIdx.x+blockIdx.x;
__同步线程();
if(threadIdx.x==0)
aux[blockIdx.x]=temp[THREADS-1];
}
int main(){
int*h_数据,*d_数据;
const int dsize=块*sizeof(int);
h_data=(int*)malloc(dsize);
cudaMalloc(和d_数据,dsize);
memset(h_数据,0,dsize);
cudaMemset(d_数据,0,数据大小);
内核(d_数据);
cudaMemcpy(h_数据、d_数据、dsize、cudaMemcpyDeviceToHost);
对于(int i=0;i
请尝试一些方法,询问您收到的具体错误或具体的编程问题。显示你的代码!这个问题毫无意义。根据定义,块是独立的,共享内存具有块作用域。您想问的是什么?您需要发布可以由其他人编译的完整代码。如前所述,你的问题毫无意义。@Talonmes我编辑了我的文章,因为上一篇文章都是关于这段代码的。谢谢,我明白了:)我在我的代码中使用了你的建议,我认为我的共享内存部分工作正常,但我的代码没有给出正确的结果