我使用Windows P7使用Cython作为Python 3.22和MinGW的G++.exe作为C++(这意味着我使用LIbSTDc++作为运行时库)。我写了两个简单的程序来比较它们的速度。
Python:
1 2 3 4
| x=0
while x!=1000000:
x+=1
print(x) |
C++:
1 2 3 4 5 6 7 8 9 10 11
| #include <iostream>
int main()
{
int x = 0;
while ( x != 1000000 )
{
x++;
std::cout << x << std::endl;
}
return 0;
} |
两者都没有优化。
我先运行C++,然后通过交互命令行运行Python,这比直接启动.pyfile慢得多。
但是,Python OutRAN C++的输出速度快了两倍以上。Python花了53秒,C++花了1分54秒。
是因为Python对解释器做了一些特别的优化,还是因为C++必须引用和STD,它使它慢下来,并使它占用RAM?还是其他原因?
编辑:我用
而不是std::endl再次尝试,用-O3标志编译,这次花了1分钟才达到50万。
- 因此,根据您的基准,Python中的一个无限循环的运行速度比在C++中打印单个数字的速度快两倍?真奇怪。
- 啊,这些代码示例做了完全不同的事情…第一个甚至没有终止。
- 就在昨天,有一篇关于这个的文章…这是课堂作业还是别的?简短的回答,默认情况下,StdUT上的C++缓冲区。Python没有。
- 你的意思是在C++代码中包含一个EDCOX1×0或EDCOX1×1的循环吗?
- python缓冲stdout。
- @Kevindtimm:虽然题目相同,但这两个问题完全不同。这不是那个问题的副本。
- @Kindall:除非你是cout << endl,否则cout也一样。
- @穆宁鸭:我同意,如果OP将示例更改为实际等效,那么应该重新打开它。我也认为这可以通过使用EDCOX1×4代替EDCOX1,5在C++样本中解决。
- 问题应该是,我应该认真考虑这个问题吗?这不是一个标准化的测试,你为什么要认真对待测试结果?
- C++ iOnStudio的最终失败是什么?
- @哑巴编码员:关键是,目前还不清楚他们为什么表现不同,所以我认为值得一问。如果你不担心,那就是你的个人态度。
- 哦,我确实需要一个while循环在C++代码中…它应该是(真){x++;STD::CUT< < x>:STD::Endl;}它是程序中的一个循环,我在帖子中错误地输入了它。
- @尼古拉斯B-我的观点是运行一个循环,然后得出结果并不是一个测试,通过它你可以决定哪个更快。在那一部分,可能还有很多其他的东西要探讨,这意味着要剖析每一个特性,以及它的最终好处或结果是什么?
- 是的,我确信C++是更好的,但是我不能解决这个问题…
- @哑巴:我还是不同意。我们不需要讨论它是否是一个有用的性能测试,但它仍然令人惊讶的是,Python优于C++,除非你知道引擎盖下发生了什么。人们喜欢在这里解剖,通常只是出于好奇,而不是因为它有一些特殊的好处。
- @布苏宣:编辑问题以反映这一点。另外,您不能比较两个无限循环的运行时,因此请在相同的迭代次数后终止这些循环。
- 好吧,我试试……
- @ NIKLAS:在C++中循环是否是无限的是未定义的。;
- @Ildjarn:嗯,我想,可以用unsigned int来解决这个问题。仍然不会改变情况,因为它不应该终止于我知道的任何C++实现:
- @尼古拉斯:是的,在这个问题下,一个无关紧要的评论似乎是合适的。-P
- 猜猜看……我把极限设置为10 ^ 6,Python花了53秒,C++用了1分54秒。
- 尼克拉斯布。你觉得新的结果怎么样?
- @布苏宣:你还在用江户十一〔七〕吗?如果是这样的话,试着读一些评论(然后用'
'代替)。
- "Idjjnn我读了一遍又做了一次测试,这次是2分钟……比"Endl"慢,只不过是一个视差,但它还是比Python慢……我甚至给Python程序添加了一个带有Time.Calm函数的自定时,它只用了半分钟,仍然比C++快了大约30秒。
- @布苏宣:我看不出有什么限制,请把它加到问题上(总是这样做!)我也不能复制它,即使使用EDCOX1,5个版本,C++版本在我的机器上也快很多。您使用的是哪个版本的python?另外,您使用的是Python优化器吗?
- 我在第一个测试中使用了python3,在第二个测试中使用了python2(默认值),在第二个测试中我添加了自动计时功能……我用python3再次测试了自动计时功能,耗时1分12秒,我使用的是非优化源代码,而不是byecode。
- 现在画面变得清晰了。Python是前进的道路。有人应该介入,最后在Cyton中加入C++解释器。
- 这也证明了python3的打印速度比python2的打印速度快。
- @布苏宣:你知道吗,请把所有这些额外的信息都编辑到这个问题上?也许到时候它会重新打开。你应该添加:C++编译器、体系结构、操作系统、Python实现/版本,尤其是真正终止的代码!把这变成一个有趣的问题,人们会很麻烦的。此外,适当地对C++代码进行格式化。
- 好的,我在上面(我用的是旧格式)
- @Niklas B.完成。
- 您使用什么命令行来构建?您正在启用优化,对吗?
- 不,我正在使用Python解释器交互会话
- @布苏宣:如果你看答案,你会发现你忘了提问题中的一些东西。
- 尼克拉斯布。谢谢提醒:)
- 有人能试试打印版吗?并尝试Visual C++。
我的一位同事告诉我,Python代码比C++代码快,然后把这个主题作为一个例子来证明他的观点。现在从其他答案显而易见的是,问题是什么错误的C++代码张贴在这个问题。我仍然想总结我的基准,我做的是为了告诉他,一个好的C++代码能有多快!
原始C++代码存在两个问题:
它使用std::endl在每次迭代中打印新行。这是一个非常糟糕的主意,因为std::endl所做的工作比简单地打印新行要多,它还强制流刷新迄今为止累积的缓冲区;刷新是一项昂贵的操作,因为它必须处理硬件&ndash;输出设备。所以第一个解决方法是:如果您想打印新行,只需使用'
'。
第二个问题不太明显,因为在代码中看不到。它是在C++流中设计的。默认情况下,C++流在每次输入和输出操作之后都与C流同步,这样,您的应用程序可以混合EDCOX1、15和EDCOX1、9、EDCOX1、17和EDCOX1,18,没有任何问题。在这种情况下,不需要这个特性(是的,它是一个特性),所以我们可以禁用它,因为它有一个小的运行时开销(这不是问题;它不会使C++坏;它只是一个特性的代价)。第二个解决办法是:std::cout::sync_with_stdio(false);。
下面是最终优化的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include <iostream>
int main()
{
std::ios_base::sync_with_stdio(false);
int x = 0;
while ( x != 1000000 )
{
++x;
std::cout << x << '
';
}
} |
并使用-O3标志编译此文件,并运行(和测量)如下:
1 2 3 4 5 6 7 8
| $ g++ benchmark.cpp -O3 #compilation
$ time ./a.out #run
//..
real 0m32.175s
user 0m0.088s
sys 0m0.396s |
运行并度量python代码(发布在问题中):
1 2 3 4 5 6 7
| $ time ./benchmark.py
//...
real 0m35.714s
user 0m3.048s
sys 0m4.456s |
user和sys的时间告诉我们哪一个快,按什么顺序。
希望这能帮助你消除疑虑。-)
这里没有明显的东西。因为python是用C语言编写的,所以它必须使用类似于printf的东西来实现print。C++ I/O流,如EDCOX1,5,通常以比EDCOX1,3,更慢的方式实现。如果你想把C++放在一个更好的基础上,你可以尝试改变:
1 2 3 4 5 6 7 8 9 10 11 12
| #include <cstdio>
int main()
{
int x=0;
while(x!=1000000)
{
++x;
std::printf("%d
", x);
}
return 0;
} |
我改为使用++x,而不是x++。几年前,人们认为这是一个有价值的"优化"。如果这种改变对程序的性能有任何影响,我会心脏病发作(Otoh,我肯定使用std::printf会对运行时性能产生巨大影响)。相反,我做这个更改仅仅是因为您在增加它之前没有注意到x的值是什么,所以我认为在代码中这样说很有用。
- 所以你说C++只是比Python慢,因为Python使用最直接的方式来实现打印,差异是由打印的东西引起的吗?隐马尔可夫模型。。。我想我应该不用印刷品就去试试。
- 哦,上帝,谢谢你的帮助…我删除了打印和CUT,Python花费了超过10秒的时间数到10 ^ 8,而C++在闪存中完成了这个任务(不是隐喻或夸张,我的意思是片刻,是的,一个真正的Flash)。所以问题是…现在我学到了一个很好的教训。非常感谢!
- @布苏宣:写控制台总是很慢。您是否尝试将每个程序的输出重定向到一个文件?您的小程序几乎可以肯定是I/O绑定的,写入文件将消除控制台缓慢的写入。
- @ BaskCurn:如果你不输出任何东西,C++编译器可能会删除整个循环。这不能证明cout确实是这里的问题。
我认为我们需要更多的信息,但我希望你正在构建一个未经优化的C++构建。尝试用-O3标志构建它。(了解GCC的人会有越来越多的建议)。然而,这里有一些来自完全不可信来源的时间安排:http://ideone.com。我每跑5次就可以得到一些关于时间的变化,但是只有原始的C++变化,而不是很多。
python:http://ideone.com/wbw9时间:0.07-0.07s您的C++:HTTP://IDENE.COM/TZWQJ时间:0.05-0.06s修改后的C++:HTTP://IDENE.COM/PXJO3时间:0.00秒-0.00秒
至于为什么我的C++比你的C++快,EDCOX1 OR 1强制C++立即刷新缓冲区。'
'在没有强制缓冲区刷新的情况下执行换行,这要快得多。
(注意:我只运行到12773,因为ideone.com在进程显示一定数量的输出后会终止进程,这是服务器提供给我的最多的结果)
- 我用和-o3再试了一次,这次花了1分钟才达到50万。
- 在这种情况下,我只有一个理论。你能打开cmd.exe并在控制台中测试这两个命令吗,以确保控制台不同吗?因为测试的Python和C++都应该是相同的。这是因为在控制台上显示内容需要大量的处理器时间,这两种语言应该是相同的。与之相比,这个循环什么都不是。
- 同样的结果…t.t CPU会影响结果吗?我听说AMD处理器速度更快,而Intel处理器速度较慢,但一次可以处理许多任务
- @不,CPU不应该影响结果。你的Python真的把所有这些数字放在控制台上两倍于C++吗?
- 是的……不知怎么…我觉得Python只能比.NET和Java更快,如果高度优化,但这是难以置信的…运行库是否影响C++?我使用的是最新版本的mingw中的libstdc++。Visual C++库速度更快吗?另外一个奇怪的行为是,使用上面的同一个python程序,我的pypy比cpython慢
- 运行时库不应该有很大的不同,但要尝试一下。你能用"语言编译器控制台类型时间"图表为你的每个测试编辑你的问题吗?
- 哦,我想问题解决了……奇迹般地……我删除了打印和CUT,Python花费了超过10秒的时间数到10 ^ 8,而C++在闪存中完成了这个任务(不是隐喻或夸张,我的意思是片刻,是的,一个真正的Flash)。所以问题是…现在我学到了一个很好的教训。
- @布苏宣:错了。如果你有一个没有输出的循环,C++就什么也不做了。它不算什么。这就是为什么基准很难实现的原因。
- 也可以尝试-march=native
- @moingduck nono,我在循环结束后添加了一个cout,这样程序仍然需要变量x。我没有优化这个变量,因为我希望在没有优化的情况下,这会比python更快。
- @布苏宣:可能还没数,可能只是打印最后一个值。唯一确定的方法是检查组件。
- @moingduck,但它必须先计数到最后一个值,然后才能确定数字是什么,对吗?此外,我没有优化它,所以它不应该跳过任何步骤。
- @布苏宣:你在同样的情况下运行Python吗?我敢打赌它也快疯了。
- @我做过驼鸭,它确实花了更长的时间。我想超过一秒钟
STD::Entl滞后,使用会使C++更快。
- 我也试过,差不多一样(慢了几秒钟,应该是随机差异)
同样的问题,为什么从STDIN中读取线比Python慢得多?但方向相反。
添加
std::cout.sync_with_stdio(false);
到程序的顶端