CUDA编程常见问题转-创新互联
http://blog.csdn.net/yutianzuijin/article/details/8147912
分类: 编程语言2012-11-05 10:55 2521人阅读 评论(0) 收藏 举报cudaGPU 最近初试cuda编程,作为一个新手,遇到了各种各样的问题,然后花费了大量时间解决这些匪夷所思的问题。为了避免后来人重蹈覆辙,现把自己遇到的问题总结如下。(一)、cudaMalloc
创新互联公司-成都网站建设公司,专注成都做网站、网站建设、外贸营销网站建设、网站营销推广,空间域名,网页空间,网站运营有关企业网站制作方案、改版、费用等问题,请联系创新互联公司。初次使用该函数,感觉没有什么困难,和c语言的malloc类似。但是在具体应用中却出了一个很难找的错误,花费了很多时间。该函数使用是需要注意的就是,它分配的内存空间单位是字节,所以需要我们在使用时用sizeof指定具体分配的变量类型,这样才能正确分配空间。例:
cudaMalloc((void**)&gpu_data,sizeof(float)*1024);
(二)、函数的执行位置
cuda程序的一大特色是程序的核心部分在GPU上执行,所以cuda函数就分为不同的类别:host、global、device三类。所以我们在编写函数时一定要分清楚当前正在编写的是哪类函数,可以调用什么库函数。
- host函数:在CPU上调用,在CPU上执行,可以调用global函数,不能调用device函数;
- global函数:只能在host函数中调用,但是执行是在GPU上执行,例如cudaMalloc之类的内存操作库函数,可以调用device函数;
- device函数:只能在GPU上调用和执行,只能被global函数引用。
- __device__ int count=0;
- __global__ static void sum(int* data_gpu,int* block_gpu,int *sum_gpu,int length)
- {
- extern __shared__ int blocksum[];
- __shared__ int islast;
- int offset;
- const int tid=threadIdx.x;
- const int bid=blockIdx.x;
- blocksum[tid]=0;
- for(int i=bid*THREAD_NUM+tid;i
- {
- blocksum[tid]+=data_gpu[i];
- }
- __syncthreads();
- offset=THREAD_NUM/2;
- while(offset>0)
- {
- if(tid
- {
- blocksum[tid]+=blocksum[tid+offset];
- }
- offset>>=1;
- __syncthreads();
- }
- if(tid==0)
- {
- block_gpu[bid]=blocksum[0];
- __threadfence();
- int value=atomicAdd(&count,1);
- islast=(value==gridDim.x-1);
- }
- __syncthreads();
- if(islast)
- {
- if(tid==0)
- {
- int s=0;
- for(int i=0;i
- {
- s+=block_gpu[i];
- }
- *sum_gpu=s;
- }
- }
- }
- for循环内可以定义变量,标准C语言不支持,所以我们可以直接用(for int i=0;i
- 变量定义位置无限制,可以在任意位置定义变量;
- CUDA支持多态,所以我们可以定义多个名称相同,参数不同的函数,这个没有问题;
- 有时多态可以用模版(template)来合并代码,达到简化编程的目的;
(六)、block和thread号的正确使用 为了调度不同的线程,我们通常需要利用内置变量threadIdx和blockIdx作为循环中的增量。但是切记在循环内部要正确使用内置变量,两天debug的教训!下面是一个示例代码: [cpp] view plaincopyprint?
- __global__ static void saliencefunc(float *peaks_gpu,int *index_gpu,float *saliencebins_gpu,int framenumber)
- {
- __shared__ float peaks[HALF_PEAK_NUM];
- __shared__ int index[HALF_PEAK_NUM];
- int tid=threadIdx.x;
- int bid=blockIdx.x;
- for(int i=bid;i
- {
- if(tid
- {
- peaks[tid]=peaks_gpu[HALF_PEAK_NUM*i+tid];
- index[tid]=index_gpu[HALF_PEAK_NUM*i+tid];
- }
- __syncthreads();
- }
- }
注意代码第十三和十四行的赋值操作HALF_PEAK_NUM*i+tid,笔者之前的写法是HALF_PEAK_NUM*bid+tid,结果花了两天的时间找问题,所以要正确使用,在可以替换的情况下就用i或者j这样的变量,尽量少用内置变量。 (七)、空间释放 在GPU上分配的空间,在使用完成之后要及时释放。对于运行一次的程序,不释放空间没有什么大碍,毕竟程序结束空间自动会被释放掉。但是当程序不间断运行多次的时候,不释放空间会导致非常严重的GPU内存泄露。第一个问题是随着程序的运行,GPU内存耗尽,导致后续内存分配失败;第二个问题是,程序运行会越来越慢。所以我们一定要养成用完及时释放空间的习惯。
文章标题:CUDA编程常见问题转-创新互联
网站网址:http://azwzsj.com/article/ehsjg.html