哪个更快? “结构矢量”或“一些矢量”?

时间:2011-09-01 17:44:21

标签: c++ performance algorithm vector

解决方案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];

问题: 哪一个更快?

有没有人有想法?非常感谢!

6 个答案:

答案 0 :(得分:15)

如果abc属于一起并形成对象,为什么你会分裂它们?首先考虑清晰度和可读性。之后还有其他任何事情发生。另外,我认为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)

“矢量结构”比“结构矢量”具有几个优点:

  • 如果你的内部循环没有使用结构的每个元素,那么struct-of-vectors可以节省内存带宽,因为未使用的元素向量不会被加载到缓存中。
  • 矢量化更容易。向量结构可以使您使用处理器的向量处理指令(通过汇编,内在函数或聪明的编译器)来加速内部循环。

另一方面,过早优化是万恶之源:

  • 使用矢量结构更加困难,笨拙和模糊。
  • 在代码启动并运行之前,您通常不知道性能瓶颈在哪里。是否值得让你的代码更冗长,更脆弱,更难?在你真正描述它之前,你不会知道。
  • 矢量结构编程的好处因具体情况而异。它并不总能产生加速;实际上,你的表现可能会更差。
  • 特别是,如果您的访问模式是随机的(与顺序或其他本地化相对),则向量结构组织最终可能会从内存中加载大量更多无用数据(如果每个缓存行)包括来自多个附近物体的元素......

所以,我建议默认情况下使用结构向量,但要记住结构向量作为替代方法(即,如果您期望顺序/本地访问模式,请确保您可以稍后切换)前面不花费太多精力)。程序运行后,您可以对其进行概要分析,以查看性能关键部分的位置,并尝试使用矢量结构和矢量化操作,以便它们能够做得最好。

答案 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的副本。