跳至主要內容

老生常谈:printf真的比std::cout快吗?

A1exlindev大约 2 分钟计算机

实验结果

实践是检验真理的唯一标准。

在程序设计竞赛等情况下,我们常常需要通过标准输入输出流交换大量的数据。然而,在传统OI培训当中,我们常常会接受到这样一个观点

要用printf,std::cout会太慢导致超时

笔者在wsl2环境下,利用谷歌开源的Google Benchmark框架进行了一次测试,被测试的函数包括:

  • 默认情况下的std::cout,且使用std::endl进行换行
  • 默认情况下的std::cout,使用\n作为换行
  • 关闭标准流同步,使用\n作为换行的std::cout
  • 关闭标准流同步,但使用std::endl作为换行的std::cout
  • 传统香烟printf
  • 笔者自行实现的所谓OI快写

被输出的数据是根据一定规则生成的约10610^6规模的整数数组,每个函数运行三十次取平均值。测试结果如下(按时间从快到慢排序)

Benchmark Result
Benchmark Result

一些讨论

测试结果相当戏剧性。

先说结论,关闭流同步,使用传统换行的cout最快。甚至比笔者自行实现的基于putchar()的简单输出函数要快。同时,我们可以观察出几个现象。

使用endl换行的输出方法比其它几种方法慢了夸张的两个数量级。在程序设计竞赛中,常数多两个零的代价显然是不可接受的。造成这个现象的其中一个原因是,每次输出std::endl时,都会调用一次std::cout.flush(),即刷新一次缓冲区。这会导致可观的性能损失。

虽然printf()是C语言标准库中的传统函数,但是它的表现略微落后于cout. 这可能是由于cout在编译期就能确定输出格式化的类型,而printf在运行时确定格式化的类型。

关于效率问题的更底层讨论,限于笔者的水平,还有待进一步的学习。

后面的代码,以后再来探索吧(

上次编辑于:
贡献者: Alexlin625