OpenCl - 全球和本地规模 - 差异以及为什么有时仅增加本地规模是显而易见的?

时间:2017-01-06 11:05:00

标签: multithreading opencl gpgpu

我写了两个OpenCl程序,它们是多平台和多设备。 首先是积分和第二个矩阵 - 矩阵乘法。 我发现用全局工作量来操纵它并使它变得更大到像2 ^ 28这样荒谬的大数字正在减慢我的程序(当地大小为1) 我可以自己解释一下,因为GPU可能会放置它拥有的每个线程,并且由于全局大小如此之大,另一个线程排队并等待前一个线程完成其工作并且正在减慢计算速度。 但是在矩阵乘法中,我能够将本地大小设置为1024(我的最大值)并且速度非常快,例如从130秒的计算到大约6秒。 但是在Integral中我做了同样的事情,但增加本地大小并没有改变任何计算时间。 当我学习OpenCl时,我并不了解全局和本地大小是什么,现在我明白全局大小编号只是执行内核代码的线程数,这意味着如果全局大小是4 000,内核代码将会执行4000次。但我仍然不明白什么是当地的规模,为什么有时它会有所作为,有时候不会,有人可以解释"当地规模"对我的定义?简单来说就是。

提前谢谢!

1 个答案:

答案 0 :(得分:2)

编辑:长话短说:

积分==>数据重用= 1 ==>记忆密集

矩阵乘法==>数据重用= n ==>缓存密集型(或本地内存)

内存密集型==>每个计算单元甚至3-5个线程填充gpu的所有内存请求槽,因此如果每个计算单元有40-50或900-1000则无关紧要。它们全部排队,直到内存控制器为所有请求服务。这些操作是序列化的。

缓存密集型==>缓存命中率高==>更高的计算内存比

每组更多主题==>更多数据重用==>更好的缓存使用率==>只有代码是高速缓存密集时的性能

在整数内核中,您最多使用一次或几次变量,因此它对内核执行时间没有明显影响。

在矩阵乘法中,每个数据块使用N次。如果它们位于本地内存中,则会受到本地内存带宽的限制。如果它在全局内存中,则会受到缓存(可能是L2)带宽的瓶颈。如果本地内存比缓存快得多,它将在基准时间上可见。

拥有数十亿个线程会导致线程发生/发出/获取瓶颈 如果每个线程只进行一些加法和乘法运算,则在时序上可见。

矩阵乘法与积分的答案是数据重用率

也许缓存的大小也很重要。如果它足够大且带宽高,那么使用本地内存可能无关紧要。例如,如果AMD的vega架构具有256MB L2缓存,那么它应该具有与本地内存版本类似的性能(如果缓存带宽也可以与本地内存相比)

Local thread number(nLocal): max number of threads that share same local memory.

Global thread number(nGlobal): max number of threads.

Max wavefront threads = k * nLocal 
// k is a dynamic factor depending on 
// free resources per compute unit.  

nGlobal = m * nLocal 
// so global number is an exact multiple of local number 
// but may not be exact ultiple of wavefront thread number

如果每个线程本地内存使用量增加,则k减少    如果每个线程本地内存使用量增加,你应该减少nLocal    如果nLocal< numCoresPerComputeUnit,它是次优的

本地线程使用其计算单元的寄存器文件    本地线程共享本地内存和计算单元的L1    计算单元共享L2,常量内存(和纹理内存?)    L2与视频RAM相关联(至少对于不受欢迎的gpus)

但是体系结构发生了变化,例如AMD的vega,显示L1处于全局共享位置,整个线程通过共享的L1只是ike图形管道部分成为L2的一个客户端。

本地内存的大小是固定的并由本地线程共享,因此如果每个线程使用更多,则应该减少本地线程数,否则它将溢出到全局内存并通过opencl api获得非常慢或返回错误。

通常每个计算单元为64kB,因此如果nLocal为16,则每个线程可以使用4kB。