FORTRANの入出力を圧縮ファイルにする(Linux編)

出典: トータル・ディスクロージャ・サイト(事実をありのままに)

あるプログラムで大量のテキストファイルを出力し、ハードディスクの容量が足りなくなりそうなことはよく経験します。対策としてよく行われるのは、プログラムの実行終了後、テキストファイルをgzipなどで圧縮し、元のファイルを消去することで、ハードディスクを解放するというものでしょう。しかし、圧縮前と圧縮中は、両方のファイルが存在するため、ハードディスクに余分な容量が必要になります。もし、プログラムの実行後でなく、実行と同時に圧縮を行い、圧縮前のファイルを存在させない方法があれば、ハードディスクの容量が大幅に節約できます。また、大量のテキストデータをハードディスクに書くのではなく、圧縮されたデータをハードディスクに書きこむので、書き込み時間が節約になり、結果的にプログラムの実行速度が向上します。これは、次の方法で可能になります。プログラムで大量のテキストデータを読み込む場合にも応用できます。

今回のサンプル

1000000要素の配列に1 - 1000000の値を詰め込んでファイルに書き出す、

      PROGRAM WRITE
      IMPLICIT NONE
      INTEGER I,N
      PARAMETER (N=1000000)
      DOUBLE PRECISION A(N)
      DO 10 I=1,N
         A(I)=DBLE(I)
 10   CONTINUE
      OPEN(1,FILE='INPUT.DAT',STATUS='UNKNOWN')
      WRITE(1,*)(A(I),I=1,N)
      CLOSE(1)
      STOP
      END

と、ここで作成したファイルを読み込んで、その入力の合計を求めて出力する、

      PROGRAM READ
      IMPLICIT NONE
      INTEGER I,N
      PARAMETER (N=1000000)
      DOUBLE PRECISION A(N),SUM
      OPEN(1,FILE='INPUT.DAT',STATUS='OLD')
      READ(1,*)(A(I),I=1,N)
      CLOSE(1)
      SUM=0.0D0
      DO 10 I=1,N
         SUM=A(I)+SUM
 10   CONTINUE
      WRITE(*,*)SUM
      STOP
      END

の、2つのプログラムを使う。

圧縮ファイル利用の方法

このサンプルにおいて、INPUT.DATはテキストファイルであるが、このファイルを圧縮ファイルとしたい。今回のデータ圧縮には、多くのLinuxディストリビューションで採用されているであろう、gzipを使うものとする。他の圧縮ユーティリティを使われたい場合は、以下の解説のgzipコマンド、および.gz拡張子を、使われたい圧縮ユーティリティのものと置き換えて考えていただきたい。

まずは、INPUT.DATというファイル名で、名前付きパイプを作る。「名前付きパイプ」が何か、という点については、名前付きパイプとは【named pipe】 - 意味/解説/説明/定義 : IT用語辞典のページあたりに簡潔な説明がある。INPUT.DATというファイルが存在しない状態で、以下のコマンドを入力すれば、INPUT.DATというファイル名の名前付きパイプができる。

$ mkfifo INPUT.DAT

これで、INPUT.DATというファイル名に対して書き込んだデータが、INPUT.DATというファイル名に対して同時にアクセスすると、読み出せる状態となる。この一連の処理で、INPUT.DATというファイルがあるストレージに対しては、アクセスが行われないため、INPUT.DATに書き込んだデータが、直接ストレージの容量を使うことは無い。代わりに、このデータを使って圧縮された.gzファイルのみが、ストレージに対する書き込み処理となる。

次に、gzipコマンドを使ってINPUT.DATを圧縮する処理を、バックグラウンドで走らせる。

$ gzip -c < INPUT.DAT > INPUT.DAT.gz &
[1] 00000

これで、INPUT.DATにデータを書き出す処理を行うと、そのデータがそのまま圧縮されてINPUT.DAT.gzに書き出される状態となる。そこで、writeプログラムを走らせる。

$ ./write
[1]+  Done                    gzip -c < INPUT.DAT > INPUT.DAT.gz

この時点で、INPUT.DAT.gzという形で、圧縮されたデータファイルができる。次は、圧縮ファイルをINPUT.DATに展開する処理を、バックグラウンドで走らせる。

$ gzip -dc < INPUT.DAT.gz > INPUT.DAT &
[1] 00000

今度は、INPUT.DATからデータを読み込む処理を行うと、INPUT.DAT.gzを展開したデータが読みだされる状態となる。そこで、readプログラムを走らせる。

$ ./read
   500000500000.00000
[1]+  Done                    gzip -dc < INPUT.DAT.gz > INPUT.DAT

1 - 1000000の和である、500000500000の値が正しく求められている。

この圧縮ファイルと、これを展開したものとで、容量を比較する。

$ ls -l INPUT.DAT.gz
-rw-rw-r-- 1 user user 2635974 00月 00 00:00 INPUT.DAT.gz
$ gzip -dc < INPUT.DAT.gz | wc
      1 1000000 26000001

本来約26 MBであったデータが、約2.6 MBに圧縮できていることがわかる。

注意点

現状のGCCやIntel Fortranなどの実装では、この方法が使えるのは、テキストファイルのみで、バイナリファイルには行えないようである。また、REWINDのような、ファイルシーク処理を行う処理も、この方法と組み合わせることができないため、注意が必要である。


この記事へのコメントをお寄せください

  • サイトへの書き込みに差し支えございましたら トータルディスクロージャーサイトサポート係へメールをお送りください
  • トータル・ディスクロージャ・サイトに投稿された文章と画像は、すべてその著作権がHPCシステムズ株式会社に帰属し、HPCシステムズ株式会社が著作権を所有することに同意してください。
  • あなたの文章が他人によって自由に編集、配布されることを望まない場合は、投稿を控えてください。
  • コメントを書き込む場合は名前にひらがなを織り交ぜてください。
  • あなたの投稿する文章と画像はあなた自身によって書かれたものであるか、パブリック・ドメインかそれに類する自由なリソースからの複製であることを約束してください。あなたが著作権を保持していない作品を許諾なしに投稿してはいけません!

<comments hideform="false" />


Comments

ノート:FORTRANの入出力を圧縮ファイルにする(Linux編)

個人用ツール