Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ajax/6.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 - Fatal编程技术网

Cuda 有没有一种有效的方法来优化我的序列化代码?

Cuda 有没有一种有效的方法来优化我的序列化代码?,cuda,gpgpu,Cuda,Gpgpu,这个问题缺乏细节。所以,我决定创建另一个问题,而不是编辑这个问题。新问题在这里: 我有一个在CUDA中运行的程序,其中一段代码在一个循环中运行(序列化,如下所示)。这段代码是包含地址和/或空指针的数组中的搜索。所有线程都执行下面的代码 while (i < n) { if (array[i] != NULL) { return array[i]; } i++; } return NULL; while(i

这个问题缺乏细节。所以,我决定创建另一个问题,而不是编辑这个问题。新问题在这里:

我有一个在CUDA中运行的程序,其中一段代码在一个循环中运行(序列化,如下所示)。这段代码是包含地址和/或空指针的数组中的搜索。所有线程都执行下面的代码

while (i < n) {
    if (array[i] != NULL) {
        return array[i];
    }
    i++;
}
return NULL;
while(i
其中
n
数组的大小,数组位于共享内存中。我只对第一个不同于NULL(第一个匹配)的地址感兴趣

整个代码(我只发布了一部分,整个代码很大)运行得很快,但代码的“核心”(即重复次数较多的部分)是序列化的,如您所见。我想知道我是否可以用一些优化算法来并行这部分(搜索)

正如我所说,该程序已经在CUDA中(以及设备中的阵列),因此它不会从主机到设备进行内存传输,反之亦然

我的问题是:
n
不是很大。它很难大于8

我曾尝试将其并行化,但我的“新”代码比上面的代码花费了更多的时间

我曾研究过归约和最小运算,但我检查过它在
n
较大时是否有用


那么,有什么建议吗?我能有效地并行化它吗,也就是说,以较低的开销?

保持简单,GPGPU代码的主要限制因素之一是内存管理。在大多数计算机中,将内存复制到设备(GPU)是一个缓慢的过程

如图所示:

“获得有效信息的关键要求 GPU子例程库的加速是 主机和GPU之间的I/O。“

这是因为主机和设备之间的I/O操作很慢

把这与你的问题联系起来,在GPU上运行是没有意义的,因为你提到的数据量太小了。首先,运行memcpy例程的时间比在CPU上运行要多,尤其是因为您提到您只对第一个匹配感兴趣

许多人有一个常见的误解,那就是“如果我在GPU上运行它,它会有更多的内核,所以会运行得更快”,而事实并非如此


在决定是否值得移植到CUDA或OpenCL时,您必须考虑该进程是否本质上是并行的-您是否正在处理大量数据等?

因为您说
数组是一个共享内存资源,所以此搜索的结果对于块的每个线程都是相同的。这意味着第一个简单的优化就是只让一个线程进行搜索。这将使除了块的第一个扭曲之外的所有扭曲都不必做任何工作(它们仍然需要等待结果,但不必浪费任何计算资源):


当然,该示例假定
n
为2的幂(并且
数组
相应地填充
NULL
s),但是请根据您的需要调整它并进一步优化它。

我不明白您在这里问什么。“数组如何具有多个地址”?如果“它将大于8”,为什么会有困难?不清楚您想做什么,为什么您所做的是不可接受的,以及该方法是什么。当您说
array
可能有多个地址时,您的意思是
array
元素可以假定对应于多个地址值的值吗?但是,不管怎样,您可能是在自己回答您的问题:当涉及到大型阵列时,GPU很方便。粗略地说,CPU比GPU快,而且当阵列很小时,设置内核启动的开销会太大。因此,尽管您没有提供您的方法,但根据一些常识,我想说,移植代码不值得,我不会感到惊讶。@Talonmes,我为我的错误问题道歉。我说这是CPU代码,因为代码以序列化的方式运行,就像CPU代码一样。很抱歉我已经更改了有关数组和地址的短语。看看你现在是否明白了,我问的方式真的很混乱。现在编辑好了。@Jackolanten,我为我提问的方式道歉。我编辑了它。现在我解释得更好了。我知道,也许我已经回答了我的问题。但这就是我想知道的,如果有一个针对小型
n
的优化算法。很抱歉我写问题的方式,它真的很混乱。@b如果只是对同一问题的更详细描述,你可以更新这个问题而不是打开另一个问题。我编辑了我的问题,我说这是CPU代码,因为它像CPU一样序列化运行。但它已经在GPU中,所以我不会在主机和设备之间进行内存传输。但是我想知道是否有一种方法可以有效地并行化
n
small(n<8)的“首次匹配搜索”。感谢您的帮助。我的观点是-对于小n来说,尝试为它实现并行实现是没有意义的。这不是GPU的设计目的。如果您只搜索第一个匹配项,那么整个过程本质上就是一个串行过程。即使你能同时做这件事,事情肯定会过于复杂。n太小了,似乎不值得。这只是我对形势的理解。特詹克斯,我写了另一个问题,其中有更多的细节。如果您阅读并回答您的想法,无论是否正确,我将不胜感激。谢谢:这段代码很脆弱,如果硬件或编译器优化发生重大变化(过去发生过,将来也会发生),那么很可能会失败。另外,对于单翘曲情况,您可以使用一行代码来完成:
\uufs(\ub
__shared__ void *result = NULL;
if(tid == 0)
{
    for(unsigned int i=0; i<n; ++i)
    {
        if (array[i] != NULL)
        {
            result = array[i];
            break;
        }
    }
}
__syncthreads();
return result;
for(unsigned int i=n/2; i>32; i>>=1)
{
    if(tid < i && !array[tid])
        array[tid] = array[tid+i];
    __syncthreads();
}

if(tid < 32)
{
    if(n > 32 && !array[tid]) array[tid] = array[tid+32];
    if(n > 16 && !array[tid]) array[tid] = array[tid+16];
    if(n > 8 && !array[tid]) array[tid] = array[tid+8];
    if(n > 4 && !array[tid]) array[tid] = array[tid+4];
    if(n > 2 && !array[tid]) array[tid] = array[tid+2];
    if(n > 1 && !array[tid]) array[tid] = array[tid+1];
}

__syncthreads();    
return array[0];