当输入量很大时,常规的有竞争力的程序员面临着共同的挑战,从stdin读取这样的输入可能会成为一个瓶颈。这种问题伴随着“警告:大量I/O数据”。
让我们创建一个虚拟输入文件,其中包含一个16字节的行,后跟一个换行符,有1000000行这样的行,制作一个17MB的文件就足够了。
// Creating a dummy file of size 17 MB to compare // performance of scanf() and cin() $ yes 1111111111111111 | head -1000000 > tmp/dummy
让我们比较一下使用scanf()和cin从stdin读取文件所需的时间(使用重定向将文件从磁盘读取到stdin)。
// Filename : cin_test.cc to test the // We redirect above created temp file // of 17 MB to stdin when this program // is run. #include<iostream> using namespace std; int main() { char buffer[256]; while (cin >> buffer) { } return 0; } |
当虚拟文件被重定向到stdin时,上述程序的输出。
$ g++ cin_test.cc –o cin_test $ time ./cin_test < /tmp/dummy real 0m2.162s user 0m1.696s sys 0m0.332s
// Filename : scanf_test.c to see // performance of scanf() // We redirect above created temp file // of 17 MB to stdin when this program // is run. #include<cstdlib> #include<cstdio> int main() { char buffer[256]; while ( scanf ( "%s" , buffer) != EOF) { } return 0; } |
当虚拟文件被重定向到stdin时,上述程序的输出。
$ g++ scanf_test.cc –o scanf_test $ time ./scanf_test < /tmp/dummy real 0m0.426s user 0m0.248s sys 0m0.084s
以上结果与我们的观察结果一致。
为什么scanf比cin更快? 从更高的层面来看,它们都是包装纸 读() 系统调用,只是语法糖。唯一明显的区别是 scanf() 必须显式声明输入类型,而 cin 使用模板重载重定向操作。这似乎不足以成为性能达到5倍的理由。
事实证明 流 利用 斯特迪奥 的缓冲系统。所以 cin 浪费时间与底层C库的同步 斯特迪奥 缓冲区,以便调用 scanf() 和 cin 可以交错。
好消息是libstdc++提供了一个选项来关闭所有数据的同步 流 标准流及其相应的标准C流使用
std::ios::sync_with_stdio(false);
和 cin 变得比 scanf() 本来应该如此。
一篇关于 竞争性编程中的快速输入输出
// Filename : cin_test_2.cc to see // performance of cin() with stdio syc // disabled using sync_with_stdio(false). #include<iostream> using namespace std; int main() { char buffer[256]; ios_base::sync_with_stdio( false ); while (cin >> buffer) { } return 0; } |
运行程序:
$ g++ cin_test_2.cc –o cin_test_2 $ time./cin_test_2 </tmp/dummy real 0m0.380s user 0m0.240s sys 0m0.028s
- 就像所有事情一样,这里有一个警告。在关闭同步的情况下,使用 cin 和 scanf() 一起将导致一个未定义的混乱。
- 关闭同步后,上述结果表明 cin 比之前快8-10% scanf() .这可能是因为 scanf() 在运行时解释格式参数,并使用可变数量的参数,而 cin 在编译时执行此操作。
现在想知道,这能以多快的速度完成?
// Redirecting contents of dummy file to null // device (a special device that discards the // information written to it) using command line. $time cat /tmp/dummy > /dev/null real 0m0.185s user 0m0.000s sys 0m0.092s
哇!这太快了!!!
本文由 阿尤什·戈维尔 .如果你喜欢GeekSforgek,并且想贡献自己的力量,你也可以写一篇文章,并将文章邮寄到contribute@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。 如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写评论