这是C++中最快的输入方法
Which is the fastest method of input in C++
我正在为各种奥运会编程,并努力提高时间效率。我正在寻找获得输入的最快方法,使用没有任何外部库的gcc编译器。
我以前使用过cin和cout,但发现scanf和printf要快得多。还有更快的方法吗?我不太在乎空间的复杂性,我更喜欢更好的时间。
流总是比C-API函数慢是一个非常常见的误解,因为默认情况下,它们与C层同步。所以,是的,这是一个功能,而不是一个bug。
在不牺牲类型安全性(和可读性,取决于您的口味)的情况下,您可以通过使用获得流的性能
std::ios_base::sync_with_stdio (false);
一个小指标:
#include <cstdio>
#include <iostream>
template <typename Test>
void test (Test t)
{
const clock_t begin = clock();
t();
const clock_t end = clock();
std::cout << (end-begin)/double(CLOCKS_PER_SEC) << " secn";
}
void std_io() {
std::string line;
unsigned dependency_var = 0;
while (!feof (stdin)) {
int c;
line.clear();
while (EOF != (c = fgetc(stdin)) && c!='n')
line.push_back (c);
dependency_var += line.size();
}
std::cout << dependency_var << 'n';
}
void synced() {
std::ios_base::sync_with_stdio (true);
std::string line;
unsigned dependency_var = 0;
while (getline (std::cin, line)) {
dependency_var += line.size();
}
std::cout << dependency_var << 'n';
}
void unsynced() {
std::ios_base::sync_with_stdio (false);
std::string line;
unsigned dependency_var = 0;
while (getline (std::cin, line)) {
dependency_var += line.size();
}
std::cout << dependency_var << 'n';
}
void usage() { std::cout << "one of (synced|unsynced|stdio), plsn"; }
int main (int argc, char *argv[]) {
if (argc < 2) { usage(); return 1; }
if (std::string(argv[1]) == "synced") test (synced);
else if (std::string(argv[1]) == "unsynced") test (unsynced);
else if (std::string(argv[1]) == "stdio") test (std_io);
else { usage(); return 1; }
return 0;
}
使用g++-O3和一个大的文本文件:
cat testfile | ./a.out stdio
...
0.34 sec
cat testfile | ./a.out synced
...
1.31 sec
cat testfile | ./a.out unsynced
...
0.08 sec
这将如何适用于您的案例取决于情况。修改这个玩具基准,添加更多的测试,并比较例如std::cin >> a >> b >> c
和scanf ("%d %d %d", &a, &b, &c);
之类的东西。我保证,通过优化(即不处于调试模式),性能差异将是微妙的。
如果这还没有让你的需求饱和,你可以尝试其他方法,例如先读取整个文件(可能会也可能不会带来更高的性能)或内存映射(这是一个不可移植的解决方案,但大型台式机也有)。
更新
格式化输入:扫描与流
#include <cstdio>
#include <iostream>
template <typename Test>
void test (Test t)
{
const clock_t begin = clock();
t();
const clock_t end = clock();
std::cout << (end-begin)/double(CLOCKS_PER_SEC) << " secn";
}
void scanf_() {
char x,y,c;
unsigned dependency_var = 0;
while (!feof (stdin)) {
scanf ("%c%c%c", &x, &y, &c);
dependency_var += x + y + c;
}
std::cout << dependency_var << 'n';
}
void unsynced() {
std::ios_base::sync_with_stdio (false);
char x,y,c;
unsigned dependency_var = 0;
while (std::cin) {
std::cin >> x >> y >> c;
dependency_var += x + y + c;
}
std::cout << dependency_var << 'n';
}
void usage() { std::cout << "one of (scanf|unsynced), plsn"; }
int main (int argc, char *argv[]) {
if (argc < 2) { usage(); return 1; }
if (std::string(argv[1]) == "scanf") test (scanf_);
else if (std::string(argv[1]) == "unsynced") test (unsynced);
else { usage(); return 1; }
return 0;
}
结果:
scanf: 0.63 sec
unsynced stream: 0.41
通常,缓冲输入将是最快的。刷新输入缓冲区的频率越低,输入就越快。要了解完整且内容丰富的讨论,请参阅此问题。简而言之,具有大缓冲区大小的read()是最快的,因为它几乎直接位于操作系统中相应的系统调用之上。
可能scanf比使用流要快一些。尽管流提供了很多类型安全性,并且不必在运行时解析格式字符串,但它通常具有不需要过多内存分配的优点(这取决于编译器和运行时)。也就是说,除非性能是你唯一的最终目标,并且你正处于关键的道路上,否则你真的应该支持更安全(更慢)的方法。
Herb Sutter 在这里写了一篇非常美味的文章
http://www.gotw.ca/publications/mill19.htm
谁详细介绍了像sscanf和lexicalcast这样的字符串格式化程序的性能,以及是什么原因导致它们运行缓慢或快速。这有点类似,可能与C风格IO和C++风格之间影响性能的事情类似。与格式化程序的主要区别往往是类型安全性和内存分配的数量。
- 当可输入框在窗口中处于活动状态时获得通知的任何方法
- 仅通过C++中数组初始化的不同方法,即可在同一输入上获得两个不同的答案
- C++ - 有什么方法可以将输入插入缓冲区/停止 cin.忽略需要输入?
- 有没有更好的方法可以让我接收这些输入?C++
- 将函数更改为具有设置函数输入变量的方法的类
- 输入可变大小矢量的正确方法
- 有没有一种方法可以接受数字数组而不接受垃圾值的输入
- isdigit() 和 isalnum() 给出错误,因为输入是一个常量字符并且无法转换。其他可能查看输入是否为数字的方法?
- 将用户输入绑定到UE4.22.3及更高版本中的UActorComponent方法
- 将整数输入数组的方法比 scanf() 或 cin 更快?
- QuickSort方法仅使用单个向量作为C 中的输入参数
- 检查字符串是否与可能的输入之一匹配的最有效方法是什么?
- 是否有一种方法可以避免标头文件中使用的constexpr函数输入全局范围,而无需额外的名称空间
- 从文件循环输入的更合适方法?
- 是否有任何方法可以在用户输入文本时读取字符
- 在 C++ 中解析 main 函数的大量输入的正确方法是什么
- 总结数字字符串输入的最佳方法
- C++简单的暴力项目密码输入方法
- C/C++ 中数字的快速输入方法
- 这是C++中最快的输入方法