【问题标题】:Reduce size of output files in FORTRAN减少 FORTRAN 中输出文件的大小
【发布时间】:2018-05-27 23:29:53
【问题描述】:

我想在不丢失任何数据的情况下最小化 FORTRAN 中输出文件的大小。为了找到这样做的最佳方法,我编写了程序:

      program test                                                              

      character(len=255) format

1     format(9i3)                                                               

c FORMATTED          
      open(99,file='form1.txt',form='formatted')                                
      do i=1,1                                                            
        write(99,1) 1, 2, 3, 4, 5, 6, 7, 8, 9                                   
      enddo                                                                     
      close(99)                                                                 

c UNFORMATTED          
      open(98,file='form2.txt',form='unformatted')                              
      do i=1,1                                                            
        write(98) 1, 2, 3, 4, 5, 6, 7, 8, 9                                     
      enddo                                                                     
      close(98)                                                                 

c DIRECT ACCESS          
      nrec=sizeof(i)*9                                                          
      open(97,file='form3.txt',form='unformatted',                              
     &     access='direct',recl=nrec)                                           
      do i=1,1                                                            
        write(97,rec=i) 1, 2, 3, 4, 5, 6, 7, 8, 9                               
      enddo                                                                     
      close(97)                                                                 

      call system('ls -lh form?.txt')                                           
      end

这将创建三个文件,每个文件都有一条记录。这个程序的输出是:

-rw-r--r--. 1 user users  28 May 27 17:10 form1.txt
-rw-r--r--. 1 user users  44 May 27 17:10 form2.txt
-rw-r--r--. 1 user users  36 May 27 17:10 form3.txt

来自Oracle's website:

如果 FORM='UNFORMATTED',则每条记录都以 INTEGER*4 计数开头和终止,使每条记录比正常长度长 8 个字符。此约定不与其他语言共享,因此仅对 FORTRAN 程序之间的通信有用。

我的问题是:

  1. 为什么form1.txt 和form2.txt 之间有16 个字节(而不是前面引用中提到的8 个字节)?请注意,file1.txt 的大小取决于格式(例如,如果我将行 format(9i3) 更改为 format(9i4),file1.txt 的文件大小将增加 9 个字节)。

我的主要问题是:

  1. 我有五列数百万行的大数据文件(大于 100G)。 FORTRAN 中减小输出文件大小的最佳方法是什么(可能以二进制形式编写)?

与我类似的问题是:Best way to write a large array to file in fortran? Text vs Other

【问题讨论】:

    标签: file binary fortran size


    【解决方案1】:

    基本上,您的格式9i3 意味着每个数字将在文件中占用 3 个字节。那是 27 个字节加上一个回车符等于 28。

    但是您只能以这种格式存储最多 999 的数字,即使这样,超过 99 的数字也会混合在一起。

    未格式化的直接访问存储整数的二进制表示,因此每个数字 32 位或 4 个字节。总共是 36 个字节。这比格式化版本的 28 个多,但它可以处理所有整数,最高为 2,147,483,647 和最低为 -2,147,483,648,同时仍然是相同的大小。 (如果您希望格式化版本具有相同的灵活性,则需要格式 9I11 总共 100 个字节)。

    未格式化(顺序)版本有点中间,因为未格式化,它存储二进制表示,但它仍然存储一些元数据(记录长度),这就是为什么它仍然有点大,但就像未格式化直接访问,您可以以这种方式存储所有整数,同时占用相同的空间。

    关于你的第二个问题,你应该使用什么取决于很多事情。正如您所注意到的,如果您的整数始终介于 0 和 99 之间,则它们的字符串表示小于二进制表示。但是一旦你需要 4 位数字(包括符号),那么二进制表示就会变小。我可能还应该指出,如果你的数字很小,你不妨将它们声明为 8 位或 16 位整数,这意味着它们分别只占用一个或两个字节。

    二进制表示也更快,因为数字不需要在二进制和字符串之间转换。

    但是对于您所说的大小,研究其他文件格式可能很有价值,例如 NetCDF,它具有一些压缩数据的方法。

    【讨论】:

    • 我(姗姗来迟)编辑了答案以使其更清晰。谢谢@IanH
    【解决方案2】:

    虽然没有直接解决您的问题,但我想指出,如果您使用二进制数据,文件大小有一个下限。即使最密集的存储表示没有任何校验和或元信息,例如使用记录长度,您必须存储 sizeof(datatype)*num_entries 字节。

    您可以使用像 blosc 这样的快速压缩算法,甚至能够胜过 C 的 RAM-to-RAM memcpy()。有效性和性能显然在很大程度上取决于数据的分布,但在实际应用中可以达到数十 GB/s。

    100GB 的数据量可能足以容纳您机器的 RAM。可以手动对文件进行分块,也可以使用HDF5 之类的库。 HDF5 为基本上任意数量的高性能数据提供压缩的分块存储。但是,即使有 HDF5 Fortran API,也可能需要合并一个大型库。

    【讨论】:

    • 在我的示例中,表达式 sizeof(datatype)*num_entries 生成一个包含 36 个字节的文件,因为 sizeof(datatype) 是 4,num_entries 是 9。现在我很困惑,因为这是文件大小,但我有另一个文件 (form1.txt) 的大小较小(28 字节)。文件form1.txt 是一个包含单行的ascii 文件:__1__2__3__4__5__6__7__8__9(这里我用_ 表示一个空格)。
    猜你喜欢
    • 2021-07-01
    • 2017-05-05
    • 2013-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-10
    • 1970-01-01
    相关资源
    最近更新 更多