0

我有大约 10numpy个项目数组n。具有全局 id 的 OpenCL 工作者i仅查看i每个数组的第 th 个元素。我应该如何安排内存?

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

4

1 回答 1

1

我不熟悉 numpy,但是如果:

  • 具有全局 id 的线程i查看ith 元素(如您所述)
  • 数据类型具有正确的内存对齐方式(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 位内存传输,从而最大限度地提高内存吞吐量。

于 2013-09-03T07:15:14.277 回答