Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/26.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_Gpu_Gpu Warp - Fatal编程技术网

为什么要费心去了解CUDA翘曲呢?

为什么要费心去了解CUDA翘曲呢?,cuda,gpu,gpu-warp,Cuda,Gpu,Gpu Warp,我有GeForce GTX460 SE,所以它是:6个SM x 48个CUDA内核=288个CUDA内核。 众所周知,在一个扭曲中包含32个线程,而在一个块中同时(一次)只能执行一个扭曲。 也就是说,在单个多处理器(SM)中,即使有48个内核可用,也只能同时执行一个块、一个扭曲和32个线程 此外,可以使用threadIdx.x和blockIdx.x作为分发混凝土螺纹和砌块的示例。要分配它们,请使用内核>()。 但是如何分配特定数量的Warp-s并进行分配,如果不可能,为什么还要费心了解Warp?

我有GeForce GTX460 SE,所以它是:6个SM x 48个CUDA内核=288个CUDA内核。 众所周知,在一个扭曲中包含32个线程,而在一个块中同时(一次)只能执行一个扭曲。 也就是说,在单个多处理器(SM)中,即使有48个内核可用,也只能同时执行一个块、一个扭曲和32个线程

此外,可以使用threadIdx.x和blockIdx.x作为分发混凝土螺纹和砌块的示例。要分配它们,请使用内核>()。 但是如何分配特定数量的Warp-s并进行分配,如果不可能,为什么还要费心了解Warp?

情况比你描述的要复杂得多

ALU(核心)、加载/存储(LD/ST)单元和特殊功能单元(SFU)(图中绿色)都是流水线单元。它们在不同的完成阶段同时保存许多计算或操作的结果。因此,在一个周期中,他们可以接受一个新的操作,并提供另一个很久以前开始的操作的结果(如果我没记错的话,ALU大约有20个周期)。因此,理论上,单个SM有资源同时处理48*20个周期=960个ALU操作,即每个扭曲960/32个线程=30个扭曲。此外,它可以以任何延迟和吞吐量处理LD/ST操作和SFU操作

warp调度程序(图中的黄色)可以为每个周期的管道调度2*32个线程,每个warp=64个线程。这就是每个时钟可以得到的结果数。因此,考虑到计算资源的混合,48个核心,16个LD/ST,8个SFU,每个都有不同的延迟,同时会处理不同的扭曲。在任何给定的周期中,warp调度器都会尝试将两个warp“配对”以进行调度,以最大限度地利用SM

如果指令是独立的,则扭曲调度器可以从不同的块或同一块中的不同位置发出扭曲。因此,可以同时处理来自多个块的扭曲

更为复杂的是,执行指令的warp的资源少于32个,必须为所有要服务的线程发出多次。例如,有8个SFU,这意味着包含需要SFU的指令的扭曲必须调度4次

这个描述被简化了。还有其他一些限制也在起作用,它们决定了GPU如何安排工作。你可以通过在网上搜索“费米体系结构”来找到更多信息

那么,说到你的实际问题

为什么要费心去了解翘曲呢

当您试图最大限度地提高算法的性能时,了解扭曲中的线程数并将其考虑在内变得非常重要。如果不遵守这些规则,您将失去性能:

  • 在内核调用中,
    ,尝试选择与扭曲中的线程数相等的线程数。如果不这样做,则会启动一个包含非活动线程的块

  • 在内核中,尝试让扭曲中的每个线程都遵循相同的代码路径。如果你不这样做,你就会得到所谓的扭曲散度。这是因为GPU必须通过每个发散的代码路径运行整个扭曲

  • 在内核中,尝试让每个线程都处于扭曲加载状态,并以特定模式存储数据。例如,让warp中的线程访问全局内存中的连续32位字

螺纹是否按一定的顺序组合成经纱,1-32,33-64

是的,编程模型保证线程按照特定的顺序分组到扭曲中

作为优化发散代码路径的一个简单示例,可以使用32个线程的组来分离块中的所有线程吗?例如:switch(threadIdx.s/32){case 0:/*1 warp*/break;case 1:/*2 warp*/break;/*Etc*/}

正是:)

单个扭曲一次必须读取多少字节:4字节*32个线程、8字节*32个线程或16字节*32个线程?据我所知,全局内存中的一个事务一次接收128字节

是的,全局内存的事务是128字节。因此,如果每个线程从连续地址中读取一个32位字(它们可能也需要128字节对齐),那么warp中的所有线程都可以通过一个事务(4字节*32个线程=128字节)进行服务。如果每个线程读取更多字节,或者如果地址不是连续的,则需要发出更多事务(每个单独的128字节行都有单独的事务)


CUDA编程手册4.2第F.4.2节“全局内存”对此进行了描述。这里还有一个广告,说只有二级缓存的数据情况不同,因为二级缓存有32字节的缓存线。我不知道如何安排数据只缓存在L2中,也不知道最终会有多少事务。

你问题的第一段大部分内容完全不正确,因此你问题的其余部分没有多大意义。谢谢,回答得很好!还有几个问题。1.螺纹是否按一定的顺序组合成经纱,1-32,33-64。。。?2.作为优化发散代码路径的一个简单示例,可以使用32个线程的组来分离块中的所有线程吗?例如:switch(threadIdx.s/32){case 0:/*1 warp*/break;case 1:/*2 warp*/break;/*Etc*/}3。单个扭曲一次必须读取多少字节:4字节*32个线程、8字节*32个线程或16字节*32个线程?据我所知,全局内存中的一个事务一次接收128字节。感谢您的澄清。对于仅在L2中缓存的数据,需要使用编译器