为什么float4应该在前缀sum中执行float

时间:2015-10-22 03:17:44

标签: performance opencl gpu

在OpenCL in Action中,Matthew Scarpino评论说,将他的前缀和从32位浮点数切换到128位4浮点数的集合会带来显着的性能提升,几乎快4倍!

  

运行Ch10 / reduction应用程序时,它将同时执行   reduction_scalar和reduction_vector内核。除了检查   结果,它测量每个内核执行所花费的时间。上   我的系统,结果如下:

     

reduction_scalar:检查通过。总时间= 489031

     

reduction_vector:检查通过。总时间= 136157

Matthew Scarpino

类似的声明是由GPU Gems提出的,引用了一个似乎是课程的课程,不再可用。

  

我们采用David Lichterman建议的技术,该技术可以处理   每个线程八个元素而不是两个加载两个元素   每个线程的float4元素而不是两个浮点数   元素(Lichterman 2007)。

http://http.developer.nvidia.com/GPUGems3/gpugems3_ch39.html

一种解释是每个线程的内存请求会增加,但这对我没有意义,因为我预计会发出相同的内存请求总数,这可能会导致相同的整体性能。

或者,每个warp发出一个请求,然后进入休眠状态。在float4情况下,它会唤醒4倍的数据,但在float情况下,数据未被缓存,因此后续线程也需要进入休眠状态并等待新数据。另一方面。我希望内存能够在warp中的线程被唤醒时进行流式处理。

我想知道某些专家是否可以插入并提供顺序解释,解释为什么float4在内存访问或计算方面的执行速度明显快于float

1 个答案:

答案 0 :(得分:3)

这里实际上有两件事情在起作用。一种是更有效地利用内存带宽,另一种是改进的计算与内存事务的比率,从而改善了延迟隐藏。

为了阐明内存带宽方面,例如考虑NVIDIA GPU的情况:硬件的设计使其能够提供128个字节(来自128字节对齐的段)单笔交易变形;对于具有L1高速缓存(高速缓存行为128字节)的架构和没有高速缓存的旧架构都是如此。因此,当使用float s insead更广泛的数据类型时,您最多只能使用一半的可用带宽。

因此,只需从float切换到float2,或多或少会使带宽加倍,因为相同数量的内存事务将加载两倍的数据。此外,对于每个事务,工作项现在将具有两倍的数据来处理:这使得更容易隐藏负载的延迟(您只需要float所需的工作项的一半)。

float2float4的改进相当不那么激烈,但你通常会看到一些。这是因为GPU设计为工作项加载128位数据(考虑4个投影坐标或4个颜色分量(RGBA))。硬件方面,这并不比加载64位数据更有效(实际上,提供float4的事务通常需要两倍才能提供float2 s。 但是,硬件设计用于通过单个指令来实现128位数据的加载(这导致后台的两个事务)。这样更有效,特别是在循环中,因为它导致更少的循环迭代来处理相同数量的数据(请记住,在循环中,下一个加载指令依赖于先前的索引增加,因此您是有效的摆脱一对依赖指令。)

请注意,继续float8float16进一步改进,因为硬件是为这些数据类型设计的(在GPU上),实际上这些类型的负载通常会破坏合并或恶化高速缓存行使用,导致性能下降。