问题描述
在许多有关面向数据的设计的著作中扮演重要角色的一项功能是,在许多情况下,而不是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)之间来回切换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!