CUDA线程执行顺序

时间:2015-05-25 18:08:23

标签: cuda

我有一个CUDA程序的代码:

#include <stdio.h>

#define NUM_BLOCKS 4
#define THREADS_PER_BLOCK 4

__global__ void hello()
{  

   printf("Hello. I'm a thread %d in block %d\n", threadIdx.x, blockIdx.x);

}


int main(int argc,char **argv)
{
    // launch the kernel
    hello<<<NUM_BLOCKS, THREADS_PER_BLOCK>>>();

    // force the printf()s to flush
    cudaDeviceSynchronize();

    return 0;
}

其中每个帖子都会打印其threadIdx.xblockIdx.x。该计划的一个可能输出是:

Hello. I'm a thread 0 in block 0
Hello. I'm a thread 1 in block 0
Hello. I'm a thread 2 in block 0
Hello. I'm a thread 3 in block 0
Hello. I'm a thread 0 in block 2
Hello. I'm a thread 1 in block 2
Hello. I'm a thread 2 in block 2
Hello. I'm a thread 3 in block 2
Hello. I'm a thread 0 in block 3
Hello. I'm a thread 1 in block 3
Hello. I'm a thread 2 in block 3
Hello. I'm a thread 3 in block 3
Hello. I'm a thread 0 in block 1
Hello. I'm a thread 1 in block 1
Hello. I'm a thread 2 in block 1
Hello. I'm a thread 3 in block 1

多次运行程序我得到了类似的结果,除了块顺序是随机的。例如,在上面的输出中我们有这个块顺序0,2,3,1。再次运行问题我得到1,2,3,0。这是预期的。但是,每个块中的线程顺序始终为0,1,2,3。为什么会这样?我以为它也是随机的。

我试图更改我的代码以强制每个块中的线程0花费更长的时间来执行。我是这样做的:

__global__ void hello()
{  

    if (threadIdx.x == 0)
    {
        int k = 0;
        for ( int i = 0; i < 1000000; i++ )
        {
            k = k + 1;
        }
    }

   printf("Hello. I'm a thread %d in block %d\n", threadIdx.x, blockIdx.x);

}

我希望线程顺序为1,2,3,0。但是,我得到的结果与我上面显示的结果类似,其中线程顺序始终为0,1,2,3。为什么会发生这种情况?

2 个答案:

答案 0 :(得分:2)

  

但是,每个块中的线程顺序始终为0,1,2,3。为什么会这样?我以为它也是随机的

每个块有4个线程,每个块只启动一个 warp warp是CUDA中的执行(以及调度和资源分配)的单位,而不是线程。目前,warp由32个线程组成。

这意味着每个块的所有4个线程(因为在这种情况下没有条件行为)正在 lockstep 中执行。当他们到达printf函数调用时,他们都在同一行代码中执行对该函数的调用在锁步中。

所以问题就变成了,在这种情况下,CUDA运行时如何调度这些&#34;同时&#34;功能调用?这个问题的答案没有具体说明,但并不是随机的#34;。因此,在warp中操作的调度顺序不会在不同的运行中发生变化是合理的。

如果启动足够的线程来为每个块创建多个warp,并且可能还包含一些其他代码来分散和/或随机化&#34;经线之间的行为,你应该能够看到printf操作来自于&#34;随机&#34;中发生的单独扭曲。顺序。

答案 1 :(得分:1)

要回答问题的第二部分,当控制流在if语句处发散时,threadIdx.x != 0只是在if语句之后等待收敛点的线程。在线程0完成printf块之前,它们不会继续if语句。