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

新手上路,请多包涵

我正在使用 Windows7,将 CPython 用于 python3.22,将 MinGW 的 g++.exe 用于 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 超过了 c++ 并且速度超过了两倍。 Python 用了 53 秒,c++ 用了 1 分 54 秒。

是因为 python 对解释器做了一些特殊的优化,还是因为 C++ 必须引用和 std ,这会减慢它的速度并使其占用内存?

或者是其他什么原因?

编辑: 我再次尝试,使用 \n 而不是 std::endl ,并使用 -O3 标志进行编译,这一次花了 1 分钟到达 0000。

原文由 busukxuan 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 413
2 个回答

这里没有什么明显的。由于 Python 是用 C 编写的,它必须使用类似 printf 的东西来实现 print 。 C++ I/O 流,如 cout ,通常以比 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 在您增加它之前的值,所以我认为在代码中这样说很有用。

原文由 Max Lybbert 发布,翻译遵循 CC BY-SA 3.0 许可协议

我的一位同事告诉我 Python 代码比 C++ 代码更快,然后将这个主题作为一个例子来证明他的观点。现在从其他答案中可以明显看出问题中发布的 C++ 代码有什么问题。我仍然想总结一下我所做的基准测试,以向他展示一个好的 C++ 代码可以有多 _快_!

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

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

  • 第二个问题不太明显,因为它没有在代码中 _看到_。它在 C++ 流的设计中。默认情况下,C++ 流在每次输入和输出操作后同步到 C 流,以便您的应用程序可以混合使用 std::coutstd::printf std::scanf std::cin --- 没有任何问题。在这种情况下不需要这个特性(是的,它是一个 _特性_),所以我们可以禁用它,因为它有一点运行时开销(这不是 _问题_;它不会让 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 时间告诉我们哪个快, 按什么顺序

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

原文由 Nawaz 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题