c++ - 缓冲输入与标准输入

标签 c++ io buffer

我试图从输入文件中读取一长串数字(大约 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;
}

最佳答案

第二个将需要内存中文件大小的 ~2 倍,否则,由于它在一次调用中读取整个文件,它可能会以底层存储可以提供的速度将数据读入内存,然后将其处理为与 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 >> 发出一个读取调用,而第三个程序可以缓冲(不时发出一个读取调用)。

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

关于c++ - 缓冲输入与标准输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24927459/

相关文章:

node.js - 如何使用 Node.js 创建带缓冲区的读取流

cocoa-touch - Cocoa Touch Bonjour如何处理NSNetService地址和uint8_t

c++ - 在 Windows 控制台应用程序中输出 unicode 字符串

c++ - Ubuntu Linux 的编译问题

c++ - Monodevelop C++ 调试问题

io - 中止来自另一个 goroutine 的 Read() 调用

java - 为什么我会在文件关闭时关心 IOExceptions?

c - 如何利用对 updateConfigParams() 函数的缓冲区溢出攻击来禁用该程序?

c++ - 在抛出 'std::length_error' what(): basic_string::_S_create 实例后终止调用

java - 如何在并行端口上打开/关闭数据引脚?