繁体   English   中英

CUDA中的简单还原程序

[英]A simple reduction program in CUDA

在下面的代码中,我试图实现一个简单的并行缩减,将块大小和每个块的线程数设为1024。但是,在实现部分缩减之后,我希望查看我的实现是否正确,在此过程中程序打印主机存储器的第一个元素(将数据从设备存储器复制到主机存储器之后)。 我的主机内存被初始化为“ 1”,并被复制到设备内存中以减少内存。 精简过程之后的printf语句在数组的第一个元素上仍给我“ 1”。

我要打印的内容是否存在问题,或者在执行缩小操作时是否合乎逻辑? 另外,内核中的printf语句不打印任何内容。 我的语法或对printf语句的调用有什么问题吗? 我的代码如下:

    ifndef CUDACC
define CUDACC
endif
include "cuda_runtime.h"
include "device_launch_parameters.h"
include
include
ifndef THREADSPERBLOCK
define THREADSPERBLOCK 1024
endif
ifndef NUMBLOCKS
define NUMBLOCKS 1024
endif

global void reduceKernel(int *c)
{
extern shared int sh_arr[];

int index = blockDim.x*blockIdx.x + threadIdx.x;
int sh_index = threadIdx.x;

// Storing data from Global memory to shared Memory
sh_arr[sh_index] = c[index];
__syncthreads();

for(unsigned int i = blockDim.x/2; i>0 ; i>>=1)
{
    if(sh_index < i){
        sh_arr[sh_index] += sh_arr[i+sh_index];
    }
    __syncthreads();
}

if(sh_index ==0)
    c[blockIdx.x]=sh_arr[sh_index];
printf("value stored at %d is %d \n", blockIdx.x, c[blockIdx.x]);
return;

}

int main()
{
int *h_a;
int *d_a;
int share_memSize, h_memSize;
size_t d_memSize;

share_memSize = THREADSPERBLOCK*sizeof(int);
h_memSize = THREADSPERBLOCK*NUMBLOCKS;

h_a = (int*)malloc(sizeof(int)*h_memSize);

d_memSize=THREADSPERBLOCK*NUMBLOCKS;
cudaMalloc( (void**)&d_a, h_memSize*sizeof(int));

for(int i=0; i<h_memSize; i++)
{
    h_a[i]=1;    
};

//printf("last element of array %d \n", h_a[h_memSize-1]);

cudaMemcpy((void**)&d_a, (void**)&h_a, h_memSize, cudaMemcpyHostToDevice);
reduceKernel<<<NUMBLOCKS, THREADSPERBLOCK, share_memSize>>>(d_a);
cudaMemcpy((void**)&h_a, (void**)&d_a, d_memSize, cudaMemcpyDeviceToHost);

printf("sizeof host memory %d \n", d_memSize); //sizeof(h_a));
printf("sum after reduction %d \n", h_a[0]);

}

此代码有很多问题。

  1. 您发布的大部分内容都不是有效的代码。 仅举几个例子,您的global关键字和shared关键字应该在前后都有双下划线,例如: __global____shared__ 我认为这是某种复制粘贴错误或格式错误。 您的define语句也存在问题。 您应该努力发布没有这类问题的代码。

  2. 每当遇到CUDA代码问题时,都应使用适当的cuda错误检查请求帮助之前使用cuda-memcheck运行代码。 如果您这样做了,它将把您的注意力集中在下面的项目3上。

  3. 您的cudaMemcpy操作以两种方式中断:

     cudaMemcpy((void**)&d_a, (void**)&h_a, h_memSize, cudaMemcpyHostToDevice); 

    首先,与cudaMalloc不同,但与memcpy一样, cudaMemcpy仅接受普通的指针参数。 其次,传输的大小(如memcpy )以字节单位 ,因此您的大小需要按sizeof(int)进行缩放:

     cudaMemcpy(d_a, h_a, h_memSize*sizeof(int), cudaMemcpyHostToDevice); 

    对于内核之后的内核也是如此。

  4. 大型内核(例如具有1048576个线程的内核)中的每个线程的printf可能不是一个好主意。 您实际上并不会获得期望的所有输出,并且在Windows上(似乎正在Windows上运行),由于内核执行时间过长,您可能会遇到WDDM看门狗超时的情况。 如果您需要从大内核中进行printf ,请选择并在threadIdx.xblockIdx.x上对您的printf进行条件设置

  5. 以上内容可能足以获得合理的打印输出,并且正如您指出的那样,您还没有完成:“我希望看看我的实现是否正确”。 但是,经过精心设计的该内核会用输出数据覆盖其输入数据:

     __global__ void reduceKernel(int *c) ... c[blockIdx.x]=sh_arr[sh_index]; 

    这将导致比赛条件。 建议不要将输出数据与输入数据分开,而不是尝试为您解决这个问题。 更好的是,您应该研究cuda减少示例代码 ,该代码也具有相关的介绍

这是您代码的修改版本,已修复了上述大多数问题。 仍然不正确。 它上面仍然有缺陷5。 与其完全重写您的代码以修复缺陷5,不如将您引向上述的cuda示例代码。

$ cat t820.cu
#include <stdio.h>

#ifndef THREADSPERBLOCK
#define THREADSPERBLOCK 1024
#endif
#ifndef NUMBLOCKS
#define NUMBLOCKS 1024
#endif

__global__ void reduceKernel(int *c)
{
extern __shared__ int sh_arr[];

int index = blockDim.x*blockIdx.x + threadIdx.x;
int sh_index = threadIdx.x;

// Storing data from Global memory to shared Memory
sh_arr[sh_index] = c[index];
__syncthreads();

for(unsigned int i = blockDim.x/2; i>0 ; i>>=1)
{
    if(sh_index < i){
        sh_arr[sh_index] += sh_arr[i+sh_index];
    }
    __syncthreads();
}

if(sh_index ==0)
    c[blockIdx.x]=sh_arr[sh_index];
// printf("value stored at %d is %d \n", blockIdx.x, c[blockIdx.x]);
return;

}

int main()
{
int *h_a;
int *d_a;
int share_memSize, h_memSize;
size_t d_memSize;

share_memSize = THREADSPERBLOCK*sizeof(int);
h_memSize = THREADSPERBLOCK*NUMBLOCKS;

h_a = (int*)malloc(sizeof(int)*h_memSize);

d_memSize=THREADSPERBLOCK*NUMBLOCKS;
cudaMalloc( (void**)&d_a, h_memSize*sizeof(int));

for(int i=0; i<h_memSize; i++)
{
    h_a[i]=1;
};

//printf("last element of array %d \n", h_a[h_memSize-1]);

cudaMemcpy(d_a, h_a, h_memSize*sizeof(int), cudaMemcpyHostToDevice);
reduceKernel<<<NUMBLOCKS, THREADSPERBLOCK, share_memSize>>>(d_a);
cudaMemcpy(h_a, d_a, d_memSize*sizeof(int), cudaMemcpyDeviceToHost);

printf("sizeof host memory %d \n", d_memSize); //sizeof(h_a));
printf("first block sum after reduction %d \n", h_a[0]);
}
$ nvcc -o t820 t820.cu
$ cuda-memcheck ./t820
========= CUDA-MEMCHECK
sizeof host memory 1048576
first block sum after reduction 1024
========= ERROR SUMMARY: 0 errors
$

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM