![](/img/trans.png)
[英]Accessing to all the elements from the single member type from the struct in c++
[英]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;
还有,有更好的方法来接近上述?
如果所有结构字段都不同,则情况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.