我已经在这里发布了这个问题,但是因为这可能不是Qt特有的,我想我也可以在这里尝试一下我的机会。 我希望这样做不是不恰当的(只要告诉我是否是这样)。
我开发了一个小的科学程序,执行一些math计算。 我试图优化它,以便尽可能快。 现在我几乎完成了对Windows,Mac和Linux用户的部署。 但是我还没能在很多不同的电脑上testing它。
这是我的麻烦:为Windows部署,我已经使用了一台同时安装了Windows 7和Ubuntu 12.04的笔记本电脑(双启动)。 我比较了在这两个系统上运行的应用程序的速度,我惊讶地发现它在Windows上的速度至less是它的两倍! 如果有一个小小的差异,我不会感到惊讶,但是怎么能说明这种差别呢?
这里有一些精确度:
我很困扰,在Windows上,这个应用程序太慢了(2到4次),真的很奇怪。 另一方面,我还没有尝试过与Windows的其他计算机。 不过,你有什么想法,为什么不同?
附加信息:一些数据…
尽pipeWindows似乎在使用两个内核,但我认为这可能与线程pipe理有关,原因如下:
样本计算n°1(此次启动2个QThreads):
样本计算n°2(这个启动3个QThreads):
样本计算n°3(这个启动6个QThreads):
哪里:
(当然,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的速度可能会降低两倍以上!