在C / C ++中有效地从结构化文件中读取数据

我有一个文件如下:

在此处输入图像描述

该文件由两部分组成:标题和数据。

数据部分被分成相同大小的页面。 每个页面都包含特定指标的数据。 可能需要多个页面(不需要连续)来保存单个度量的数据。 每个页面都包含页眉和页面正文。 页眉具有称为“下一页”的字段,该字段是保存同一度量的数据的下一页的索引。 页面正文包含真实数据。 所有页面都具有相同和固定的大小(标题为20个字节,正文为800个字节(如果数据量小于800个字节,则将填充0))。

标题部分由20,000个元素组成,每个元素都有关于特定度量的信息(点1 – >点20000)。 元素具有称为“第一页”的字段,该字段实际上是保存度量数据的第一页的索引。

该文件最大可达10 GB。

要求:在最短的时间内重新排序文件的数据,即,保存单个度量的数据的页面必须是连续的,并且根据字母顺序从度量1到度量20000(标题部分必须相应地更新)。

一种明显的方法:对于每个指标,读取指标的所有数据(逐页),将数据写入新文件。 但这需要很长时间,尤其是从文件中读取数据时。

有没有有效的方法?

一种可能的解决方案是从文件创建索引,其中包含您需要排序的页码和页面度量标准。 将此索引创建为数组,以便第一个条目(索引0 )对应于第一个页面,第二个条目(索引1 )对应于第二个页面等。

然后使用指定的指标对索引进行排序。

排序后,您最终会得到一个包含新的第一个和第二个等条目的新数组,并且您按照排序索引的顺序读取输入文件写入输出文件。

一种明显的方法:对于每个指标,读取指标的所有数据(逐页),将数据写入新文件。 但这需要很长时间,尤其是从文件中读取数据时。

有没有有效的方法?

是。 获得有效的解决方案后,测量其效率,然后确定要优化的部件。 优化的内容和方式在很大程度上取决于您在此获得的结果(您的瓶颈是什么)。

一些要考虑的通用事项:

  • 如果您有一组步骤来读取单个度量的数据并将其移动到输出,您应该能够并行化(具有20组步骤而不是一组)。
  • 无论您运行代码的硬件是什么,10Gb文件都需要一些处理(令人信服的是,您可以在超级计算机上运行它,但我忽略了这种情况)。 您/您的客户可能会接受一个较慢的解决方案,如果它显示它的进度/显示进度条。
  • 不要使用字符串比较进行排序;

编辑(发表评论)

考虑执行如下操作:

  • 为要读取的块创建块偏移列表

  • 创建固定大小的工作线程列表(例如,10个工作者)

  • 每个空闲工作程序将接收文件名和块偏移量,然后在文件上创建一个std :: ifstream实例,读取该块,并将其返回给接收对象(然后,请求另一个块编号,如果有的话) 。

  • 读取页面应传递给管理/存储页面的中央结构。

还要考虑分别管理块的内存(例如,当您知道要读取的块数时,抢占式地分配多个块的块)。

我首先阅读标题部分,然后按字母顺序对指标进行排序。 对于排序列表中的每个度量,我从输入文件中读取所有数据并写入输出文件。 为了消除读取数据步骤中的瓶颈,我使用了内存映射。 结果显示,使用内存映射时,与不使用内存映射时相比,5 GB输入文件的执行时间减少了5~6倍。 这种方式暂时解决了我的问题。 但是,我也会考虑@utnapistim的建议。