Python比C++快吗?这是怎么发生的?

Python faster than C++? How does this happen?

本问题已经有最佳答案,请猛点这里访问。

我使用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++代码快,然后把这个主题作为一个例子来证明他的观点。现在从其他答案显而易见的是,问题是什么错误的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

usersys的时间告诉我们哪一个快,按什么顺序。

希望这能帮助你消除疑虑。-)


这里没有明显的东西。因为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++构建。尝试用-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在进程显示一定数量的输出后会终止进程,这是服务器提供给我的最多的结果)


STD::Entl滞后,使用会使C++更快。


同样的问题,为什么从STDIN中读取线比Python慢得多?但方向相反。

添加

std::cout.sync_with_stdio(false);

到程序的顶端