2

我有这样的代码:

for(int i =0; i<2; i++)
{
    //initialization of memory and some variables
    ........
    ........
    RunDll(input image, output image); //function that calls kernel
}

上述循环中的每次迭代都是独立的。我想同时运行它们。所以,我尝试了这个:

for(int i =0; i<num_devices; i++)
{
    cudaSetDevice(i);
    //initialization of memory and some variables
    ........
    ........
    RunDll(input image, output image); 
    {
        RunBasicFBP_CUDA(parameters); //function that calls kernel 1

        xSegmentMetal(parameters); //CPU function

        RunBasicFP_CUDA(parameters);  //function that uses output of kernel 1 as input for kernel 2

        for (int idx_view = 0; idx_view < param.fbp.num_view; idx_view++)
        {
            for (int idx_bin = 1; idx_bin < param.fbp.num_bin-1; idx_bin++)
            {
                sino_diff[idx_view][idx_bin] = sino_org[idx_view][idx_bin] - sino_mask[idx_view][idx_bin];
            }
        }

        RunBasicFP_CUDA(parameters);
        if(some condition)
        {
            xInterpolateSinoLinear(parameters);  //CPU function
        }
        else
        {
            xInterpolateSinoPoly(parameters);  //CPU function
        }

        RunBasicFBP_CUDA( parameters );
    }
}

我正在使用 2 GTX 680,我想同时使用这两个设备。使用上面的代码,我没有得到任何加速。处理时间几乎与在单个 GPU 上运行时相同。

如何在两个可用设备上实现并发执行?

4

2 回答 2

5

在您的评论中,您说:

RunDll 有两个内核,它们正在一个一个启动。内核确实有 cudaThreadSynchronize()

请注意,这cudaThreadSynchronize()等效于cudaDeviceSynchronize()(前者实际上已弃用),这意味着您将在一个 GPU 上运行,同步,然后在另一个 GPU 上运行。另请注意,这cudaMemcpy()是一个阻塞例程,您需要该cudaMemcpyAsync()版本来避免所有阻塞(正如@JackOLantern 在评论中指出的那样)。

一般来说,您需要发布更多关于内部内容的详细信息,RunDLL()因为没有这些信息,您的问题就没有足够的信息来给出明确的答案。最好遵循这些准则

于 2013-09-05T11:45:32.057 回答
0

在我对您上一篇文章的回答中(同时运行两个 for 循环,循环周期数相同,涉及两个 GPU 上的 GPU 和 CPU 任务),我指出您2在使用2GPU 时不会实现加速。

为了解释原因,让我们考虑以下代码片段

Kernel1<<<...,...>>>(...); // assume Kernel1 takes t1 seconds

// assume CPUFunction + cudaMemcpys take tCPU seconds
cudaMemcpy(...,...,...,cudaMemcpyDeviceToHost); // copy the results of Kernel1 to CPU
CPUFunction(...); // assume it takes tCPU seconds
cudaMemcpy(...,...,...,cudaMemcpyHostToDevice); // copy data from the CPU to Kernel2

Kernel2<<<...,...>>>(...); // assume it takes t2 seconds

我是否正在使用cudaDeviceSynchronize()cudaMemcpy获得同步并不重要。

for仅在一个 GPU 上循环执行上述代码片段的成本为

t1 + tCPU + t2 + t1 + tCPU + t2 = 2t1 + 2tCPU + 2t2

2GPU 的情况下,如果您能够在两个不同的 GPU 上实现完美的并发执行Kernel1Kernel2那么执行上述代码片段的成本将是

t1(Kernel1在两个 GPU 上同时执行)+ 2*tCPU(您需要对 CPU 函数进行两次调用,每次调用不同的输出实例)+ t2(在两个 GPU 上Kernel1同时执行)Kernel2

因此,通过使用两个 GPU 而不是一个实现的加速将是

(2*(t1 + tCPU + t2))/(t1 + 2tCPU + t2)

当 tCPU 等于 0 时,加速比变为2.

这是阿姆达尔定律的一种表达。

于 2013-09-05T12:25:25.863 回答