C ++ - 指向对象的向量的向量性能与对象的性能 [英] C++ - Performance of vector of pointer to objects, vs performance of objects

查看:146
本文介绍了C ++ - 指向对象的向量的向量性能与对象的性能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在这种情况下,问题场景是一个游戏,所以所有资源都在开始时分配,然后迭代一个级别。

In this case the question scenario is a game, so all resources are allocated at the beginning then iterated over for a level.

存储在向量中的对象是复杂类的实例,当然在加载时将它们实际复制到向量中是耗时的,但是关注度很低。

The objects being stored in the vector are instances of complex classes, and of course the actual copying them into the vector at load-time is time-consuming, but of low-concern.

但是如果我的主要是关注是在运行时迭代类对象的速度,我是否更好地将类对象本身存储在向量中,而不是像传统推荐的那样只指向类对象?

But if my main concern is the speed of iteration over the class objects at runtime, would I be better to store the class objects themselves in the vector, rather than just pointers to the class objects as is traditionally recommended?

我不担心本例中的内存管理,只考虑迭代速度。

I am not worried about memory management in this example, only speed of iteration.

推荐答案

我正在回答这个问题迟到了,但是性能方面很重要,到目前为止在线答案纯粹是理论上和/或专注于内存管理方面。所以这里是我最近尝试的三个相关场景的一些实际基准信息。你的结果可能会有所不同,但至少对实际应用中的事情有所了解。

I'm answering this question late, but the performance aspect is important and the answers online so far have been purely theoretical and/or focusing exclusively on the memory-management aspects. So here is some actual benchmarking info on three related scenarios I recently tried. Your results may be different but at least there's some idea of how things pan out in a practical application.

班级 A 有大约10个成员字段,其中一半是基元,另一半是 std :: string std :: vector< int> ; 和其他动态大小的容器。该应用程序已经相当优化,因此我们希望看到哪个架构现在为我们提供了最快的循环 A 的集合。任何 A 对象的成员字段的值可能正在改变应用程序生命周期,但是 A 对象的数量向量不会改变我们执行的许多重复迭代(这种连续迭代构成了该应用程序执行时间的大约95%)。在所有情况下,使用典型的 std :: iterator std :: const_iterator 执行循环。每个枚举的 A 对象至少访问了几个成员字段。

The class A referenced here has about 10 member fields, half of which are primitives and the other half are std::string, std::vector<int>, and other dynamically sized containers. The application has already been fairly optimized and thus we would like to see which architecture now gives us the fastest looping over the collection of A. The values of any of A object's member fields may be changing over the application lifetime, but the number of A objects in the vector do not change over the many repeated iterations we perform (this continual iterating constitutes about 95% of this application's execution time). In all scenarios, looping was performed with the typical std::iterator or std::const_iterator. Each enumerated A object has at least several member fields accessed.

场景1—对象指针的向量

虽然最简单的,这种 std :: vector< A *> 结束比其他人略慢。

Although the simplest, this architecture of std::vector<A*> ended being slightly slower than the others.

场景2—矢量对象指针,对象使用新的位置分配

这种方法背后的想法是我们可以通过强制我们的对象来改善缓存的局部性分配到连续的内存空间。所以对象指针的 std :: vector< A *> 保证与 std :: vector 实现和 A 对象本身在堆上也是连续的,因为我们已经使用了放置新的习语。我使用了与回答中概述的相同方法;有关新的展示位置的更多信息,请访问此处

The idea behind this approach is that we can improve the locality of caching by forcing our objects to be allocated into contiguous memory space. So the std::vector<A*> of object pointers is guaranteed to be contiguous by the std::vector implementation and the A objects themselves will also be contiguous on the heap because we've used the placement new idiom. I used the same approach outlined in this answer; more info on placement new can be found here.

此方案比方案1快2.7%。

This scenario was 2.7% faster than Scenario 1.

方案3—对象向量

这里我们直接使用 std :: vector< A> std :: vector 实现保证我们的 A 对象在内存中是连续的。请注意,对象的 std :: vector 确实涉及 A 的移动和复制构造函数的注意事项。为了避免不必要的移动和/或重建,最好是 std :: vector.reserve()提前可能需要的最大尺寸(如果可能),然后使用 std :: vector.emplace_back()(而不是 push_back())如果可能的话。循环使用这个结构是最快的,因为我们能够消除一个指针间接层。

Here we use std::vector<A> directly. The std::vector implementation guarantees our A objects will be contiguous in memory. Note that a std::vector of objects does involve considerations of the move and copy constructors of A. To avoid unnecessary moving and/or reconstruction, it is best to std::vector.reserve() the maximum possibly needed size in advance (if possible) and then use std::vector.emplace_back() (instead of push_back()) if at all possible. Looping over this structure was the fastest because we are able to eliminate one level of pointer indirection.

这种方法比场景1快6.4%。

This approach was 6.4% faster than Scenario 1.

另一个问题的相关答案也显示了普通对象(作为班级成员)可以比相应的指针(作为类成员)快得多。

A related answer to a different question also shows that plain objects (as class members) can be quite faster than the respective pointers (as class members).

这篇关于C ++ - 指向对象的向量的向量性能与对象的性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆