CUDA同一个Warp中的线程执行顺序

#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.为什么会发生这种情况?

回答:

由于每块4个线程你只推出每块一个。 A warp是CUDA中的执行单元(以及调度和资源分配),而不是线程。目前,一个warp包含32个线程。

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

因此,在这种情况下,CUDA运行时如何调度这些“同时”函数调用?这个问题的答案没有具体说明,但它不是“随机的”。因此,对于一个warp内的操作的调度顺序不会随着运行而改变是合理的。

如果启动足够的线程为每个块创建多个warp,并且可能还包含一些其他代码以分散或“随机化”warp之间的行为,则应该能够看到printf操作是从“随机顺序。

问:

谢谢,这是对我的问题的非常准确的答案。我将其标记为答案,因为我学到了很多东西。但是,如果我将代码分散或“随机化”,会发生什么?我有兴趣进一步了解锁步部分。所以假设线程0进入一个if语句,并且线程1到31不(在同一个warp中)。假设线程1-31已准备好继续,它们是否会等待线程0完成if语句并以锁步方式继续?再次感谢您的回答。

 回答:

是的,对于if-then-else构造,满足if条件的warp中的所有线程将遵循if路径,而其余线程为“inactive”。然后,满足if条件的线程将变为“不活动”,并且不满足if条件的线程将被激活,并且这些线程将遵循else路径。在完成这个序列时,warp中的所有线程都会隐式地重新同步,然后继续以lockstep执行。 (事实上​​,if路径首先发生还是其他路径首先发生的确切顺序是未指定的。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值