我目前正在考虑将我的CUDA内核中使用的数据存储从结构阵列(AoS)转换为数组结构(SoA)。
我有一个结构化的Element
struct Element
{
float3 origin;
float3 direction;
uint8_t count1;
uint8_t count2;
unsigned int index;
float distance;
uint16_t instanceId;
uint64_t hash;
};
这些结构在kernel1
中作为一个整体写入一个驻留在全局内存中的数组中,然后在多个后续内核中使用条目的子集。
我现在可以将其转换为以下结构:
struct ElementSoA
{
float3 origin[N];
float3 direction[N];
uint8_t count1[N];
uint8_t count2[N];
unsigned int index[N];
float distance[N];
uint16_t instanceId[N];
uint64_t hash[N];
};
问题:
1)如果在kernel1
中有8个单独的“小”写,而不是一个“大”写,那么写性能会受到影响吗?
2)在ElementSoA
中“打包”条目的部分是否有意义,例如将count1
和count2
组合成一个
struct uint8_2
{
uint8_t count1;
uint8_t count2;
};
3)如果“包装”有用,是否有一种计算的方法-- ElementSoA
的最优结构?假设我有一个每个内核读取访问的列表,如下所示:
kernel2
:origin
,direction
,hash
kernel3
:count1
,count2
,distance
,hash
我要求计算最优解的原因是,我有多个结构,它们包含的条目比Element
还要多,所以需要实现和测试大量的组合。
发布于 2015-06-22 18:23:49
假设线程i
访问元素i
,并且只访问元素i
。从上下文来看,情况似乎是这样的。
如果在kernel1中有8个单独的“小”写,而不是一个“大”写,那么写性能会受到影响吗?
是。应该更快些。“大”写入将由编译器拆分为多个小写入,每个写入都将被跨出。当访问模式不跨时,内存子系统的工作性能要好得多。
这里值得指出的是,您所使用的float3
类型也将像这样工作,并且将被分割为三个32位的事务。但是,您也没有理由不能将这些代码从AoS转换为SoA。
在
ElementSoA
中“打包”条目的部分内容有意义吗?
是。更大的对齐功率两种类型(在目前的硬件,多达128位)允许硬件加载和存储效率更高。两者之间的差别并不大,但如果很容易做到,那往往是值得的。
如果“包装”有用的话,是否有办法计算--
ElementSoA
的最优结构?
没有办法计算这个。一个问题是内核具有不同的特性。它可能是一个很强的带宽限制,所以使用有效的负载将有所帮助。另一个可能是计算界,因此更有效的负载不会有多大帮助。
https://stackoverflow.com/questions/30980767
复制相似问题