如何在C ++中优化输入/输出

时间:2012-10-25 17:21:59

标签: c++ performance

我解决了需要非常快速输入/输出的问题。更确切地说,输入数据文件将高达15MB。有没有一种快速的方法来读取/打印整数值。

注意:我不知道它是否有帮助,但输入文件的格式如下:

  • 第1行:数字n
  • 第2..n + 1行:三个数字a,b,c;
  • 第n + 2行:数字r
  • 行n + 3..n + 4 + r:四个数字a,b,c,d

注2:输入文件为stdin

编辑:以下内容不够快:

void fast_scan(int &n) {
  char buffer[10];
  gets(buffer);
  n=atoi(buffer);
}

void fast_scan_three(int &a,int &b,int &c) {
  char buffval[3][20],buffer[60];
  gets(buffer);
  int n=strlen(buffer);
  int buffindex=0, curindex=0;
  for(int i=0; i<n; ++i) {
    if(!isdigit(buffer[i]) && !isspace(buffer[i]))break;
    if(isspace(buffer[i])) {
      buffindex++;
      curindex=0;
    } else {
      buffval[buffindex][curindex++]=buffer[i];
    }
  }
  a=atoi(buffval[0]);
  b=atoi(buffval[1]);
  c=atoi(buffval[2]);
}

5 个答案:

答案 0 :(得分:3)

通用输入/输出优化原则执行尽可能少的I / O操作读取/写入尽可能多的数据

因此,性能感知解决方案通常如下所示:

  1. 将设备中的所有数据读入某个缓冲区(使用上述原理)
  2. 将生成结果数据的数据处理到某个缓冲区(在某处或另一个缓冲区)
  3. 从缓冲区到设备的输出结果(使用上述原理)
  4. E.g。您可以使用std::basic_istream::read按大块输入数据,而不是逐行进行。与输出类似的想法 - 生成单个字符串作为结果手动添加换行符号并立即输出。

答案 1 :(得分:1)

如果要最小化物理I / O操作开销,请通过名为memory mapped files的技术将整个文件加载到内存中。我怀疑你会获得明显的性能提升。解析很可能会花费更多。

答案 2 :(得分:0)

将几个输入行放在缓冲区中,拆分它们,然后在不同的线程中同时解析它们。

答案 3 :(得分:0)

考虑使用线程。线程对很多事情很有用,但这正是推动线程发明的问题。

基本思想是分离输入,处理和输出,以便这些不同的操作可以并行运行。做得对,你会看到显着的加速。

让一个线程接近纯输入。它将行读入行缓冲区。让第二个线程快速进行预解析并将原始输入组织成块。您有两件事需要解析,包含包含三元组的行数的行以及包含包含四元组的行数的行。此线程将原始输入形成块,这些块仍然主要是文本。第三个线程解析三元组和四元组,将输入重新形成为完全解析的结构。由于数据现在被组织成独立的块,因此您可以拥有此第三个操作的多个实例,以便更好地利用计算机上的多个处理器。最后,其他线程将在这些完全解析的结构上运行。注意:组合其中一些操作可能更好,例如将输入和预解析操作组合到一个线程中。

答案 4 :(得分:0)

它只有15MB。我只是将整个事物啜饮到内存缓冲区,然后解析它。 解析看起来像这样,大约:

#define DIGIT(c)((c) >= '0' && (c) <= '9')
while(*p == ' ') p++;
if (DIGIT(*p)){
    a = 0;
    while(DIGIT(*p){
        a *= 10; a += (*p++ - '0');
    }
}
// and so on...

你应该能够在睡梦中写下这种代码。

我不知道这是否比atoi更快,但它并不是在弄清楚数字的开始和结束位置。我会远离scanf,因为它经过九码计算出它的格式字符串。

如果你在一个循环中运行这整件1000次并获取一些堆栈样本,你应该看到它花费了近100%的时间读取文件并生成输出(你没有提到)。 你无法击败那个。 如果您确实看到在实际解析中花费了大量时间,则可能会执行重叠I / O,但是机器必须非常慢,或者I / O非常快(例如来自固态驱动器)在此之前是有意义的。