代码之家  ›  专栏  ›  技术社区  ›  builder-7000

减小Fortran中输出文件的大小

  •  2
  • builder-7000  · 技术社区  · 8 年前

    我希望在不丢失任何数据的情况下最小化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='UNFORMATED',则每个记录前面都有一个整数*4计数,使每个记录比正常记录长8个字符。此约定不与其他语言共享,因此仅对Fortran程序之间的通信有用。

    我的问题是:

    1. 为什么在 form1.txt 和 form2.txt ?请注意 file1.txt 取决于格式(例如,如果我更改行 format(9i3) 到 format(9i4) 文件大小 文件1.txt 增加9字节)。

    还有我的 主要问题是:

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

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

    2 回复  |  直到 8 年前
        1
  •  3
  •   chw21    8 年前

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

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

    直接访问存储了整数的二进制表示,因此每个数32位或4字节。总共36字节。这超过了格式化版本的28个,但是它可以处理所有整数,最大2147483647,最小2147483648,同时仍然保持相同的大小。(如果您希望格式化版本具有相同的灵活性,则需要格式化 9I11 总共100字节)。

    未格式化的版本有点居中,它仍然存储一些元数据,这就是为什么它比直接访问大一点,但是像直接访问一样,您可以以这种方式存储所有整数,同时占用相同的空间量。

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

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

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

        2
  •  3
  •   Obay    8 年前

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

    你可以使用像 blosc 甚至可以超越C的RAM到RAM memcpy() . 有效性和性能显然很大程度上取决于数据的分布,但在实际应用中可以达到数十GB/s。

    100GB可能是许多适合您机器RAM的数据。可以手动将文件分块,也可以使用类似的库 HDF5 . HDF5为基本上任意数量的高性能数据提供压缩块存储。然而,合并一个大型图书馆可能是一些工作,即使有一个 HDF5 Fortran API .