为OpenCL安排内存

时间:2013-09-03 06:29:09

标签: opencl

我有大约10 numpyn项目数组。全局标识为i的OpenCL工作程序仅查看每个数组的i元素。我该如何安排记忆?

我在考虑在显卡上交错数组,但我不确定这是否会有任何性能提升,因为我不了解工作组内存访问模式。

1 个答案:

答案 0 :(得分:1)

我不熟悉numpy,但是如果:

  • 具有全局标识i的主题查看i元素(如您所述)
  • 数据类型具有适当的内存对齐(4,8,16)
  • 每个线程一次读取32,64,128位

由于合并的内存访问,您应该能够实现最佳的内存吞吐量。在这种情况下,交错不会带来任何性能提升。

如果未满足最后两点之一,并且您可以通过交错实现它们,则可以看到性能提升。

编辑:阵列结构(SoA)与结构阵列(AoS)

这一点可以在文献中找到。我会做的很简短:

为什么SoA优于AoS?想象一下,你有10个32位数据类型的数组。 AoS解决方案如下:

struct Data
{
   float a0;
   float a1; 
   ...
   float a9;
}; // 10 x 32bit = 320 bit 

struct Data array[512];

内存读取怎么样?内存不对齐而没有任何更改,内存传输无法合并。但是,需要阅读的代码很短:

Data a = array[i];

幸运的是,编译器足够智能,至少可以合并一些读取指令。一个选项是显式内存对齐。这将使您的全局内存消失,这在GPU上非常有限。

现在的SoA解决方案:

struct Data
{
    float a0[512];
    float a1[512]; 
    ...
    float a9[512];
};

struct Data array;

访问内存的工作稍微复杂一些,但是每次访问都可以在合并读取中组合,并且不需要内存对齐。您也可以忘记结构并使用每个数组,而不会出现任何性能问题。

可以使用的另一件事是矢量化数据类型(如果你的numpy数组允许这样)。您可以使用float2,float4(或其他简单数据类型,如int,double ...)来利用组合内存传输,即每次读取float4数组都会在128位内存传输中合并,从而最大限度地提高内存吞吐量。