解决方案1: 如果我有类似的课程,
class car{ public: int a; string b; bool c;};
我可以制作200辆汽车的载体:
std::vector<car> allcas;
allcars.resize(200)
在运行时,我只是这样做:
this_car=allcars[102];
然后......
解决方案2:
我有
std::vector<int> a; a.resize(200);
std::vector<string>b; b.resize(200);
std::vector<bool> c; c.resize(200);
this_car_a = a[102];
this_car_b = b[102];
this_car_c = c[102];
问题: 哪一个更快?
有没有人有想法?非常感谢!
答案 0 :(得分:15)
如果a
,b
和c
属于一起并形成对象,为什么你会分裂它们?首先考虑清晰度和可读性。之后还有其他任何事情发生。另外,我认为v2会慢一些。更多访问矢量。没有时间。一如既往地关于速度的问题,时间。
答案 1 :(得分:10)
CPU喜欢预取。
如果您要按照以下模式线性遍历您的数据...
abcabcacb...
...然后你用解决方案#1改善(性能方面)。如果您要以下列方式访问它们:
aaa...bbb..ccc...
...然后去寻找解决方案#2。
然而,如果您不打算进行线性遍历,或者您实际上没有对代码进行基准测试,并得出结论,您确实需要从这段代码中挤出最后一滴性能,使您的可维护性受到青睐并坚持使用解决方案#1。
---编辑---
在多线程环境中,数据的物理布局可能会导致false sharing。从本质上讲,保持不同线程同时访问的数据可能会导致缓存争用并破坏可伸缩性。
因此,如果您同时从一个线程访问a
而从另一个线程同时访问b
,则可能值得将它们分开并实施解决方案#2。另一方面,如果您访问两个“兄弟”a
,请坚持使用解决方案#1。
---编辑2 ---
对于这个主题的优秀处理,我热烈推荐Herb Sutter的演讲“你的编程语言永远不会告诉你的东西”,仍可在以下网址找到:
http://video.google.com/videoplay?docid=-4714369049736584770 http://www.nwcpp.org/Downloads/2007/Machine_Architecture_-_NWCPP.pdf
答案 2 :(得分:10)
“矢量结构”比“结构矢量”具有几个优点:
另一方面,过早优化是万恶之源:
所以,我建议默认情况下使用结构向量,但要记住结构向量作为替代方法(即,如果您期望顺序/本地访问模式,请确保您可以稍后切换)前面不花费太多精力)。程序运行后,您可以对其进行概要分析,以查看性能关键部分的位置,并尝试使用矢量结构和矢量化操作,以便它们能够做得最好。
答案 3 :(得分:2)
首先,出于可维护性的原因,拆分它们是一个可怕的想法,这应该是您最关心的问题。
其次,您只需将分配时间增加三倍(三次分配而不是一次),解除分配时间(相同),并破坏参考的缓存局部性(可能是减速)。
第三,唯一的好处是,如果您只为所有汽车一遍又一遍地阅读一个成员,并且很少改变汽车。
答案 4 :(得分:2)
这实际上取决于您希望如何使用数据。例如,如果您只想访问一个字段:
car this_car = allcars[12];
cout << this_car.a;
然后这会导致您创建this_car的副本。在这种情况下,您将不必要地复制字段b和c。当然,你可以通过引用来解决这个问题:
car & this_car = allcars[12];
这可能仍然比只做
慢a = a[12];
但是,如果要访问类的多个属性,那么将它们存储在一起几乎肯定更好。此时,由于locality of reference,您可能会获得更好的性能,但它完全依赖于编译器,内存管理器等。
最后,最佳表现的答案是:它取决于。这肯定不是瓶颈决定,将它们保存在单个结构中以获得代码可读性/您自己的理智当然更好。
答案 5 :(得分:1)
这取决于struct成员的大小和模式访问。一个单例访问是无关紧要的,但考虑你对向量进行迭代,而你只对成员a
感兴趣。结构越宽,结构条目在缓存行中的适应性就越少,缓存未命中的次数也就越多。在向量中移动所有a
个成员会增加缓存行密度,从而提高性能。它可能非常重要(1.5倍,2倍甚至更多)。
然而,重点关注代码可维护性,使其可读,可调试且易于重构更为重要。代码应该清楚地表达意图。您询问的这种微观优化只应考虑测量的瓶颈。获取Software Optimization Cookbook的副本。