本文介绍了在结构阵列(AoS)和阵列结构(SoA)之间来回切换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在许多有关面向数据的设计的著作中扮演重要角色的一项功能是,在许多情况下,而不是AoS(结构数组):

One feature that plays a prominent role in many of the writings on data oriented design is that there are many cases where rather than AoS (array of structs):

struct C_AoS {
  int    foo;
  double bar;
};

std::vector<C_AoS> cs;
...
std::cout << cs[42].foo << std::endl;

在SoA(数组结构)中安排数据的效率更高:

it is more efficient to arrange one's data in SoA (struct of arrays):

struct C_SoA {
  std::vector<int>    foo;
  std::vector<double> bar;
};

C_SoA cs;
...
std::cout << cs.foo[42] << std::endl;

现在,我正在寻找一种解决方案,该解决方案使我可以在不更改调用接口的情况下在AoS和SoA之间进行切换,即,我可以以最小的努力,并且没有额外的运行时成本(至少达到过度间接),例如cs[42].foo;不管我使用的是哪种数据排列方式.

Now what I am looking for is a solution which would allow me to switch between AoS and SoA without changing the calling interface, i.e. that I could, with minimal effort and with no extra runtime cost (at least to the point of excessive indirection), call e.g. cs[42].foo; regardless of which arrangement of data I'm using.

我应该注意,上面的示例语法是理想的情况,这很可能是不可能的,但是我也会对近似近似感兴趣.有参加者吗?

I should note that the example syntax above is the ideal case, which might very well be impossible, but I'd be very interested in close approximations, too. Any takers?

推荐答案

我将选择以下语法:cs.foo[42]为单一语法,并使用typedef在各种排列之间进行切换:

I'm going to choose this syntax: cs.foo[42] to be the single syntax and use typedefs to switch between arrangements:

因此,很明显,根据您的帖子给出的C_SoA,上述语法有效,我们可以:

So, obviously given C_SoA from your post, the above syntax works and we can have:

typedef C_SoA Arrangement;

Arrangement cs;

为了使用std::vector<C_AoS>,我们将不得不引入其他内容:

In order to use std::vector<C_AoS> instead we are going to have to introduce something else:

typedef std::vector<C_AoS> AOS;

template<class A, class C, class T>
struct Accessor {
    T operator[](size_t index){
            return arr[index].*pMember;
    }
    T (C::*pMember);
    A& arr;
    Accessor(A& a, T (C::*p)): arr(a), pMember(p){}
};

struct Alt_C_AoS{
    Accessor<AOS, C_AoS, int> foo;
    Accessor<AOS, C_AoS, double> bar;

    AOS aos;
    Alt_C_AoS():foo(aos, &C_AoS::foo), bar(aos, &C_AoS::bar){}
};

现在我们可以拥有:

//Choose just one arrangement
typedef Alt_C_AoS Arrangement;
//typedef C_SoA Arrangement;

Arrangement cs;
...
std::cout << cs.foo[42] << std::endl;

本质上,这会将container dot member index转换为container index dot member.

Essentially this converts container dot member index into container index dot member.

这篇关于在结构阵列(AoS)和阵列结构(SoA)之间来回切换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-29 09:41