我希望为C ++模拟应用程序优化读/写大数据。被称为“地图”的数据基本上由整数,双精度,浮点数和单个枚举组成。大部分地图数据的大小是固定的,但其中一小部分可能会有所不同 (从几个到几KB)的大小。几个这样的映射(通常是数百万)在应用程序开始时计算一次,然后存储在单个二进制文件中,以便在每个模拟时间步骤进行解析。
由于有几百万张地图,因为fseek和fread是主要的瓶颈,解析这个二进制文件的速度非常慢。我正在寻找另一种方法来做同样的事情。
任何指针?
答案 0 :(得分:10)
由于您没有提及正在运行此操作系统的操作系统,您是否已查看映射文件的内存,然后使用标准内存例程在您继续操作时“遍历”文件?
这样你就不会使用fseek / fread,而是使用指针算法。 Here is an mmap example将一个文件从源文件复制到目标文件。这可能会提高性能。
您可以查看的其他内容是将文件拆分为较小的文件,并使用与时间单位对应的哈希值关闭然后打开下一个文件以继续模拟,这样处理较小的文件即可主机操作系统更积极地缓存!
答案 1 :(得分:3)
您可以考虑使用内存映射文件。例如,请参阅boost::interprocess,因为它们提供了方便的实现。
另外,您可以考虑使用stlxxl来提供类似STL的功能,以实现针对大型基于文件的数据集。
还有一个 - 如果你想要迭代器来访问你的数据,那么看看boost::iterator_facade。
如果你不想玩花哨的技巧,你可以提供额外的二进制文件,其中包含带结构的文件的索引(包含结构起始偏移的偏移量)。这将提供间接随机访问。
答案 2 :(得分:3)
这种想法的有效性取决于您的访问模式,但如果您不在每个周期查看可变大小的数据,则可以通过重新安排文件结构来加快访问速度:
而不是直接转储这样的结构:
struct {
int x;
enum t;
int sz
char variable_data[sz];
};
你可以预先写下所有固定大小的部分,然后再存储变量部分:
struct {
int x;
enum t;
int sz;
long offset_to_variable_data;
};
现在,在每个周期解析文件时,您可以一次线性读取N条记录。当您需要获取可变大小的数据时,您只需要处理fseek。您甚至可以考虑将该变量部分保存在单独的文件中,这样您也只能读取该文件。
如果你像其他人建议的那样使用内存映射文件,这种策略甚至可以提高你的性能。
答案 3 :(得分:2)
在这种情况下可能没有相关性,但我设法通过写入压缩数据(zlib)来增加文件读取和写入的应用程序的性能,并在运行中解压缩,减少读/写时间与增加的CPU负载是一场胜利。
或者,如果您的问题是数据量不适合内存而您想将磁盘用作缓存,则可以查看memcached,它提供可伸缩的分布式内存缓存。
答案 4 :(得分:2)
“数百万”地图听起来不像很多数据。 什么阻止你将所有数据保存在内存中?
另一个选择是使用一些适合您需要的标准文件格式,例如sqlite(使用SQL存储/检索数据)或某些特殊格式(如hdf5)或使用类似的东西定义您自己的格式Google Protocol Buffers
答案 5 :(得分:1)
答案 6 :(得分:1)
将计算数据存储在关系数据库中。
答案 7 :(得分:0)