【问题标题】:Same program faster on Linux than Windows -- why?Linux 上的相同程序比 Windows 更快——为什么?
【发布时间】:2011-12-25 16:34:08
【问题描述】:

解决方案在问题Executable runs faster on Wine than Windows -- why? Glibc 的floor() 可能是根据系统库实现。


我有一个非常小的 C++ 程序(约 100 行)用于物理模拟。我在同一台计算机上的 Ubuntu Oneiric 和 Windows XP 上使用 gcc 4.6.1 编译了它。我使用了完全相同的命令行选项(相同的 makefile)。

奇怪的是,在 Ubuntu 上,程序完成的速度比在 Windows 上快得多(~7.5 秒对 13.5 秒)。此时我认为这是编译器的差异(尽管使用相同的版本)。

但更奇怪的是,如果我在 wine 下运行 Windows 可执行文件,它仍然比在 Windows 上快(我得到 11 秒的“真实”时间和 7.7 秒的“用户”时间——这包括 wine 启动。)

我很困惑。当然,如果相同的代码在同一个 CPU 上运行,那么时间上应该不会有差异。

这可能是什么原因?我做错了什么?

该程序执行最少的 I/O(输出单行),并且仅使用来自 STL 的固定长度 vector(即不应涉及系统库)。在 Ubuntu 上我使用了默认的 gcc,在 Windows 上我使用了Nuwen distribution。我在进行基准测试时验证了 CPU 使用率接近于零(我关闭了大多数程序)。在 Linux 上,我使用 time 进行计时。在 Windows 上,我使用了timethis.exe

更新

我做了一些更精确的计时,比较了 Windows XP、Wine 和 Linux 上 gcc 和 msvc 编译程序的不同输入的运行时间(运行时间必须与输入成比例)。所有数字都以秒为单位,并且至少是 3 次运行的最小值。

在 Windows 上我使用timethis.exe(墙上时间),在 Linux 和 Wine 上我使用时间(CPU 时间)。 (timethis.exe 在 Wine 上损坏)我确定没有其他程序在使用 CPU 并禁用了病毒扫描程序。

gcc 的命令行选项是 -march=pentium-m -Wall -O3 -fno-exceptions -fno-rtti(即异常被禁用)。

我们从这些数据中看到的:

  1. 差异不是由于进程启动时间,因为运行时间与输入成正比

  2. 在 Wine 和 Windows 上运行的区别只存在于 gcc 编译的程序,而不是 msvc 编译的程序:不能由其他程序在 Windows 上占用 CPU 或 timethis.exe 被破坏.

【问题讨论】:

  • 这个东西占用了多少内存?您是否尝试过在分析器下运行它?
  • 这就像说如果 2 辆不同的汽车(一辆卡车和一辆小型跑车)使用相同的引擎,它们应该以相同的速度加速?
  • 会不会是Windows上的启动时间比较长?如果让程序运行时间更长,对 Windows 和 Linux 的时差有何影响?
  • @bdonlan 根据 Process Explorer,它使用的内存不到 1 MB。
  • @celtschk 我会检查的。我无法快速回复,因为我需要重新启动才能在 Linux 上进行测试。

标签: c++ windows linux gcc benchmarking


【解决方案1】:

您会惊讶于所涉及的系统库。只需在您的应用上执行 ldd,然后查看使用了哪些(好吧,没那么多,但肯定是 glibc)。

为了完全相信您对执行速度的发现,您需要按顺序运行您的应用几次并取平均执行时间。可能是操作系统加载器比较慢(虽然 4s 是一个很长的加载时间)。

其他非常可能的原因是:

  1. 不同的 malloc 实现
  2. 异常处理,如果使用到极端可能会导致速度变慢(Windows GCC、MinGW,可能不是最佳的异常处理明星)
  3. 依赖于操作系统的初始化:需要在 Windows 上的程序启动时完成的事情,而不是在 Linux 上。

其中大部分都很容易进行基准测试;-)


更新您的更新:您现在唯一能做的就是配置文件。停止猜测,让分析器告诉你时间花在了哪里。使用 gprof 和 Visual Studio 内置分析器并比较在不同函数中花费的时间。

【讨论】:

  • 我跑了很多次,以确保时间正确(我学的是物理,所以我在实验课上学到了这一课)。好的,所以首先我将单次运行时间增加到一分钟以上,我将禁用异常(我没有使用它们),将使用 C 样式数组代替 std::vector 来摆脱所有malloc/new,那我再试一次。这需要一段时间,因为我也需要重新启动。
  • 请查看我对问题的编辑。我排除了第 2 点和第 3 点。第 1 点仍然是一种可能性,但据我了解,我的程序不应该在堆上分配内存,除非在启动时初始化 std::vector
【解决方案2】:

在代码中进行基准测试。也尝试用visual studio编译。在 Windows 上,如果您有一些应用程序(例如 Yahoo Messenger)正在安装挂钩,它们可以很容易地减慢您的应用程序加载时间。

在 Windows 上,您拥有:QueryPerformanceCounter 在 Linux 上:clock_gettime

【讨论】:

    【解决方案3】:

    显然差异与系统有关。

    您可以使用strace 来了解系统调用的执行情况,例如

    strace -o /tmp/yourprog.tr yourprog
    

    然后查看/tmp/yourprog.tr

    (如果 Windows 上存在 strace 的等效项,请尝试使用它)

    也许您的程序正在分配内存(使用mmap 系统调用),也许与内存相关的系统调用在 Linux(甚至在 Wine)上比在 Windows 上更快?或者其他一些系统调用在 Linux 上提供比在 Windows 上更快的功能。

    注意。我对 Windows 一无所知,因为我从 1986 年开始使用 Unix 系统,从 1993 年开始使用 Linux。

    【讨论】:

    • 我会试试的。关于您对标题的编辑,相同的可执行文件也存在差异,在 Windows 或 Wine 上运行(不仅仅是在不同系统上编译源代码时)。这对我来说真的很奇怪。
    • 当你使用 Wine 时,你是在间接使用 Linux 内核。所以这并不奇怪(在 Wine 和 Linux 下,你使用的是同一个内核)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-04
    • 1970-01-01
    • 2010-09-08
    • 2014-08-02
    • 2015-07-18
    • 1970-01-01
    相关资源
    最近更新 更多