Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Cuda 为';运行不同的内核变体是否是一种良好的做法;完整';和';部分尾部';阻碍?_Cuda_Gpgpu_Idioms - Fatal编程技术网

Cuda 为';运行不同的内核变体是否是一种良好的做法;完整';和';部分尾部';阻碍?

Cuda 为';运行不同的内核变体是否是一种良好的做法;完整';和';部分尾部';阻碍?,cuda,gpgpu,idioms,Cuda,Gpgpu,Idioms,通常,当您编写GPU内核时,关于具有完整块/扭曲的假设[1]非常有用:您可以在扭曲中的所有线程之间移动;不同的warp可以假定部分必要的工作将由其他warp等完成。当您有大量的输入要处理时(许多块线程),这将转化为有意义的性能增益 当然,如果您做出这样的假设,那么对于输入数据的“余数”,或者更确切地说是网格中未满的单个“余数”块,您需要使用特殊情况。充其量,在某个地方有一个额外的if(blockIdx.x我同意Jez的观点,即内核启动开销可能是一个严重的约束。GaTech的一篇研究论文对此进行了

通常,当您编写GPU内核时,关于具有完整块/扭曲的假设[1]非常有用:您可以在扭曲中的所有线程之间移动;不同的warp可以假定部分必要的工作将由其他warp等完成。当您有大量的输入要处理时(许多块线程),这将转化为有意义的性能增益

当然,如果您做出这样的假设,那么对于输入数据的“余数”,或者更确切地说是网格中未满的单个“余数”块,您需要使用特殊情况。充其量,在某个地方有一个额外的
if(blockIdx.x
,最坏的情况是,它是一个完全不同的计算方法,不管你想要什么

有人想知道,本质上有两个独立的内核是否是一个好主意,一个用于剩余块,另一个用于大容量数据,这样大容量内核就不需要浪费时间来确保它在完整块上工作了

当然,在实践中,这可能只是一个静态检查,即

template <bool IsRemainder>
__global__ void fooKernel(int* a, int* b)
{
    if (IsRemainder) {
        /* special-casing */
    }
    else {
        /* regular case, full block. */
    }
}
模板
__全局无效内核(int*a,int*b)
{
如果(IsRemainder){
/*特殊套管*/
}
否则{
/*正常情况下,完全阻塞*/
}
}
注:

  • 假设所有数据都在GPU上,并且不会很快返回CPU
  • 假设网格是一维的
  • 这允许常规案例代码根本不检查块是否已满-在运行时检查那里的条件

    [1] (用CUDA的说法;用OpenCL:工作组,嗯,波阵面,对吧?)

此策略(即在单独的流中启动特殊案例以同时执行)是否能显著提高您的性能取决于两个方面:

  • 检查的成本真的很高吗?如果这个特例很便宜,并且是在内核顶部检查的,而内核在其他方面非常昂贵,那么它可能不值得这么复杂
  • API开销是一个问题吗?启动一个内核不是免费的,大约需要10us(在一个数量级内)。您的第一个内核必须花费足够长的时间来覆盖“特殊”内核的开销,否则可能会降低应用程序的速度

  • 其他需要考虑的因素包括编译时间和可执行的大小,如果代码中的每一个都使用这种模式,这两个因素都会显著地提高。

    < P>我同意Jez的观点,即内核启动开销可能是一个严重的约束。GaTech的一篇研究论文对此进行了评估: 这里的作者更关心GPU代码中存在的动态并行机会,并使用NVIDIA的机制在运行时启动新内核

    本研究的后续工作位于(如果有兴趣):

    对于这么广泛的问题,恐怕有很多可能的排列方式,没有一般的答案(例如,通常在主机上与GPU并行进行剩余计算是一种可行且性能良好的选择)@Talonmes:试图限制我问题的范围。如果1的答案为真,也就是说,您有足够的数据,可以从运行大部分完整块版本中获得不可忽略的好处-那么,对2的回答可能是“不是问题”。您可能会遇到这样一种情况,即检查成本很高,但一个块会发生什么问题?假设我有足够的块来填充GPU 100次。我仍然只有两次发射。或者我遗漏了什么?如果你有足够的内存来填充GPU 100次,那么这可能不会是一个问题。虽然这不是你最初的假设之一……好吧,我确实说过“大部分数据”是完整块的情况,但我将重新措辞以希望澄清。嗯,那篇文章讨论了一个动态并行场景,其中发生了大量内核“启动”,而这不是这个问题的内容。或者我误解你了吗?虽然这篇论文是关于动态并行的,但它揭示了现代GPU的一个重要方面,即对可运行的并发内核数量的限制(以及启动新内核的开销)。GPU上可能有许多图形内核(例如AMD异步着色器),您的计算内核必须与之竞争资源。在这种情况下,您需要警惕创建新内核的影响(这与您提出的问题有点关联)。