【问题标题】:Python faster than C++? How does this happen? [duplicate]Python 比 C++ 快?这是怎么发生的? [复制]
【发布时间】:2012-03-30 02:32:43
【问题描述】:

我正在使用 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分钟达到500,000。

【问题讨论】:

  • 所以根据您的基准,Python 中的无限循环运行速度是在 C++ 中打印单个数字的两倍?这确实很奇怪。
  • 啊,这些代码示例做了完全不同的事情......第一个甚至没有终止。
  • @Mooing Duck:我同意,如果 OP 将示例更改为实际等效,则应该重新打开它。我也认为这可以通过在 C++ 示例中使用 \n 而不是 std::endl 来解决。
  • @busukxuan:您能知道将所有这些额外信息编辑到问题中吗?也许它会重新开放。您应该添加的内容:C++ 编译器、架构、操作系统、Python 实现/版本,尤其是实际终止的代码!把这个问题变成一个有趣的问题,人们就会烦恼。另外,正确格式化 C++ 代码。

标签: c++ python


【解决方案1】:

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

原来的C++代码有两个问题:

  • 它使用std::endl 在每次迭代中打印一个换行符。这是一个非常糟糕的主意,因为std::endl 所做的不仅仅是简单地打印换行符——它还强制流刷新到目前为止积累的缓冲区;刷新是一项昂贵操作,因为它必须处理硬件——输出设备。所以第一个解决方法是:如果要打印换行符,只需使用'\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 时间告诉我们哪个快,以及按什么顺序

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

【讨论】:

    【解决方案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 在您增加它之前的值是什么,所以我认为在代码中这样说很有用。

    【讨论】:

    • 所以你是说c++只比python慢​​,因为python是用最直接的方式来实现打印的,而差异是由打印的东西引起的?嗯...我想我应该不带印刷品去试试。
    • 天哪,感谢您的帮助....我删除了 print 和 cout,python 花了 10 多秒才数到 10^8,而 C++ 在一瞬间完成了(不是比喻或夸张,我的意思是几分之一秒,是的,真正的闪光)。所以问题出在 cout... 现在我学到了一个很好的教训。非常感谢!
    • @busukxuan:写入控制台总是很慢。您是否尝试过将每个程序的输出重定向到文件?您的小程序几乎肯定是 I/O 绑定的,写入文件将消除缓慢的控制台写入。
    • @bosukxuan:如果你不输出任何东西,C++ 编译器可能会删除整个循环......这并不能证明cout 确实是这里的问题。
    【解决方案3】:

    我认为我们需要更多信息,但我希望您正在构建一个未优化的 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 在显示一定数量的输出后会杀死进程,这是服务器给我的最多)

    【讨论】:

    • 我又试了一次,用\n和-O3,这次花了​​1分钟达到500,000
    • 那样的话,我只有一个理论。你能打开 cmd.exe 并在 that 控制台中测试它们,以确保它不是不同的控制台吗?因为对于您的测试,Python 和 C++ 的时间应该几乎相同。这是因为在控制台上显示内容需要 很多 的处理器时间,这对于两种语言来说应该是相同的。与此相比,循环算不了什么。
    • 还是一样的结果...T.T CPU会影响结果吗?我听说 AMD 处理器要快得多,而 Intel 处理器速度较慢,但​​一次可以处理许多任务
    • @busukxuan:不,CPU 不应该影响结果。你的 python 真的把所有这些数字放在控制台中的速度是 C++ 的两倍吗?
    • @busukxuan:错了。如果你有一个没有输出的循环,C++ 将什么都不做。它不算任何东西。这就是基准测试很难的原因。
    【解决方案4】:

    std::endl 滞后,使用 '\n' 将使 c++ 更快。

    【讨论】:

    • 我试过了,差不多(慢了几秒,应该是随机差异)
    【解决方案5】:

    Why is reading lines from stdin much slower in C++ than Python? 中提出的问题相同,但方向相反。

    添加

    std::cout.sync_with_stdio(false);

    到程序顶部

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-13
      • 2017-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多