【问题标题】:Printing inside a cuda __global__ function kills the thread在 cuda __global__ 函数中打印会杀死线程
【发布时间】:2015-09-02 20:20:41
【问题描述】:

我的代码有一个奇怪的问题。如果我尝试在线程内打印某个变量的值,则不会将任何内容写入屏幕,并且所有线程都会在该点停止。这是代码:

    #define WINSIZE 1
    const int nebsize=(WINSIZE*2+1)*(WINSIZE*2+1);

    __global__ void loop(double *img, int *consts, int w, int h, double epsilon){

        int ind=blockIdx.x*blockDim.x+threadIdx.x;
        if(ind<w*h && !consts[ind] && ind%w>=WINSIZE && ind%w<w-WINSIZE && ind/w>=WINSIZE && ind/w<h-WINSIZE){
            int win_inds[nebsize];
            double winI[3*(2*WINSIZE+1)*(2*WINSIZE+1)];
            double winI_re_aux[3*nebsize];
            double pre_win_var[9];
            double win_var[9];
            double win_mu[3];
            double tvals[nebsize*nebsize];
            double detwin;
            int min_i=ind%w-WINSIZE;
            int max_i=ind%w+WINSIZE;
            int min_j=ind/w-WINSIZE;
            int max_j=ind/w+WINSIZE;
            int k;
            int l;
            k=0;        
            for(int i=min_i; i<=max_i; i++){
                for(int j=min_j; j<=max_j; j++){
                    win_inds[k]=h*i+j;
                    k++;
                }
            }
            k=0;
            for(int j=min_j; j<=max_j; j++){        
                l=0;
                for(int i=min_i; i<=max_i; i++){
                    winI[3*(l*(2*WINSIZE+1)+k)]=img[3*(j*w+i)];
                    winI[3*(l*(2*WINSIZE+1)+k)+1]=img[3*(j*w+i)+1];
                    winI[3*(l*(2*WINSIZE+1)+k)+2]=img[3*(j*w+i)+2];
                    l++;
                }
                k++;
            }

            win_mu[0]=0;
            win_mu[1]=0;
            win_mu[2]=0;    
            for(int i=0; i<nebsize; i++){
                win_mu[0]+=winI[3*i];
                win_mu[1]+=winI[3*i+1];
                win_mu[2]+=winI[3*i+2];
            }
            win_mu[0]=win_mu[0]/(double)nebsize;
            win_mu[1]=win_mu[1]/(double)nebsize;
            win_mu[2]=win_mu[2]/(double)nebsize;
            //all ok here

            //this works here
            if(ind==200){   
                    printf("%f\n", win_var[8]);
            }

            for(int i=0; i<3; i++){
                for(int j=0; j<3; j++){
                    pre_win_var[3*i+j]=0;
                    for(int n=0; n<nebsize; n++){
                        pre_win_var[3*i+j]+=winI[3*n+i]*winI[3*n+j];
                    }
                    pre_win_var[3*i+j]=pre_win_var[3*i+j]/(double)nebsize;
                    pre_win_var[3*i+j]+=(i==j)*epsilon/(double)nebsize-win_mu[j]*win_mu[i];
                }
            }
            //this kills all threads          
            if(ind==200){   
                    printf("%f\n", win_var[8]);
            }
            detwin=pre_win_var[0]*pre_win_var[4]*pre_win_var[8]+pre_win_var[2]*pre_win_var[3]*pre_win_var[7]+pre_win_var[1]*pre_win_var[5]*pre_win_var[6];
            detwin-=pre_win_var[6]*pre_win_var[4]*pre_win_var[2]+pre_win_var[3]*pre_win_var[1]*pre_win_var[8]+pre_win_var[7]*pre_win_var[5]*pre_win_var[0];

            win_var[0]=(pre_win_var[4]*pre_win_var[8]-pre_win_var[5]*pre_win_var[7])/detwin;
            win_var[3]=-(pre_win_var[3]*pre_win_var[8]-pre_win_var[5]*pre_win_var[6])/detwin;
            win_var[6]=(pre_win_var[3]*pre_win_var[7]-pre_win_var[4]*pre_win_var[6])/detwin;
            win_var[1]=-(pre_win_var[1]*pre_win_var[8]-pre_win_var[2]*pre_win_var[7])/detwin;
            win_var[4]=(pre_win_var[0]*pre_win_var[8]-pre_win_var[2]*pre_win_var[6])/detwin;
            win_var[7]=-(pre_win_var[0]*pre_win_var[7]-pre_win_var[1]*pre_win_var[6])/detwin;
            win_var[2]=(pre_win_var[1]*pre_win_var[5]-pre_win_var[2]*pre_win_var[4])/detwin;
            win_var[5]=-(pre_win_var[0]*pre_win_var[5]-pre_win_var[2]*pre_win_var[3])/detwin;
            win_var[8]=(pre_win_var[0]*pre_win_var[4]-pre_win_var[1]*pre_win_var[3])/detwin;                

            //this line gets executed in all threads if I printf nothing
            consts[ind]=666;

        }
    }

只能在计算值之前打印 win_var 或 pre_win_var 的值,但如果我在此之后尝试打印它们,它似乎会杀死所有线程。如果我什么都不打印,则 consts[ind]=666 行会在所有线程中执行,我知道这一点,因为我可以将 consts 复制回主机内存并打印它。那么,有人知道出了什么问题吗?

【问题讨论】:

  • 您的代码中可能存在非法访问权限。由于您的大部分代码活动不会影响任何全局状态,因此编译器会对其进行优化,包括进行非法访问的代码。不知何故,printf 以一种不明显的方式影响编译器优化决策,这影响了哪些代码被丢弃。在您失败的情况下,使用答案here 中描述的方法来确定生成非法访问的确切代码行。投票结束,因为此类问题预计将包括 MCVE
  • 这就是我得到的:========= CUDA-MEMCHECK ========= 程序命中 cudaErrorLaunchOutOfResources(错误 7),因为“请求启动的资源太多" 关于对 cudaLaunch 的 CUDA API 调用。我想我的内存不足了。
  • @protas:可能没有注册。尝试减小块大小
  • 这更有意义。我无法将 printf 直接与代码包含联系起来。但是 printf 肯定会影响寄存器的使用。
  • 如果我注释掉 printf 行,错误就会消失。

标签: cuda


【解决方案1】:

问题似乎是资源耗尽之一。由于包含 ABI 调用的内核的更大寄存器占用空间,您在启动时会收到 cudaErrorLaunchOutOfResources 并启用 printf。

您没有提供有关启动参数的任何详细信息,但将每个块的总线程数减少到 32 的较小倍数应该可以解决问题。

【讨论】:

  • 什么更好,线程数是 32 的倍数,还是块数是 GPU 中多处理器数的倍数?我正在尝试根据输入图像的像素数和 GPU 上的多处理器数量来计算执行时间的块数和线程数。
  • 两者,理想情况下。但是每个块的线程数是扭曲大小的倍数是最重要的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-11
  • 1970-01-01
  • 1970-01-01
  • 2014-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多