加快Qt程序的性能:Windows vs Linux

我已经在这里发布了这个问题,但是因为这可能不是Qt特有的,我想我也可以在这里尝试一下我的机会。 我希望这样做不是不恰当的(只要告诉我是否是这样)。

我开发了一个小的科学程序,执行一些math计算。 我试图优化它,以便尽可能快。 现在我几乎完成了对Windows,Mac和Linux用户的部署。 但是我还没能在很多不同的电脑上testing它。

这是我的麻烦:为Windows部署,我已经使用了一台同时安装了Windows 7和Ubuntu 12.04的笔记本电脑(双启动)。 我比较了在这两个系统上运行的应用程序的速度,我惊讶地发现它在Windows上的速度至less它的两倍! 如果有一个小小的差异,我不会感到惊讶,但是怎么能说明这种差别呢?

这里有一些精确度:

  • 我做这个程序的计算只是一些残酷而愚蠢的math计算,基本上它是在一个被称为十亿次的循环中计算乘积和余弦。 另一方面,计算是multithreading的:我启动了6个QThreads。
  • 笔记本电脑有两个核心@ 1.73Ghz。 起初我以为Windows可能没有使用其中一个内核,但是随后我看着处理器活动,根据小graphics,两个内核都运行在100%。
  • 然后我认为Windows的C ++编译器没有使用Linux的C ++编译器自动完成的优化选项(如-O1 -O2之类的东西),但显然是这样的。

我很困扰,在Windows上,这个应用程序太慢了(2到4次),真的很奇怪。 另一方面,我还没有尝试过与Windows的其他计算机。 不过,你有什么想法,为什么不同?

附加信息:一些数据…

尽pipeWindows似乎在使用两个内核,但我认为这可能与线程pipe理有关,原因如下:

样本计算n°1(此次启动2个QThreads):

  • PC1窗口:7.33s
  • PC1-linux:3.72s
  • PC2-linux:1.36s

样本计算n°2(这个启动3个QThreads):

  • PC1窗口:6.84s
  • PC1-linux:3.24s
  • PC2-linux:1.06s

样本计算n°3(这个启动6个QThreads):

  • PC1窗口:8.35s
  • PC1-linux:2.62s
  • PC2-linux:0.47s

哪里:

  • PC1-windows =我的2核笔记本电脑(@ 1.73Ghz)与Windows 7
  • PC1-linux =我的2核心笔记本电脑(@ 1.73Ghz)与Ubuntu 12.04
  • PC2-linux =我的8核心笔记本电脑(@ 2.20Ghz)与Ubuntu 12.04

(当然,PC2的速度并不令人震惊,我不可思议的是PC1-windows和PC1-linux的区别)。

注意:我也尝试在最近的PC上运行程序(4或8核心@ 3Ghz,不记得准确)在Mac OS,速度相当于PC2-linux(或稍快)。

编辑:我会在这里回答我在评论中被问到的几个问题。

  • 我只是在Windows上安装了Qt SDK,所以我想我有最新的版本(包括MinGW?)。 编译器是MinGW。 Qt版本是4.8.1。

  • 我使用没有优化标志,因为我注意到,当我build立在释放模式(与Qt造物主)时,它们自动使用。 在我看来,如果我写的东西像QMAKE_CXXFLAGS + = -O1,这只在debugging版本中有效。

  • 线程的生命周期等:这很简单。 当用户点击“计算”button时,同时启动2到6个线程(取决于他计算的内容),当计算结束时它们被终止。 没有太花哨。 每个线程只是做残酷的计算(除了一个,实际上,每30ms计算一次(不那么)小的计算,基本上检查错误是否足够小)。

编辑:最新的发展和部分的答案

这里有一些新的发展提供了所有这些答案:

  • 我想确定速度的差异是否真的与线程有关。 所以我修改了程序,以便计算只使用1个线程,这样我们就比较了“纯C ++代码”的性能。 事实certificate,现在Windows只比Linux稍微慢一些(大概是15%)。 所以我想这个差异的一小部分(但不是不重要的)部分是系统固有的,但最大的部分是由于线程pipe理

  • 作为一个人(卢卡·卡隆,感谢这一点)在评论中build议,我试图build立应用程序与Microsoft Visual Studio(MSVC),而不是MinGW的编译器。 令人惊讶的是,计算(所有线程和所有内容)现在“仅”比Linux慢20%到50%! 我想我会继续前进,满足于此。 我注意到,奇怪的是,“纯粹的C ++”计算(只有一个线程)现在甚至比MinGW慢,这必须考虑到整体的差异。 所以据我所知, MinGW比MSVC略胜一筹,只不过它像一个白痴一样处理线程

所以,我想或者有什么我可以做的MinGW(理想情况下,我宁愿使用它比MSVC)更好地处理线程,或者它不能。 我会感到惊讶,怎么可能不知道和logging? 虽然我想我应该小心得出结论,但我只是在一台计算机上比较(现在)。

另一个选项可能是:在Linux上qt只是加载,这可能会发生,即如果您使用KDE,而在Windows库中必须加载,所以这减慢了计算时间。 要检查多少库加载浪费你的应用程序,你可以写一个纯粹的c + +代码虚拟测试。

我听说过一个例子,如果你写错了,那么Windows在编写文件时速度非常慢。 (这与Qt无关)

在这种情况下,问题是开发人员使用SQLite数据库,写了大约10000个数据集,并在每次插入后执行SQL COMMIT 。 这导致Windows每次都将整个DB文件写入磁盘,而Linux只会更新RAM中文件系统inode的缓冲版本。 在这种情况下,速度差异更大:Linux上1秒,Windows上1分钟。 (在他改变SQLite只提交一次,在Windows上也是1秒)。

所以如果你把计算结果写到磁盘上,你可能想要检查一下你是否经常调用fsync()fflush() 。 如果你的代码来自一个库,你可以使用strace (仅限于Linux,但应该给你一个基本的想法)。

通过在Windows和Linux上运行互斥锁,可能会遇到性能差异。

每次锁定时,Windows上的纯互斥代码可能会有15毫秒的等待时间。 在Windows上更好的执行同步机制是关键部分 。 在大多数情况下,它并不会遇到普通互斥锁经历的锁定惩罚。

我发现在Linux上,常规互斥锁的执行与Windows上的“关键部分”相同。

这可能是内存分配器,尝试使用Google的jemalloc或tcmalloc 。 Glibc的ptmalloc3比MSVC的crt中的老式分配器好得多。 来自Microsoft的可比选项是Concurrency CRT,但不能简单地将其作为替代品放入。

我注意到我的电脑上完全一样的行为。 我运行Windows 7(64位),Ubuntu(64位)和OSX(狮子64位),我的程序比较2个XML文件(每个超过60Mb)。 它也使用多线程(2线程):

 -Windows : 40sec -Linux : 14sec (!!!) -OSX : 22sec. 

我使用个人类的线程(而不是Qt之一),它使用linux / OSX上的“pthread”和Windows上的“线程”。 我使用Qt / mingw编译器,因为我需要从Qt的XML类。

我发现没有办法(现在)有3操作系统有相似的表现…但我希望我会的!

我认为另一个原因可能是内存:我的程序使用大约500Mb的RAM。 所以我认为Unix是最好的管理方式,因为在单线程中,Windows慢了1.89倍,而且我认为Linux的速度可能会降低两倍以上!