CUDA针对不同功能的每个块使用不同的线程

CUDA针对不同功能的每个块使用不同的线程,cuda,Cuda,我正在做一个CUDA程序,遇到了一个问题。我有两个职能: \uuuuu全局\uuuuuu无效校准频率(浮点*,字符*,字符*,整数*,整数*) \uuuuuuuuuuuuuuuuu全局\uuuuuuuuuuuuu无效校验和\uvfreq\upl(浮点*,浮点*,字符*,字符*,整数*) 我这样调用第一个函数: cal_freq_pl(…) M是一个大约15的数字,所以我不担心它。512是我的GPU上每个块的最大线程数。这可以很好地工作,并为所有M*512值提供预期的输出 但当我以类似的方式调用第

我正在做一个CUDA程序,遇到了一个问题。我有两个职能:

  • \uuuuu全局\uuuuuu无效校准频率(浮点*,字符*,字符*,整数*,整数*)
  • \uuuuuuuuuuuuuuuuu全局\uuuuuuuuuuuuu无效校验和\uvfreq\upl(浮点*,浮点*,字符*,字符*,整数*)
  • 我这样调用第一个函数:
    cal_freq_pl(…)
    M是一个大约15的数字,所以我不担心它。512是我的GPU上每个块的最大线程数。这可以很好地工作,并为所有M*512值提供预期的输出

    但当我以类似的方式调用第二个函数时:
    cal_sum_vfreq_pl(…)
    它不起作用。在调试了该函数的垃圾之后,我终于发现它是以以下维度运行的:
    cal_sum_vfreq_pl(…),比512小128。它显示512没有错误,但结果不正确

    我目前只能访问Compute1.0 arch,并且在Windows 64位计算机上有Nvidia Quadro FX4600图形卡

    我不知道为什么会发生这样的行为,我肯定第一个函数运行512个线程,第二个函数只运行384个(或更少)

    有人能提出一些可能的解决方案吗

    先谢谢你

    编辑: 以下是内核代码:

    __global__ void cal_sum_vfreq_pl(float *freq, float *v_freq_vectors, char *wstrings, char *vstrings, int *k){
        int index = threadIdx.x;
        int m = blockIdx.x;
        int block_dim = blockDim.x;
        int kv = *k; int vv = kv-1; int wv = kv-2;
        int woffset = index*wv;
        int no_vstrings = pow_pl(4, vv);
        float temppp=0;
        char wI[20], Iw[20]; int Iwi, wIi;
        for(int i=0;i<wv;i++) Iw[i+1] = wI[i] = wstrings[woffset + i];
        for(int l=0;l<4;l++){
                Iw[0] = get_nucleotide_pl(l);
                wI[vv-1] = get_nucleotide_pl(l);
                Iwi = binary_search_pl(vstrings, Iw, vv);
                wIi = binary_search_pl(vstrings, wI, vv);
                temppp = temppp + v_freq_vectors[m*no_vstrings + Iwi] + v_freq_vectors[m*no_vstrings + wIi];
        }
        freq[index + m*block_dim] = 0.5*temppp;
    }
    
    \uuuuu全局\uuuuu无效计算和\uvfreq\upl(浮点*freq,浮点*v\ufreq\u向量,char*wstring,char*vstrings,int*k){
    int index=threadIdx.x;
    int m=blockIdx.x;
    int block_dim=blockDim.x;
    int kv=*k;int vv=kv-1;int wv=kv-2;
    int woffset=索引*wv;
    int no_v字符串=功率(4,vv);
    浮点temppp=0;
    char-wI[20],Iw[20];int-Iwi,wIi;
    
    对于(int i=0;i来说,您似乎在第二个内核中分配了很多寄存器。由于硬件资源的限制,例如每个块的寄存器数,您无法始终达到每个块的最大线程数

    CUDA提供了一个工具来帮助计算每个块的正确线程数


    您也可以在CUDA安装目录中找到此.xls文件。

    什么是“它不工作”意思是?是内核启动失败,还是内核启动并在内核中运行?可能只是内核内部的绑定检查失败。@hubs:从385开始,它开始提供错误的输出,这很奇怪。如果它以385个线程开始,结果将是错误的,那么很肯定您的内核源代码中会出现故障。但是我很难说没有看到你的内核代码。@hubs:不,我的意思是,如果我把blockDim=385放进去,输出是错误的,整个输出都是错误的,不只是从385开始,而是从所有的M*512值开始。我将添加内核代码……作为一般规则,在任何情况下,你都应该检查线程是否要访问你分配的内存。试着运行你的p用
    cuda memcheck编程
    噢,我来研究一下。一个简单的问题,char[20]算1还是20个寄存器?看起来是
    binary\u search\u pl(…)
    是所有问题的根源。我需要以某种方式替换它,以使线程/块不会下降到384。我仍然不确定寄存器变量的使用位置,但这个
    \uu设备\uuuuuuu
    函数有一些事情要做。正如上面注释中的答案所示,长字符数组自动被删除传输到本地内存,我也测试了它,char[20]不是问题,但是
    \uuuu设备\uuuu
    函数调用是(在本例中为二进制搜索\upl),它们使用了太多的寄存器变量。@user1961040,有一些编译选项可以为您输出regester的用法。或者,我经常使用Visual profile检查寄存器的用法。我刚刚发现了一个新东西。因此,由于内核代码(和
    \uu设备\uuu
    函数调用),寄存器的数量减少了。但是,我得到的错误输出不是由于内核代码的某些错误计算。代码甚至没有编译,但VS2008没有显示错误,即使使用--ptxas options=-v option。因此,运行的代码是最后一个成功编译的版本。无论我做了什么更改(线程数>384)没有编译,所以以前的版本会运行。我经常遇到这个问题,所以我想在这里为面临类似问题的人编写它。