繁体   English   中英

C ++ Cache友好的方式访问`vector的所有元素的所有成员 <struct_type> `

[英]C++ Cache friendly way of accessing all the members of all elements of a `vector <struct_type>`

我有兴趣优化我的多线程计算代码。 在缓存,流水线操作或内存访问的任何其他方面,如何比较保存这些资源:

情况1

struct something{
    float a;
    float b;
    int c;
    bool d;
};

vector <something> vec(n, something());

for(int q=0; q<n; q++)
    {
         vec[q].a = expression1;
         vec[q].b = expression2;
         vec[q].c = expression3;
         vec[q].d = expression4;
    } 

案例2

struct something{
    float a;
    float b;
    int c;
    bool d;
};

vector <something> vec(n, something());

for(int q=0; q<n; q++)
    vec[q].a = expression1;
for(int q=0; q<n; q++)
    vec[q].b = expression2;
for(int q=0; q<n; q++)
    vec[q].c = expression3;
for(int q=0; q<n; q++)
    vec[q].d = expression4;

案例3

vector <float> a(n);
vector <float> b(n);
vector <int>   c(n);
vector <bool>  d(n); 

for(int q=0; q<n; q++)
    a[q] = expression1;
for(int q=0; q<n; q++)
    b[q] = expression2;
for(int q=0; q<n; q++)
    c[q] = expression3;
for(int q=0; q<n; q++)
    d[q] = expression4;

还有,有更好的方法来接近上述?

  • 案例1是最具可读性的。
  • 案例1案例3同样缓存友好。 两者都只通过所有数据。*
  • 情况2是最糟糕的,因为它对数据进行了4次传递 - 每次只传递一个元素。

如果所有结构字段都不同,则情况3具有可能可矢量化的巨大优势,而情况1则不具有。

原因是因为案例3数组打包的结构 ,它将所有相同的数据类型顺序放在一起存储在内存中 - 从而暴露了向量化。

编辑:

* 案例3可能比案例1更加缓存友好,因为它不需要struct-padding - 因此数据大小更小。

在缓存访问方面,案例2显然是最糟糕的:它会将内存重新加载到缓存中4次。

情况3与填充数据时的情况1相同,但可能更糟糕以供以后使用(假设abcd是相关的并且可能一起读取)。

这个比案例1更好:

for (vector<something>::iterator it = vec.begin(); it != vec.end(); ++it)
{
    it->a = e1;
    it->b = e2;
    it->c = e3;
    it->d = e4;
}

什么会更快取决于很多事情。 例如,以错误的顺序计算复杂表达式可能比任何缓存未命中都要糟糕得多。 如果不进行真正的分析,你就不应该做出纯粹的理论选择。

案例1是最好的。 案例3在缓存访问方面同样出色,但是额外的循环会带来轻微的性能开销。 案例2是你必须避免的。

但是你为什么不运行一些基准测试,让我们知道结果呢?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM