我使用的是Windows 7,使用CPython for python3.22和MinGW的g ++。exe for C ++(这意味着我使用libstdc ++作为运行时库)。我写了两个简单的程序来比较它们的速度。
的Python:
x=0
while x!=1000000:
x+=1
print(x)
C ++:
#include <iostream>
int main()
{
int x = 0;
while ( x != 1000000 )
{
x++;
std::cout << x << std::endl;
}
return 0;
}
两者都没有优化。
我首先运行c ++,然后通过交互式命令行运行python,这比直接启动.py文件慢得多。
但是,python outran c ++的速度是原来的两倍多。 Python花了53秒,c ++花了1分54秒。
是因为python对解释器进行了一些特殊的优化,还是因为C ++必须引用和std会降低它并使其占用ram?
还是其他原因?
修改:我再次尝试使用\n
代替std::endl
,并使用-O3
标记进行编译,这次耗时1分钟达到500,000
答案 0 :(得分:29)
我的一位同事告诉我,Python代码比C ++代码更快,然后以此主题为例来证明他的观点。从其他答案中可以明显看出问题中发布的C ++代码有什么问题。我仍然想总结一下我的基准,以便向他展示 fast 一个好的C ++代码是什么样的!
原始C ++代码存在两个问题:
它使用std::endl
在每次迭代中打印换行符。这是一个非常糟糕的主意,因为std::endl
比简单地打印换行更多的东西 - 它还强制流 flush 到目前为止累积的缓冲区;刷新是一项昂贵的操作,因为它必须处理硬件 - 输出设备。所以第一个解决方法是:如果要打印换行符,只需使用'\n'
即可。
第二个问题不太明显,因为代码中没有看到。它是在C ++流的设计中。默认情况下,在每次输入和输出操作之后,C ++流将同步到C流,以便您的应用程序可以混合std::cout
和std::printf
以及std::cin
和std::scanf
而不会出现任何问题。在这种情况下不需要此功能(是的,它是功能),所以我们可以禁用它,因为它有一点运行时开销(这不是问题;它不会使C ++变坏;它只是功能的价格。所以第二个问题就是:std::cout::sync_with_stdio(false);
这是最终的优化代码:
#include <iostream>
int main()
{
std::ios_base::sync_with_stdio(false);
int x = 0;
while ( x != 1000000 )
{
++x;
std::cout << x << '\n';
}
}
使用-O3
标记进行编译并运行(和度量):
$ g++ benchmark.cpp -O3 #compilation
$ time ./a.out #run
//..
real 0m32.175s
user 0m0.088s
sys 0m0.396s
运行并测量python代码(发布在问题中):
$ time ./benchmark.py
//...
real 0m35.714s
user 0m3.048s
sys 0m4.456s
user
和sys
时间告诉我们哪一个是快速的,按什么顺序。
希望能帮助您消除疑虑。 : - )
答案 1 :(得分:15)
这里没有任何明显的东西。由于Python是用C语言编写的,因此它必须使用printf
之类的东西来实现print
。像cout
这样的C ++ I / O流通常以比printf
慢得多的方式实现。如果你想让C ++处于更好的基础,你可以尝试改为:
#include <cstdio>
int main()
{
int x=0;
while(x!=1000000)
{
++x;
std::printf("%d\n", x);
}
return 0;
}
我确实更改为使用++x
而不是x++
。多年前人们认为这是一次有价值的“优化”。如果这个改变对你的程序性能产生任何影响,我会心脏病发作(OTOH,我很肯定使用std::printf
会对运行时性能产生巨大影响)。相反,我之所以做出改变只是因为你没有注意到x
的价值增加之前是什么,所以我觉得在代码中说这很有用。
答案 2 :(得分:11)
我认为我们需要更多信息,但我希望您构建一个未经优化的C ++版本。尝试使用-O3
标志构建它。 (更了解GCC的人会有更多更好的建议)。但是,这里有一些完全不值得信任的来源:http://ideone.com。我每次跑5次以获得一些时间上的变化,但只有原始的C ++变化,并没有那么多。
Python:http://ideone.com/WBWB9时间:0.07-0.07s
你的C ++:http://ideone.com/tzwQJ时间:0.05-0.06s
修改后的C ++:http://ideone.com/pXJo3时间:0.00s-0.00s
至于为什么我的C ++比你的快,std::endl
强制 C ++立即刷新缓冲区。 '\n'
在没有强制缓冲区刷新的情况下执行换行,这非常快 。
(注意:我只跑到12773,因为ideone.com在显示一定数量的输出后杀死进程,这是服务器给我的最多)
答案 3 :(得分:6)
std :: endl滞后,使用'\ n'会使c ++更快。
答案 4 :(得分:3)
与Why is reading lines from stdin much slower in C++ than Python?中提出的问题相同,但方向相反。
添加
std::cout.sync_with_stdio(false);
到程序的顶部