C++性能:列表和迭代器

发布于 2024-12-21 02:23:10 字数 1161 浏览 3 评论 0原文

我有一些继承的内部 C++ 代码,在 Windows 上使用 VC++ 编译时,其运行速度比在 Linux 上使用 g++ 编译时快一个数量级(5 分钟 vs. 2 小时)。无论有没有“正常”优化标志,以及每个编译器和各自平台的几个不同版本,所有这些都在可比较的硬件上,情况仍然如此。

使用 g++ 在 Linux 上构建调试/配置文件版本 (-g -pg),我发现以下三个区域消耗了大部分时间:

%   cumulative   self              self     total
time   seconds   seconds    calls  Ks/call  Ks/call  name
31.95    955.93   955.93 3831474321     0.00     0.00  std::_List_const_iterator<xxFile>::operator!=(std::_List_const_iterator<xxFile> const&) const
22.51   1629.64   673.71 3144944335     0.00     0.00  std::_List_const_iterator<xxFile>::operator++()
15.56   2095.29   465.65 686529986      0.00     0.00  std::iterator_traits<std::_List_const_iterator<dtFile> >::difference_type std::__distance<std::_List_const_iterator<xxFile> >(std::_List_const_iterator<xxFile>, std::_List_const_iterator<xxFile>, std::input_iterator_tag)

(xxFile 类由整数、浮点数、双精度数、布尔值和字符串组成)

我天真的猜测是 VC++ 正在补偿某些编码不良的内容,或者 GNU STL 可能没有优化。我目前正在使用 Boost 库编译 g++/Linux 版本,从 allocate/std/list.hpp 和 boost::assign 命名空间开始。

我无法共享代码,但是根据您的经验,是否有一些明显的原因(除了我有限的 C++ 经验之外)?

I've got some inherited in-house C++ code, which when compiled with VC++ on Windows, runs an order of magnitude faster than when compiled with g++ on Linux (5 minutes vs. 2 hours). This remains the case both with and without the "normal" optimization flags, as well as over a few different versions of each compiler and respective platform, all on comparable hardware.

Building a debug/profile version (-g -pg) on Linux with g++, I see the following three areas are consuming most of the time:

%   cumulative   self              self     total
time   seconds   seconds    calls  Ks/call  Ks/call  name
31.95    955.93   955.93 3831474321     0.00     0.00  std::_List_const_iterator<xxFile>::operator!=(std::_List_const_iterator<xxFile> const&) const
22.51   1629.64   673.71 3144944335     0.00     0.00  std::_List_const_iterator<xxFile>::operator++()
15.56   2095.29   465.65 686529986      0.00     0.00  std::iterator_traits<std::_List_const_iterator<dtFile> >::difference_type std::__distance<std::_List_const_iterator<xxFile> >(std::_List_const_iterator<xxFile>, std::_List_const_iterator<xxFile>, std::input_iterator_tag)

(The xxFile class consists of ints, floats, doubles, bools, and strings)

My naive guesses are that there's something poorly coded which VC++ is compensating for or that the GNU STL may not be as optimized. I'm currently working on compiling the g++/Linux version with the Boost library, starting with assign/std/list.hpp and the boost::assign namespace.

I'm unable to share the code, but does something obvious (besides my limited C++ experience) jump out as the cause, based on your experience?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

唠甜嗑 2024-12-28 02:23:10

除了花费大量时间迭代列表之外,我会在不了解您的代码的情况下扔掉一些东西。

您需要使用列表吗?

如果您的大部分时间都花在迭代上,也许您应该使用连续的数据结构(数组/向量)。除非您出于其他原因需要列表行为(即,在其他地方进行大量插入,这可能会主导您的运行时),由于内存局部性,使用数组应该会提供更好的性能。尽管迭代数组和列表都是 O(n),但实际上,由于充分利用了 CPU 的缓存,数组可以更快。当你浏览一个列表->下一步时,你不知道你可能会在哪里结束,如果你总是出现页面错误,你的性能将会很糟糕。

您是否进行了大量搜索?也许有很多线性搜索?

事实上,运算符 != 位于列表的顶部,这使得它看起来像这样。谁这么叫的,为什么?如果您正在进行大量搜索并且这在您的运行时占据主导地位,那么您可能还需要考虑不同的数据结构,如果您进行大量插入和查找,则可能是二叉搜索树或哈希表。

A couple things I'll toss out without knowing anything about your code except that it spends a lot of time iterating lists.

Do you need to use lists?

If the bulk of your time is spent iterating, maybe you should be using a contiguous data structure (array/vector). Unless you require list behavior for some other reason (i.e., lots of insertions elsewhere, which might otherwise dominate your runtime) using arrays should give much better performance due to memory locality. Even though iterating an array and list are both O(n), in practice arrays can be much faster due to taking proper advantage of the CPU's caches. When you go through a list->next you don't know where you might end up, and if you end up page faulting all the time you will have horrible performance.

Are you doing lots of searches? Maybe lots of linear searches?

The fact that operator != is at the top of the list makes it appear this way. Who is calling that and why? If you are doing lots of searching and this dominates your runtime, you may also want to consider a different data structure, perhaps a binary search tree or hash table if you do lots of insertions and lookups.

倾其所爱 2024-12-28 02:23:10

因为最上面的项目是距离、operator++ 和operator!= 我相信您的问题是在列表上使用 size() 操作。

这是 C++ 标准允许不同实现的领域之一。 MSVC 实现将列表的大小存储为数字,因此返回值非常快。 GCC 没有,因此要获取列表的大小,它必须执行以下操作:

count = 0;
for(
    list::iterator it = l.begin()
    it != l.end();
    ++it
)
    ++count;

在该循环中,您可以看到配置文件顶部的每个操作。

Because the top items are distance, operator++ and operator!= I believe your problem is using the size() operation on a list.

This is one of those areas where the C++ standard allows different implementations. The MSVC implementation stores the size of a list as a number, so returning the value is very fast. GCC does not, so to get the size of a list it must essentially perform:

count = 0;
for(
    list::iterator it = l.begin()
    it != l.end();
    ++it
)
    ++count;

And in that loop you can see each of the operations which top your profile.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文