c - 将数字数据存储在二进制文件和数据结构中

标签 c data-structures binaryfiles

我是一个新手,我正在寻找一些方向,因为这个话题的可能性似乎是无穷的。
我正在运行一个数值模拟,它创建了很多数据,我希望不再将其存储为纯文本(一旦我试图保存所有创建的数据,最后得到一个4TB txt文件)。
我的模拟是在一个时间间隔内包含4个场(每个场由一个通常4000到16000个元素的双倍数组表示),它们每次进化大约100万个周期,所以我们讨论的是产生的数十亿个双倍。
当然,我不会每次都保存所有内容,而是使用3种类型的文件
(由于简短的原因,这些文件是一个模型,我的实际文件都是以%g格式编写的,因此它们采用这7个字符+表格):
将字段内容保存在所有时间点的特定点的文件,例如:

t     Phi    Pi    Delta    A
0     1.3    0.4   0.3      0.99
...

在某个时间步保存整个间隔内所有字段的文件
x     Phi   Pi    Delta    A
0     0.0   0.4   0.0      1.0
...

在时间和空间上每n步保存一次的文件
t    x    Phi    Pi    Delta    A
0.0  0.0  0.0    1.3   0.0      1.0
0.0  0.1  0.01   1.2   0.02     0.98
...
0.2  0.0  0.0    1.3   0.0      1.0
0.2  0.1  0.03   1.5   0.01     0.95

然后,我将这些文件用于各种目的,如绘制图形、对它们进行傅立叶变换并使用它们恢复模拟。
我最终需要在集群上运行它,所以我仅限于C语言,目前还不知道他们是否有任何数据库/bigdata系统。
我的问题是:
对于这些数据,最好的格式是什么?我假设它只是将doubles保存为原始二进制文件,然后编写一个程序稍后再检索它们,但我愿意接受建议
组织这些数据的最佳方法是什么?我环顾四周,也许我可以写一棵叶子是数组的树
压缩呢?

最佳答案

存储这些数据的最佳格式是什么
这取决于精度和值的结构。
如果精度的7个有效小数位数足够,且值在2-126到2127(1.17549×10-38到1.70141×1038)之间,则可以使用IEEE-754binary32格式。在所有用于高性能计算的机器和集群上,float类型与此对应。
如果您需要15位有效的小数精度,和/或范围从2-1023到21023(1.11254×10-308到8.98847×10308),请使用IEEE-754binary64格式。同样,在所有用于高性能计算的机器和集群上,double类型都与此对应。
剩下的问题是字节顺序和字段标识。
假设您不希望在计算期间花费任何HPC资源来进行数据转换,则最好以本机字节顺序存储数据,但在文件中包含一个头,该头包含每个值类型的已知“prototype”值,以便读取器可以检查它们以验证是否需要字节顺序补偿来正确解释字段;并为每个字段加上描述符。
(作为一个例子,我以一种方式实现了这一点,它允许用C语言和本地Fortran 95轻松读取文件,并且只需最少的编译器扩展名,还允许每个计算节点将结果保存到一个本地文件中,读卡器自动并行地从多个文件中获取数据。我通常只支持u8s8u16s16u32s32u64s64r32(对于各种位大小的无符号和有符号整数),并且分别支持单精度和双精度实数,或二进制32和二进制64。我还不需要复杂的数字格式。)
大多数人喜欢使用例如NetCDF来实现这一点,但我的方法不同,因为编写器以本机格式而不是规范化格式生成数据;我的目的是最小化数据创建/模拟时的开销,并将所有开销都推给读卡器。
如果您发现在文件生成时(在模拟过程中)的小开销是可以接受的,并且没有编写二进制文件格式例程的经验,我建议您使用NetCDF。
请注意,如果HPC集群操作员发现您的模拟/计算浪费了资源(例如,平均核心CPU负载较低,或者无法很好地扩展到多个核心),则可能不允许您在集群中运行模拟。这显然也取决于当地的政治和政策。
组织这些数据的最佳方法是什么?
由于数据量非常大,并行文件可能是您的最佳选择。(一些集群具有快速的本地存储,在这种情况下,可以将数据直接从每个节点存储到本地文件,并在运行后将这些本地文件收集在一起,这可能是可取的。由于情况不同,请询问集群管理员。)
换言之,每个相关数据数组一个文件。
编写一个可以并行读取多个文件的库并不困难,但是正确解析和管理结构化文件要困难得多。
此外,将数据分割成不同的文件通常会使数据传输更容易。如果您有一个16 TiB大小的数据文件,那么基本上只限于网络传输,甚至可能会限制您可以使用哪些文件系统。但是,如果您有128个文件,每个文件的大小约为128 GiB,那么您有更多的选项,并且在处理其他文件时,可能会将其中一些文件保存在脱机存储中。特别是,许多HPC集群运营商将允许您将文件直接传输到本地媒体存储设备(USB3磁盘或内存条),以减少网络传输拥塞。
压缩呢?
如果需要,您可以压缩数据,但我个人会在您自己的工作站上收集/组合/处理数据的位置进行压缩,而不是在生成数据的位置。HPC计算是昂贵的;当您第一次处理数据时,对数据进行咀嚼要便宜得多。
二进制数据的压缩效果不如文本,但在相同的数据分辨率下,文本文件要大得多。这意味着无论如何选择用于存储每个参数的正确值类型是很重要的。为了保持处理简单,您希望在整个集合中保留该类型,而不是从一个记录更改为另一个记录。
至于压缩/解压缩算法,我会在zlibxz之间进行选择。如需快速查看速度/压缩比曲线,请参见here。简单地说,zlib速度快,但提供了适度的压缩比,而xz速度慢,但提供了更好的压缩比。

关于c - 将数字数据存储在二进制文件和数据结构中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50467987/

相关文章:

python - 比较,例如 float(1.221) 和 c_float(1.221).value,使用减法和 epsilon 还是最佳方式?

c - To const or not to const--当我的代码不会修改用户代码的字符串但我依赖的第三方代码忘记声明const时声明什么?

C++从二进制文件写入和读取 double 矩阵

c - 从文件中读取位时 `16 longs` 和 `110 words` 是什么意思

c - 如何在不使用临时节点的情况下在单链表中插入新节点?

c++ - 如何读/写二进制文件中的结构?

objective-c - 未指定大小的多维数组作为实例变量?

c - MISRA C :2012 Rule 14. 4

c++ - 将整数标识符转换为指针

c# - C#数据结构按顺序添加元素