【问题标题】:Buffered input versus standard input缓冲输入与标准输入
【发布时间】:2014-07-24 07:23:54
【问题描述】:

我试图从输入文件中读取一长串数字(大约 10^7)。通过一些搜索,我发现使用缓冲区读取内容与逐个读取数字相比具有更高的性能。

我的第二个程序比第一个程序执行得更好。我在第一个程序中使用 cin 流对象,在第二个程序中使用 stringstream 对象。这两者在 I/O 性能方面有什么区别?

#include <iostream>
using namespace std;

int main()
{
    int n,k;
    cin >> n >> k;
    int count = 0;
    while ( n-- > 0 )
    {
        int num;
        cin >> num;
        if( num % k == 0 )
            count++;
    }
    cout << count << endl;
    return 0;
}

与以下使用缓冲输入的代码相比,此程序需要更长的时间。

#include <iostream>
#include <sstream>
using namespace std;

int main()
{
    cin.seekg(0, cin.end);
    int length = cin.tellg();
    cin.seekg(0, cin.beg);
    char *buffer = new char[length];
    cin.read(buffer,length);
    stringstream ss(buffer);
    int n,k;
    ss >> n >> k;
    int result = 0;
    while( n-- )
    {
        int num;
        ss >> num;
        if( num % k == 0 )
            result++;
    }
    cout << result << endl;
    return 0;
}

【问题讨论】:

  • 你知道cin 缓冲了吗?而且cin(作为一个文件)有一个不确定的大小(所以寻找到最后是行不通的,因为没有真正的结束)。
  • 我试图从文件 program.exe
  • 输入来自哪里并不重要,cin 不是文件流,所以你不能真正改变位置。一旦从cin 读取输入,您就不能倒带查看历史,也不能快进到未来。不要将cin 视为文件,因为它不是。 std::cin 不能用于随机访问读取,即使您从重定向文件获取输入。
  • 那么从键盘读取大量数字的最佳方法是什么?
  • @JoachimPileborg cin 实际上是 a little special about buffering

标签: c++ io buffer


【解决方案1】:

第二个将需要〜两倍的文件大小在内存中,否则,由于它在一次调用中读取整个文件,它可能会以底层存储可以提供的速度将数据读入内存,然后将其处理为CPU 能做到的那样快。

最好避免内存成本,在这方面,您的第一个程序会更好。在我的系统上,使用名为 test.txt 的输入,如下所示:

10000000 2
13
13
< 10000000-2 more "13"s. >

你的第一个程序叫做a,你的第二个程序叫做b。我明白了:

% time ./a <test.txt 
0
./a < test.txt  1.70s user 0.01s system 99% cpu 1.709 total
% time ./b <test.txt
0
./b < test.txt  0.76s user 0.04s system 100% cpu 0.806 total

cin 默认情况下不缓冲,以保持与stdio 的“同步”。请参阅this excellent answer 以获得很好的解释。为了让它缓冲,我在你的第一个程序的顶部添加了cin.sync_with_stdio(false),并调用了结果c,它的运行速度可能会稍微快一些:

% time ./c <test.txt
0
./c < test.txt  0.72s user 0.01s system 100% cpu 0.722 total

(注意:时间有点乱,我只进行了一些测试,但c 似乎至少和b 一样快。)

您的第二个程序运行得很快,因为虽然没有缓冲,但我们可以发出一个读取调用。第一个程序必须为每个cin &gt;&gt; 发出一个读取调用,而第三个程序可以缓冲(不时发出一个读取调用)。

请注意,添加此行意味着您无法使用 C FILE * 读取 stdin 的名称,或调用任何可以这样做的库方法。实际上,这可能不是问题。

【讨论】:

  • 谢谢。您的链接通过使用 cin.sync_with_stdio(false); 帮助我了解了性能;
猜你喜欢
  • 2014-12-07
  • 2011-05-18
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 2012-05-02
  • 1970-01-01
相关资源
最近更新 更多