如何优化C++中的输入输出

如何优化C++中的输入输出,c++,performance,C++,Performance,我正在解决一个需要快速输入/输出的问题。更准确地说,输入数据文件将达到15MB。是否有一种快速的方法来读取/打印整数值 注意:我不知道它是否有用,但输入文件的格式如下: 第1行:数字n 第2行..n+1:三个数字a、b、c; 第n+2行:数字r 第n+3..n+4+r行:四个数字a、b、c、d 注2:输入文件将为标准格式 编辑:以下内容不够快: void fast_scan(int &n) { char buffer[10]; gets(buffer); n=atoi(buf

我正在解决一个需要快速输入/输出的问题。更准确地说,输入数据文件将达到15MB。是否有一种快速的方法来读取/打印整数值

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

第1行:数字n 第2行..n+1:三个数字a、b、c; 第n+2行:数字r 第n+3..n+4+r行:四个数字a、b、c、d 注2:输入文件将为标准格式

编辑:以下内容不够快:

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]);
}

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

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

使用上述原理将设备中的所有数据读入某个缓冲区 将生成结果数据的数据处理到某个缓冲区或另一个缓冲区 使用上述原理从缓冲器到设备的输出结果
例如,你可以使用大数据块来输入数据,而不是一行一行地输入。与输出类似的想法是,通过手动添加换行符生成单个字符串,然后立即输出。

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

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

使用上述原理将设备中的所有数据读入某个缓冲区 将生成结果数据的数据处理到某个缓冲区或另一个缓冲区 使用上述原理从缓冲器到设备的输出结果
例如,你可以使用大数据块来输入数据,而不是一行一行地输入。与输出类似的想法是,手动添加换行符后生成单个字符串,并立即输出。

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

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

如果希望最小化物理I/O操作开销,请使用一种称为的技术将整个文件加载到内存中。不过,我怀疑您是否会获得明显的性能提升。解析很可能成本更高。

如果您想将物理I/O操作开销降至最低,请使用一种称为的技术将整个文件加载到内存中。不过,我怀疑您是否会获得明显的性能提升。解析很可能成本更高。

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

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


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

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

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

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

它只有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非常快,就像固态驱动器一样,才有意义。

只有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真的很快,就像之前的固态驱动器一样,这是有意义的。

如果你不关心良好的编码实践,并且你正在编写程序以达到在线判断的最高水平,那么就编写你自己的方法来解析输入和写输出。通常情况下,算法比输入/输出优化更重要。@nhahdh是的,但我将如何编写它?它只有4-5行代码,请自己编写。将输入读入一些缓冲区fread/fgets,然后将字符串解析为数字。您尝试过什么吗?我鼓励您尝试使用您所知道的解决方案,然后如果速度不够快,或者您正在为某个特定零件而挣扎,请回来寻求帮助。状态机跟踪您在读取n-def-line、n-lines after、r-def-line、r-lines after的每个阶段中所处的位置,对于您在本问题中提出的条件来说几乎是微不足道的。关于如何编写,我想到了trying这个词,紧接着是text editor。如果你不关心良好的编码实践,并且你正在编写程序以达到在线评判的最高水平,那么就编写你自己的方法来解析输入并编写输出。通常情况下,算法比输入/输出优化更重要。@nhahdh是的,但我将如何编写它?它只有4-5行代码,请自己编写。将输入读入一些缓冲区fread/fgets,然后将字符串解析为数字。您尝试过什么吗?我鼓励您尝试使用您所知道的解决方案,然后如果速度不够快,或者您正在为某个特定零件而挣扎,请回来寻求帮助。状态机跟踪您在读取n-def-line、n-lines after、r-def-line、r-lines after的每个阶段中所处的位置,对于您在本问题中提出的条件来说几乎是微不足道的。关于如何编写它,我想到了“尝试”这个词,紧接着是“文本编辑器”。他使用的是stdio,它也是缓冲的,所以磁盘访问应该最小化。很好,但我想知道是否有更快的方法。@Barmar在任何情况下,任何I/O函数调用都有开销,应该最小化。他使用的是stdio,这也是缓冲的,所以应该尽量减少磁盘访问。不错,但我想知道是否有更快的方法。@Barmar在任何情况下,任何I/O函数调用都有开销,应该尽量减少。这听起来很有趣;你知道有什么简单的preferablyc++实现吗?事实上,与物理I/O相比,我希望解析几乎是免费的;你知道有什么简单的preferablyc++实现吗?实际上,与物理I/O相比,我希望解析几乎是免费的。