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

时间:2012-03-13 16:43:58

标签: c++ python

我使用的是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

5 个答案:

答案 0 :(得分:29)

我的一位同事告诉我,Python代码比C ++代码更快,然后以此主题为例来证明他的观点。从其他答案中可以明显看出问题中发布的C ++代码有什么问题。我仍然想总结一下我的基准,以便向他展示 fast 一个好的C ++代码是什么样的!

原始C ++代码存在两个问题:

  • 它使用std::endl在每次迭代中打印换行符。这是一个非常糟糕的主意,因为std::endl比简单地打印换行更多的东西 - 它还强制流 flush 到目前为止累积的缓冲区;刷新是一项昂贵的操作,因为它必须处理硬件 - 输出设备。所以第一个解决方法是:如果要打印换行符,只需使用'\n'即可。

  • 第二个问题不太明显,因为代码中没有看到。它是在C ++流的设计中。默认情况下,在每次输入和输出操作之后,C ++流将同步到C流,以便您的应用程序可以混合std::coutstd::printf以及std::cinstd::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

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

希望能帮助您消除疑虑。 : - )

答案 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);

到程序的顶部