首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >提供对SoA的AoS访问

提供对SoA的AoS访问
EN

Stack Overflow用户
提问于 2017-02-12 12:43:58
回答 2查看 362关注 0票数 0

我在内存中以数组结构(SoA)或指针结构(SoP)形式布局数据,并且能够访问这些数据,就好像它是以结构数组(AoS)形式布局的一样--代码如下所示。

但是,我对struct AoS_4_SoP的使用并不是很满意--尽管这个struct似乎使用了模板,但它并不是真正通用的,因为例如,foobar在其中是硬编码的。

两个问题/请求:

1)在读写性能上,AoS访问是否和直接SoA访问一样好?

2)更通用的方案是什么?(我看过quamranacode here,但它也没什么用。)

代码语言:javascript
复制
struct  SoP{      // Structure of Pointers
   int    *foo{ nullptr };
   double *bar{ nullptr };
   SoP( int *xi, double *xd ):foo(xi), bar(xd){};
};

struct SoR{       // Structure of References
   int    &foo;
   double &bar;
   SoR( int &xi, double &xd ):foo(xi), bar(xd){};
};

template< typename T,  typename S >
struct AoS_4_SoP {
    AoS_4_SoP( T *x ) : p( x ){};
    T    *p;

          S  operator[](std::size_t idx) const { return { p->foo[idx], p->bar[idx] }; }
    const S  operator[](std::size_t idx) const { return { p->foo[idx], p->bar[idx] }; }
};

下面是一个main(),展示了上面的用法:

代码语言:javascript
复制
int main()
{
    std::vector< int    > ibuf{ 11, 22, 33, 44 };
    std::vector< double > dbuf{ 0.11, 0.22, 0.33, 0.44 };;

    SoP  x_sop( ibuf.data(),  dbuf.data() );

    ibuf.at(2)  = 333;
    std::cout << "Access via SoP syntax:\n      "
              << x_sop.foo[2]
              << "        "
              << x_sop.bar[2] << std::endl;

    AoS_4_SoP<SoP, SoR> xacc( &x_sop );

    std::cout << "Access via AoS syntax:\n      "
              << xacc[2].foo
              << "        "
              << xacc[2].bar << std::endl;

    // show write access via SoA syntax
    ibuf.at(2)   = 3333;
    dbuf.at( 2 ) = 0.333333;  // will get overwritten below
    xacc[2].bar = 0.3333;

    std::cout << "Values written via SoP, read via SoP:\n      "
              << x_sop.foo[2]
              << "       "
              << x_sop.bar[2] << std::endl;

    // show write access via AoS syntax
    xacc[2].foo = 333333;
    dbuf.at( 2 ) = 0.3333333333;  // will get overwritten below
    xacc[2].bar = 0.333333;

    std::cout << "Values written via AoS, read via AoS:\n      "
              << xacc[2].foo
              << "     "
              << xacc[2].bar << std::endl;
}

上面的代码可以通过以下方式编译:

代码语言:javascript
复制
// x86_64-w64-mingw32-g++.exe -D_WIN64 -Wall -Wextra -Werror -std=c++11 -O3 -static-libgcc -static-libstdc++ aossoa.cc -o aossoa.exe

并产生以下输出:

代码语言:javascript
复制
Access via SoP syntax:
      333        0.33
Access via AoS syntax:
      333        0.33
Values written via SoP, read via SoP:
      3333       0.3333
Values written via AoS, read via AoS:
      333333     0.333333
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-02-14 04:58:06

我认为这个模板会起作用。

代码语言:javascript
复制
template<class T, class U, class D, class S>
struct Accessor {
    T* p;
    U* (T::*pFirst);
    D* (T::*pSecond);
    S operator[](size_t index) {
        return {(p->*pFirst)[index], (p->*pSecond)[index]};
    }
    Accessor(T* p_, U * (T::*pF), D * (T::*pS)): p(p_), pFirst(pF), pSecond(pS) {}
};

void main() {
    std::vector< int    > ibuf{ 11, 22, 33, 44 };
    std::vector< double > dbuf{ 0.11, 0.22, 0.33, 0.44 };;

    SoP  x_sop(ibuf.data(),  dbuf.data());

    Accessor<SoP, int, double, SoR> aos(&x_sop, &SoP::foo, &SoP::bar);

    aos[0].foo;
}

现在,模板访问器对T成员的名称一无所知。

至少它可以在VS2015下编译

票数 1
EN

Stack Overflow用户

发布于 2017-02-13 03:46:26

以下是我针对“反向”用例(SoA access for AoS)对quamrana解决方案的修改:

代码语言:javascript
复制
template<class T, class S, class M0, class M1>
struct Accessor2{
    T*  p;
    M0  m0;
    M1  m1;

          S operator[](std::size_t idx)       { return { m0[idx], m1[idx] }; }
    const S operator[](std::size_t idx) const { return { m0[idx], m1[idx] }; }

    Accessor2(T* x, M0 p0, M1 p1): p(x), m0(p0), m1(p1){}
};

template< typename T,  typename S >
struct AoS_4_SoP : public Accessor2<T, S, decltype(T::foo), decltype(T::bar)>
{
#ifndef COMPILER_CAN_INFER_PARENT_CLASS_TEMPLATE_SPECIFICATION
    AoS_4_SoP(T *x) : Accessor2<T, S, decltype(T::foo), decltype(T::bar)>
                      (x, x->foo, x->bar ){}
#else
    AoS_4_SoP(T *x):Accessor2(x, x->foo, x->bar ){}
#endif
};

关于#ifndef COMPILER_CAN_INFER_PARENT_CLASS_TEMPLATE_SPECIFICATION,我使用的编译器(即g++ 6.2.0 (x86_64_6.2.0_posix_seh_rt_v5_rev1/mingw64/bin/x86_64-w64-mingw32-g++.exe)无法推断出父类的模板规范。但是,正如Lightness Races in Orbit所说的on this page:基类的注入类名对于编译器来说应该是足够的信息。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42184288

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档