• ベストアンサー

fortranの限界って・・・

こんにちは。 プログラミングはFORTRANくらいしかやった事のない上にあまり得意ではありません。 現在、3列に並ぶ237万行ほどのデータを扱っています。 この3列目のみ、つまり237万個の数字を、 1行あたり14個で並び替えしたいと思っています。 FORTRAN使用です。OSはWinXPです。 ところが、 読み込む時点で237万行のデータ(約1GB)が読み込めません。 テストで数行の軽いデータならうまく回ります。 237万行のデータでは回らないのは、データの行数に限度があるためなのでしょうか? それとも単純なプログラムミス? どなたかお詳しい方、ご教授お願いします。 もし、OSのせいだとしたら、LINUX等ではうまく回るのでしょうか? その場合、WinとLINUXではプログラミングどう違うかも教えて頂けないでしょうか? WinのプログラムはLINUXではそのまま動きませんでしたもので・・・ 宜しくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • ultraCS
  • ベストアンサー率44% (3956/8947)
回答No.6

#4です 補足で大体のことがわかりました。こんな感じでしょうか、一例を挙げてみます。 私はFORTRANは77で引退したので、77で書きます。コメントはコンパイラ通らないのでご注意。 ここではシンプルに書きますが、実際は、もう少しエラーチェックなどをした方が良いでしょう。    CHARACTER*30 STRING    REAL*4 DATA(3)    INTEGER*4 IDATA(14)    OPEN(10,FILE='HOGE.TXT',STATUS='OLD')    OPEN(20,FILE='OUT.TXT',STATUS='NEW')   1 CONTINUE    NDATA=0  データのカウントを初期化    DO 5 LOOP=1,15002  15002回のループ    READ(10,'(A30'),END=9) STRING  データを読み、ファイル終端でループ脱出    if(LOOP .GT. 1) THEN  1レコード目は読み飛ばして2レコード目以降を処理     READ(STRING,'(3F10.1) DATA  数値を取り出し     NDATA=NDATA+1  データのカウントを増やす     IDATA(NDATA)=INT(DATA(3)*10000.+0.1)  整数化     IF(NDATA .EQ. 14) THEN  14個読んだら書き出す      WRITE(20,'(14I5)') IDATA      NDATA=0  データのカウントを初期化     ENDIF    ENDIF   5 CONTINUE    IF(NDATA .GT. 0) THEN  15001/14だとあまりが出るけど書くのかな     WRITE(20,'(14I5)') (IDATA(1),I=1,NDATA)     NDATA=0    ENDIF    GO TO 1   9 CONTINUE    IF(NDATA .GT. 0) THEN  読み終わりでデータのあまり対策     WRITE(20,'(14I5)') (IDATA(1),I=1,NDATA)     NDATA=0    ENDIF    CLOSE(10)    CLOSE(20)    STOP    END こんな感じでしょうか、久々のFORTRANで自信がないけど。 大きな勘違いをしているようならご指摘ください     

hinekichi
質問者

お礼

どうもありがとうございます!私の考えていた流れとほぼ同様でした!特に困っていた読み込みのところがとても参考になりました!大変勉強になりました、みなさんのお蔭で完成致しました!ありがとうございました!

その他の回答 (5)

回答No.5

No.3の補足に対する回答 ひゃぁ、学習5日目ですか! もっとも、私も40年前の入社当時、3日でFORTRANを独習させられ、すぐ仕事をあてがわれました。だからお気持ちはわかるつもりです。しかし、FORTRAN文法は既に忘却の彼方です。 > 1行目、15003行目、30005行目、45007行目・・・ 今度はこうなるのですね。 0000001 >    0000001÷15002=0...1 0000002 データ … 0015003 >    0015003÷15002=1...1 0015004 データ … 0030005 >    0030005÷15002=2...1 0030006 データ … 0045007 >    0045007÷15002=3...1 0045008 データ … 0060009 >    0060009÷15002=4...1 0060010 データ … ">"記号が入っているのは、15002×n+1(n=0,1,2・・157)行目であると既に分かっていれば、これから読み取ろうとする行番号を15002で除したときの余りが1であれば「読み飛ばし」をすれば済みます。 > 最初から(15002×n+1)行目だけを避けて… 文字データの読み方をご存知ですか? ">"の右側に改行文字があるかどうかは不問として、必用な文字数を読み込んで(A変換を使います)知らん顔していればいいのです。 【おまけ】 全てのデータをメモリーに一気読みさせるのは不適当です。 メモリーは有限だし、そのメモリーを使ってOS等目に見えないソフトが動く仕組みになっているので、データを扱う場合は、遠慮しいしいちょびっとのメモリーを都合してもらって処理します。なおメモリーはOSが管理していて、限度以上のメモリーをよこせと要求すでば、OSはこれを拒否します。これがエラーにつながるのですね。 では、どれくらいのメモリーなら確保できるかというと、64キロバイト以下とするのが無難なところです。

hinekichi
質問者

お礼

ありがとうございます! 考え方、大変参考になりました!どうやら私は文字変換で変な勘違いをしていた為に、'>'記号を読むところでつまってました。プログラムはデータ一気読みを避けて組むことが出来ました。アドバイス本当にありがとうございました!

  • ultraCS
  • ベストアンサー率44% (3956/8947)
回答No.4

#1の方が頑張っておられるようなので、余計な口を出すのははばかられるのですが ・前二列のデータは不要と言うことでいいんですね。 ・三列目だけを七行ごとに纏めると言うことでしょうか ・>が入っている行のフォーマットは固定されていますか、また、必ず、15002行おきでしょうか ともかく、「まずすべてをよみこむ」というのが、間違いの根源です(はっきり言って素人プログラミング)。 基本的には逐次処理で解決できる問題ですよ。七行読んだら書いてバッファをフラッシュ、別にカウントして、15002行目にはそれなりの処理をすれば済むだけだと思うんですがね。 作ったソースとデータの最初十行くらいを出してくれるともっとちゃんとアドバイスできるのですが

hinekichi
質問者

補足

どうもありがとうございます。 おっしゃる通り、プログラミング歴=FORTRAN歴=5日目です。 >前二列のデータは不要と言うことでいいんですね そうです。三列目のみです。(細かく言うと前二列は別に使いますが、それは解決しています) >三列目だけを七行ごとに纏めると言うことでしょうか 三列目のデータを14個並べ、次の行へ、です("FORMAT(14)"で改行は勝手にやってくれているみたいですが)。 >">"が入っている行のフォーマットは固定されていますか、また、必ず、15002行おきでしょうか 1行目、15003行目、30005行目、45007行目の、 (15002×n+1)行目(n=0,1,2,・・・157) に">"が出てきます。 出てくるのは">"のみで、このフォーマットは固定です。 (ちなみに、">"は文字や実数など、扱いがわかりません) ">"を含む「全てを読み込む」のが間違いですか、 それを聞いて一歩前進した気がします。 おっしゃられる「それなりの処理」をご教授願えますか? 参考までに、 ソースは ********************************* > -4.9 0.0000 0.0049 -4.9 0.0040 -0.0052 -4.9 0.0080 -0.0033 ・・・・・ -4.9 60.0000 -0.0544 > -2.2 0.0000 0.0035 -2.2 0.0120 -0.0028 -2.2 0.0160 -0.0924 ・・・・・ -2.2 60.0000 0.2314 > ・・・・・ ********************************** スペースがうまく表現出来ませんが、 このFORMATは"FORMAT(F10.1,F10.4,F11.4)"です。 このように、1列目が-4.9や-2.2でくくられており、これをひとブロックとすると、これが158回続きます。 ひとブロックあたり15001個行のデータ、その頭の行に">"の行があるといった感じです。 これを1行14個のデータに並べたい訳です。 このFORMATは"FORMAT(14I5)"です。 *********************************************** 49 -52 -33 -17 -74 -97 -58 3 39 25 -21 -65 -74 -32 31 62 26 -28 -42 57 80 66 30 -5 -22 -14 5 17 ・・・・・ *********************************************** このように、と言いたい所ですがこちらも上手く表現出来てません。 FORMATを参照して下さい。 説明が分かりにくかったらすみません、 どうかアドバイス宜しくお願い致します!!!

回答No.3

No.2の補足に対する回答。 たて並びデータの様子は以下に示すようになっているとします。 間違っていたら適宜調整してください。大筋ではこのようなやり方でいいはずです。 左側の7桁の数は説明の便宜上付加した行番号で、それを15000で除したきの商と余りを右にコメントしてあります。 ここで、余りの方は">"の出現回数に一致していることに気がついてください。 0000001 >    0000001÷15000=0...1 0000002 データ … 0015002 >    0015002÷15000=1...2 0015003 データ … 0030003 >    0030003÷15000=2...3 0030004 データ … 0045004 >    0045004÷15000=3...4 0045005 データ … 0060005 >    0060005÷15000=4...5 0060006 データ … という様相を呈するのであれば、読み取り行数と">"記号が現れる回数をカウントしましょう。ILINE=1 IGREATER=1が初期値となります。 ILINEは1行読む都度1増えます。IGREATERは">"記号が現れる回数とすれば、読み取り行番号を15000で除した時に、余りがIGREATERに等しければその行を読み飛ばすようにするのです。 なお読み飛ばしたときはIGREATERを1増すようにしてください。 230万行程度ならこのやり方で大丈夫ですが、余りが0になるとバグが顔を出します。そうならないよう、幸運を祈ります。

hinekichi
質問者

補足

度々すみません、ありがとうございます。 先の補足で15000毎、と言いましたが、間違いです。 1行目、15003行目、30005行目、45007行目・・・ と、15002行目毎に">"記号が入っています。 >その行を読み飛ばす についてですが、その方法を教えて頂けませんか? ご説明頂いた割り算の理論は、">"記号の行を数式で条件化するものだと理解しましたが(意図が違うようでしたら私の理解力不足をご指摘下さい)、 ">"記号が入っているのは、 15002×n+1(n=0,1,2・・157)行目 であると既に分かっています。 この行だけ、読み込むのを避ける方法はございますでしょうか? 今の私の状況は、 まず全てを読み込む、そして上記(15002×n+1)行目だけを避けて書き込む、というフローで考えてましたが、 ">"記号をどう扱っていいかわからずREAD文で止まってしまうのです。 ">"記号の部分を読み込んで処理するのではなく、 最初から(15002×n+1)行目だけを避けて読み込めないものでしょうか? 長く付き合って頂いて本当にありがとうございます。宜しくお願いいたします!!!

回答No.2

No.1の補足に対する回答。 私も早とちりしたかもしれません。 さて、14行のデータを1行にまとめると、 2,370,000÷14=169,286 となり、ざっと17万行のファイルができあがります。 行列の入れ替えのように難しく考えないで、単純に処理させればいいでしょう。ディスクアクセスが頻繁になるので、処理終了まで1時間程度はかかるかも? 1時間かかるとしても、喫茶室にお出かけになればいいでしょう。 1)ファイルDATA-1をAppendモードで開く。 2)データファイル(DATA-Xとする)をReadOnlyモードで開く。 3)DATA-Xから14行読み取る。 4)三列目の情報のみ取り出し、1レコードとしてDATA-1に   追記する。 5)改行文字を出力する。 6)以下データが尽きるまで3)-5)を繰り返す。 プログラムの終了条件は、DATA-Xから14行を読み取れなかったとき、またはEND OF FILEとなったときです。 おおまかな予想処理時間は、14行の読み取りおよび1行の書き込みにそれぞれ15msかかるとして、 (15+15)×169,286=5,078,580ms が見込まれます。これは5,078秒となり、84.6分(1時間25分)になります。 この時間が大変だというときは、28行ずつ読み取り、2行ぶんを一度に書き込むような工夫をしなければなりません。 その前に、ディスクの1セクタは256バイトであり、この単位で読み書きしますので、書き込むフォーマットも工夫する必要が出てきます。 取り出した三列目の数字を9桁のフォームで14個横並べすると126バイトになります。改行文字(CR+LF)を加えて128バイト。1セクタに二行分記録するとして、256バイトちょうどになります。これが最も効率のよい記録フォームではないかと思います。 単純とはいえ、厄介な処理ですね。

hinekichi
質問者

補足

良くわかりました、ありがとうございます! ところで、追加質問で恐縮ですが、縦並びデータは1行目、及び15000行ごとに『 > 』記号が入っており、readできなくて困ってます。 プログラム作成で『 > 』の行だけ飛ばす、 指定した行から指定した行を読み込む(これが簡単そうに見えて出来ませんでした・・DOループで2~150001まで、15003~ と指定しても1行目から読み込もうとしてしまいます)、 或いはその他の方法がございましたら是非お教え下さいませんか?

回答No.1

> 読み込む時点で237万行のデータ(約1GB)が読み込めません。 約115万行なら500MB 約64万行なら256MB 約32万行なら128MB 約16万行なら64MB 約8万行なら32MB 約4万行なら16MB 約2万行なら8MB 約1万行なら4MB 約5000行なら2MB 約2500行なら1MB この1MBというのがお使いのFORTRANの作業領域に関する制約かどうかわからないのですが、仮に1MBだとして、三列目の値に注目します。 work1ファイルには三列目の値が0~2500のものを抜き出してSORTします。 work2ファイルには三列目の値が2501~5000のものを抜き出してSORTします。 work3ファイルには三列目の値が5001~7500のものを抜き出してSORTします。 …… という具合に分類SORTしておいて、最後にwork1,work2,work3,…を一つのファイルに連結すればいいのですが、手操作による介入が必要になると思います。 これは最も単純な処理方法なのですが、業務ではSORT/MERGEというソフトを利用するのが通例です。ここに、MERGEというのは「併合」くらいの意味と思ってください。 これは二つのデータファイルがあるとき、この二種類のデータキーを互いに昇順(或いは降順)に保ちながら、新しい昇順(或いは降順)ファイルにまとめあげることを目的とします。 このやり方はdata1およびdata2ファイルをそれぞれ昇順(或いは降順)にSORTしておき、data1およびdata2の先頭から順に読み出し、大小を勘案しながらdata3ファイルに記録していくものです。 ご質問の内容はSORTなのですが、大規模データということを考えれば、データを分割してSORTし、何回かのMERGE操作を繰り返すことになりそうです。 1)データの先頭から約1000行程度を取り出し、SORTする。   これをDATA-1とします。 2)データの1001行目から約1000行程度を取り出し、SORTする。   これをDATA-2とします。 3)DATA-1とDATA-2をMERGEして、これをDATA-3とします。 4)DATA-3のファイル名をDATA-1に変更します。 5)データの2001行目から約1000行程度を取り出し、SORTする。   これをDATA-2とします。 6)DATA-1とDATA-2をMERGEして、これをDATA-3とします。 7)DATA-3のファイル名をDATA-1に変更します。 8)データの3001行目から約1000行程度を取り出し、SORTする。   これをDATA-2とします。 9)以下同様に繰り返し、元データが尽きるまで処理します。 結局、SORTの他にMERGEが必用になってきたというところですが、SORT済みの二つのファイルをMERGEする方式の説明については割愛します。それほど難しくない処理ロジックなので、研究がてら開発してみてください。 また、MERGEライブラリがあるなら、開発の手間をかけるよりもそちらを利用した方がいいです。 なお上記は1000行単位で処理していますが、2000行単位に拡大しても大丈夫だと思います。

hinekichi
質問者

補足

ご丁寧にありがとうございます。説明不足で申し訳ありませんでした!「並び替え」と書きましたが昇順、降順ではなく、単純に縦書きを横書きに変換です。 1 43 326 54 -22  ・  ・ を 1 43 326 54 -22 ・・ といった感じにです。 昇順、降順よりも単純かと思われますが、もし宜しければ再度ご教授お願いしますm(_ _)m

関連するQ&A

  • fortranでテキストファイルを読み込む

    fortranでプログラムを作っています。 普通にテキストファイルの文字列を読み込むことくらいは出来ます。 そこで、質問です。 あるテキストファイルがあります。 これは行数が何行あるかわからないとします。 しかし、一行の形式はすべて同じです(例えば、3つの数字とか)。 そこで、ループでこのファイルをすべて読み込み、 行が無くなったらREADを終了する方法を知っている方がいたら教えて下さい。 ちなみにfortranは77もしくは95です。 わかりづらくて済みません。 よろしくお願いいたします。

  • Fortranについて

    私は今大学生のものです。 今卒業研究でFortranのプログラムを用いています。しかし私はプログラミングには疎く、独学で勉強しようと思うのですがなにか初心者にわかりやすいお勧めの本、サイトなどはあるでしょうか? 本屋に行ってもFortranの本は販売されておらず、通販では手にはいるのですがどの本がいいのかわかりません。是非教えていただければと思いここに書き込ませていただきました。 また、家でもFortranのプログラムをコンパイル、実行できる環境をつくりたいのですがどうすればよろしいでしょうか? 学校ではcygwinをインストールして行っていますが家でもcygwinをインストールすればいいのでしょうか? また今もととなるプログラムはあるのですがこのプログラムはLinux上では正常にコンパイルされないところがあるらしく書き直さなければならないらしいのですがLinux上でのFortranのプログラムは普通のFortranのプログラムとは違うのでしょうか?ちなみに学校のパソコンのOSはWindows Vistaです。 初心者の質問ばかりになってしまってすみません。自分でしっかり学びたいと思うのでぜひ教えてください。

  • fortranに関する質問です。

    fortranに関する質問です。 100個の整数データが並んでいるdate1.TXTとdata2.TXTがある。この二つのファイルを読み込んで、200個全てのデータを小さい順に並び替え、1行に10個ずつの整数を印字して画面上に出力しなさい。全データの和、平均値、最大値、最小値を求めて出力しなさい。 1、 データファイルはそれぞれ100個の数字が並んでおり、date1.TXTには3桁の数字が5個ずつ20行、data2.TXTは2桁の数字が10個ずつ10桁の型式できにゅうされている。 2、配列を用いる方法でプログラムを作ること。 以上の問題が全く理解できません。 出来れば、詳しく教えていただきたいです。

  • FORTRAN 行数の分からないテキストデータの読み込み

    FORTRANで、テキストデータを読み込む際、読み込みたいデータの行数が あらかじめ分からない場合、どのように書けばいいのか分からずこまって おります。たとえば、データ数の行数が、 a、a1、a2・・・ b、b1、b2・・・ c、c1、c2・・・ d、d1、d2・・・ e、e1、e2・・・ などで、5行と分かっている場合は、 do=1,5 read(*,*)・・・ ・・・ と書けばいいことは分かるのですが…。 データの行数が予め分からなくても、すべてのデータを読み込ませる方法 (書き方)についてよろしければご教授ください。

  • fortran freeについて

     現在fortran のフリーコンパイラを探しています. 作業環境が Dual CPUが増えたため,dual CPU対応のフリーコンパイラをご存知でしたら教えてください. 通常使用しているPCのOSはWin XPですが,Win版が無ければLinux等でも構いません. どなたか良い情報がありましたら教えてください.よろしくお願いします.

  • Fortranで文字の読み込み&書き込み

    こんばんは。 FORTRANでとあるデータを処理しているのですが、 そこでひとつ分からないことがあるので質問します。 ご存知の方、ご教示願えないでしょうか。 以下、質問内容 ------------------------------------ 「aaaa_50」という文字列から、「_50」のみの文字列を抜き出したい。 具体例から説明しますと、 1 parameter A 2 read (10,*) A <-- Aは「aaaa_50」という文字列。 3 write (10,*) A <-- このままでは「aaaa_50」を書き込みます ------------------------------------ 確か2行目と3行目の間に何らかの処理を書けば「_50」の文字列が 表現出来たと思うのですが・・・ 説明も分かりにくいかもしれませんが宜しくお願いいたします。

  • fortranを動かす最速なパソコンとは?

    お世話になります.初めて書き込みします. 今現在 (1)Compaq Visual Fortran Standard Edision for Win32 x86 Systems(Version6.6) (2)Fortran & C Package V2.0(Fujitsu) の2つを使用してfortranのプログラムを行っています.これらを動かすのに最速なパソコンをご存知の方ぜひ教えてください.ちなみに今使用しているパソコンは Pentium4 DELL OS:Windows 2000 CPU:1.8GHz です.dual CPUを使用するとかえって遅くなるとか,macやLINUXを使用した方が速い等の噂も聞くのですがその辺ご存知の方もぜひご回答ください.(FujitsuのFortranについてはV4.0にUPグレードさせる予定です)プログラムの作り方によって速度もかなり変わるかと思いますが,個人の考えでも構いませんので宜しくお願いします.

  • [awk]2つのファイルを参照して1つのファイルに出力する方法

    最近プログラミング(シェル、awk)を始めた者です。 かなり大まかなものは作れるようになったのですが、急遽、大規模なデータ整理を行わないといけなくなってしまったため、皆さんの知恵を貸していただきたく質問いたしましたm(_ _)m 以下に示すような2つのファイルがあります。 (file1)         (file2) 1 6           1  1  2  10 11 2 3           2  3  5  7  8 3 5           3  6  2  12 13 4 1           4  9  4  5  19 5 2           5  10 19 1  5 6 4           6  4  8  2  9 file1を上から1行ずつ順に読んでいき、2列目の値と同じものをfile2の1列目から探します。合致したところで、file2の合致した行の2列目以降を行番号を付けて表示するというものです。 (「file1の2列目の値=file2の1列目の値」を探し、file2の合致行の値を出力。) 上記ファイルですと、結果的に 1  4  8  2  9 2  6  2  12 13 3  10 19 1  5 4  1  2  10 11 5  3  5  7  8 6  9  4  5  19 という具合になります。 2つのファイルの行数は同じではなく、また、両ファイルとも1列目が行番号というだけで、他の列の値に規則性はありません。 file2の行数は100万以上の大規模なものになります。 自分が作ったものを掲載できればよかったのですが、あいにく会社のPC内にありまして、持ち出しできないため、掲載できません。 動作環境はLinux(RedHat)になります。 他のプログラミング言語についてはまだ分からないため、awkもしくはシェルでお願いいたします。

  • FORTRAN77のプログラミングを、Windowsで

    大学でFORTRAN77のプログラミングをしています。家でも、練習したいので、Windowsでも使えるプログラミングソフトを探しています。過去の質問を検索した結果、fcpad.exeというソフトが使えるようなので、http://www.vector.co.jp/soft/dl/win95/prog/se153699.htmlから、ダウンロードしたのですが、ソフトを起動すると、「コンパイラのパス」という項目に何かを入力しなくてはいけないようなのですが、適当に入力しても、「コンパイラのパスが正しくありません」と表示されます。一体何を入力すればよいのでしょうか? ちなみに家のパソコンのOSはWindows98です。

  • EXCELで同じ値のセルを結合したいのですが。。。

    よろしくお願いします。 OSはwindows2000で、EXCEL2000を使用しています。 A列内に数字が昇順に入っています。 数字によって、行数がばらばらで1~1000の値が入っていますが、全体では、5000行のデータです。 同じ値のセルを結合したいのです。 現状は、1から順に選択して、セルの結合しています。 早く出来る方法ありますか? よろしくお願いします。

専門家に質問してみよう