【问题标题】:CUDA: embedded for loop kernelCUDA:嵌入式for循环内核
【发布时间】:2011-07-02 04:58:52
【问题描述】:

我有一些代码想要制作成 cuda 内核。看:

    for (r = Y; r < Y + H; r+=2)
    {
        ch1RowSum = ch2RowSum = ch3RowSum = 0;
        for (c = X; c < X + W; c+=2)
        {
            chan1Value = //some calc'd value
                            chan3Value = //some calc'd value
            chan2Value = //some calc'd value
            ch2RowSum  += chan2Value;
            ch3RowSum  += chan3Value;
            ch1RowSum  += chan1Value;
        }
        ch1Mean += ch1RowSum / W;
        ch2Mean += ch2RowSum / W;
        ch3Mean += ch3RowSum / W;
    }

是否应该将其拆分为两个内核,一个用于计算 RowSums,一个用于计算 Means,以及我应该如何处理循环索引不从零开始并以 N 结束的事实?

【问题讨论】:

  • 尝试选择一个问题,很难选择正确的答案。但是,关于你的第二个问题......很难具体回答,但我认为一旦你进一步开发你的内核,你就会看到。
  • 你应该使用像 H 块和每个块 W 线程这样的配置来启动你的内核。然后,您将根据内核中的 blockIdx 和 threadIdx 值计算 r 和 c。计算 r 和 c 但是你想要......我试着把它放在下面的答案中......
  • 看起来确实像两个问题,但如果我尝试将其写成两个问题,我不确定上下文是否存在

标签: c++ cuda


【解决方案1】:

假设您有一个计算三个值的内核。配置中的每个线程都会计算每个 (r,c) 对的三个值。

__global__ value_kernel(Y, H, X, W)
{
    r = blockIdx.x + Y;
    c = threadIdx.x + W;

    chan1value = ...
    chan2value = ...
    chan3value = ...
}

我不相信您可以在上述内核中计算总和(至少完全并行)。您将无法像上面那样使用 += 。如果每个块(行)中只有一个线程进行求和和均值,则可以将它们全部放在一个内核中,就像这样......

__global__ both_kernel(Y, H, X, W)
{
    r = blockIdx.x + Y;
    c = threadIdx.x + W;

    chan1value = ...
    chan2value = ...
    chan3value = ...

    if(threadIdx.x == 0)
    {
        ch1RowSum = 0;
        ch2RowSum = 0;
        ch3RowSum = 0;

        for(i=0; i<blockDim.x; i++)
        {
            ch1RowSum += chan1value;
            ch2RowSum += chan2value;
            ch3RowSum += chan3value;
        }

        ch1Mean = ch1RowSum / blockDim.x;
        ch2Mean = ch2RowSum / blockDim.x;
        ch3Mean = ch3RowSum / blockDim.x;
    }
}

但最好先使用第一个值内核,然后使用第二个内核进行求和和均值... 可以进一步并行化下面的内核,如果它是单独的,您可以在准备好时专注于它。

__global__ sum_kernel(Y,W)
{
    r = blockIdx.x + Y;

    ch1RowSum = 0;
    ch2RowSum = 0;
    ch3RowSum = 0;

    for(i=0; i<W; i++)
    {
        ch1RowSum += chan1value;
        ch2RowSum += chan2value;
        ch3RowSum += chan3value;
    }

    ch1Mean = ch1RowSum / W;
    ch2Mean = ch2RowSum / W;
    ch3Mean = ch3RowSum / W;
}

【讨论】:

  • 我提到你可以并行化总和/平均值......你想要的是减少。 (许多可用示例之一:supercomputingblog.com/cuda/…
  • 我注意到您实际上并没有在这里使用 R 或 C 的值。如果blockIdx.x*threadIdx.x大于blockIdx.x+Y,是否应该进行某种检查来执行No Op?那会是什么样子?
  • 您也没有在代码中使用 r 或 c。您为每个网格位置 (r,c) 计算了三个值。您可能希望让一个线程计算一组值。当你启动你的内核时,每块启动 r 个块和 c 个线程。然后,在每个线程中,您可以从块 id 和线程 id 计算 r 和 c。我假设 r 和 c 用于访问值计算的输入和/或直接使用它们。 (如果您可能会启动一个具有比您需要的更多线程或块的内核,那么请务必检查您的边界......类似 if(r >= #rows || c >= #cols) return;)
  • 总的来说,在我看来,您需要阅读更多关于如何使用 CUDA 的信息,或者查看一些示例。输入是什么?你将如何将数据传输到 GPU 上?将如何安排?你将如何访问它?结果将如何安排?你将如何将结果返回给 cpu?尝试仅使用值计算来完成所有这些工作,并首先将它们与 cpu 计算值进行比较。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多