最快的数组结构到结构数组的转换
Fastest Possible Struct-of-Arrays to Array-of-Structs Conversion
我的结构如下所示:
struct SoA
{
int arr1[COUNT];
int arr2[COUNT];
};
我希望它看起来像这样:
struct AoS
{
int arr1_data;
int arr2_data;
};
std::vector<AoS> points;
尽快。必须保留顺序。
是单独构建每个 AoS
对象并将其推回最快的方法,还是有更快的选择?
SoA before;
std::vector<AoS> after;
for (int i = 0; i < COUNT; i++)
points.push_back(AoS(after.arr1[i], after.arr2[i]));
Whosebug 上有 SoA/AoS 个相关问题,但我没有找到与最快转换相关的问题。由于结构包装差异,我看不出有什么方法可以避免将数据从一种格式复制到另一种格式,但我希望有人能告诉我有一种方法可以简单地以不同方式引用数据并避免复制。
特别鼓励非主流解决方案。
SoA
和AoS[]
/std::vector<AoS>
的二进制布局是不同的,所以如果不进行复制操作,真的没法转换。
您拥有的代码非常接近最佳 - 一项改进可能是使用预期的元素数量预分配向量。或者尝试使用原始数组构建整个元素和每个 属性 初始化。需要仔细衡量更改(绝对是使用具有您期望的数组大小的完全优化构建来衡量)并根据代码的 readabilty/correctness 进行加权。
如果您不需要精确的二进制布局(似乎是这种情况,因为您正在使用向量),您可以通过创建一些自定义 类 以不同方式公开现有数据来实现类似的语法.这将完全避免复制。
您需要 "array" 类型(在 SoA
的实例上提供 indexing/iteration)和 "element" 类型(使用对 SoA 实例和索引的引用初始化,公开访问器对于该索引处的单独字段)
代码草图(添加迭代器,...):
class AoS_Element
{
SoA& soa;
int index;
public:
AoS_Element(SoA& soa, int index) ...
int arr1_data() { return soa.arr1[index];}
int arr2_data() { return soa.arr2[index];}
}
class AoS
{
SoA& soa;
public:
AoS(SoA& _soa):soa(_soa){}
AoS_Element operator[](int index) { return AoS_Element(soa, index);}
}
我的结构如下所示:
struct SoA
{
int arr1[COUNT];
int arr2[COUNT];
};
我希望它看起来像这样:
struct AoS
{
int arr1_data;
int arr2_data;
};
std::vector<AoS> points;
尽快。必须保留顺序。
是单独构建每个 AoS
对象并将其推回最快的方法,还是有更快的选择?
SoA before;
std::vector<AoS> after;
for (int i = 0; i < COUNT; i++)
points.push_back(AoS(after.arr1[i], after.arr2[i]));
Whosebug 上有 SoA/AoS 个相关问题,但我没有找到与最快转换相关的问题。由于结构包装差异,我看不出有什么方法可以避免将数据从一种格式复制到另一种格式,但我希望有人能告诉我有一种方法可以简单地以不同方式引用数据并避免复制。
特别鼓励非主流解决方案。
SoA
和AoS[]
/std::vector<AoS>
的二进制布局是不同的,所以如果不进行复制操作,真的没法转换。
您拥有的代码非常接近最佳 - 一项改进可能是使用预期的元素数量预分配向量。或者尝试使用原始数组构建整个元素和每个 属性 初始化。需要仔细衡量更改(绝对是使用具有您期望的数组大小的完全优化构建来衡量)并根据代码的 readabilty/correctness 进行加权。
如果您不需要精确的二进制布局(似乎是这种情况,因为您正在使用向量),您可以通过创建一些自定义 类 以不同方式公开现有数据来实现类似的语法.这将完全避免复制。
您需要 "array" 类型(在 SoA
的实例上提供 indexing/iteration)和 "element" 类型(使用对 SoA 实例和索引的引用初始化,公开访问器对于该索引处的单独字段)
代码草图(添加迭代器,...):
class AoS_Element
{
SoA& soa;
int index;
public:
AoS_Element(SoA& soa, int index) ...
int arr1_data() { return soa.arr1[index];}
int arr2_data() { return soa.arr2[index];}
}
class AoS
{
SoA& soa;
public:
AoS(SoA& _soa):soa(_soa){}
AoS_Element operator[](int index) { return AoS_Element(soa, index);}
}