【问题标题】:Fastest Possible Struct-of-Arrays to Array-of-Structs Conversion最快的可能的结构数组到结构数组的转换
【发布时间】:2015-07-10 20:34:40
【问题描述】:

我的结构如下所示:

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]));

StackOverflow 上有与 SoA/AoS 相关的问题,但我没有找到与最快可能转换相关的问题。由于结构打包差异,我看不到任何方法可以避免将数据从一种格式复制到另一种格式,但我希望有人能告诉我有一种方法可以简单地以不同方式引用数据并避免复制。

特别鼓励采用现成的解决方案。

【问题讨论】:

  • 我怀疑你可以“简单地以不同的方式引用数据”,因为它在内存中的排列方式不同。
  • 无论如何您都需要插入/推送它们,否则您的vector 将处于无效状态。
  • 请注意,以不同方式引用数据实际上可能并不比复制更快... RAM 缓存在线性读取或写入内存时最有效,并且执行大量取消引用可能会破坏这种情况模式,导致大量缓存未命中,因此执行速度较慢。 (也许不是,但关键是要从两个方面进行衡量,并准备好在你的直觉与现实不符时感到惊讶)

标签: c++ arrays struct type-conversion


【解决方案1】:

SoAAoS[]/std::vector&lt;AoS&gt; 的二进制布局不同,所以如果不进行复制操作,真的没有办法转换。

您拥有的代码非常接近最优 - 一项改进可能是预先分配具有预期元素数量的向量。或者尝试使用构建整个元素和每个属性初始化的原始数组。需要仔细测量更改(绝对使用您期望的数组大小的完全优化构建进行测量)并根据代码的可读性/正确性加权。

如果您不需要精确的二进制布局(在使用矢量时似乎就是这种情况),您可以通过创建几个以不同方式公开现有数据的自定义类来实现外观相似的语法。这将完全避免复制。

您将需要“数组”类型(提供对 SoA 实例的索引/迭代)和“元素”类型(通过对 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);}
}

【讨论】:

  • 你能扩展你提到的“数组”类型吗?你是对的,精确的二进制表示不是这里的目标,只是有效地访问元素。我没想过使用自定义迭代器
  • @ConnorLawson 我添加了非常粗略的示例(可能甚至无法编译...希望比文字更能说明我的意思)。
  • std::vector 内容具有与普通旧数组相同的二进制布局。
  • @BenVoigt 是的,但我不确定它将如何帮助将数组结构转换或 暴露(这似乎是实际目标)数组结构到结构数组无需复制数据。 (更新了问题以澄清我比较的类型)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-02
  • 2023-04-08
  • 2014-06-14
  • 1970-01-01
  • 1970-01-01
  • 2022-08-04
相关资源
最近更新 更多