1 名前:デフォルトの名無しさん [2006/11/12(日) 17:13:35 ] FORTRAN総合スレッドです。 FORTRAN77/90/95/2003, HPF等、FORTRAN全般に関する話題を書き込んで下さい。 ・FORTRAN関連情報 お約束だが、まずは自分で調べよう www.google.co.jp/ x86で動作するFortranコンパイラ www.nminoru.jp/~nminoru/programming/x86-fortran.html The Fortran Company www.fortran.com/ Polyhedron Software www.polyhedron.co.uk/ Google Directory - Fortran directory.google.com/Top/Computers/Programming/Languages/Fortran/ ・前スレ FORTRAN III pc8.2ch.net/test/read.cgi/tech/1104724162/ FORTRAN II pc5.2ch.net/test/read.cgi/tech/1068351911/ Fortran pc2.2ch.net/test/read.cgi/tech/1003214738/
496 名前:デフォルトの名無しさん mailto:sage [2009/02/17(火) 22:12:50 ] >>491 なるほど、ためになったわ。サンキュー。PUREを付けるだけで簡単に速くなったわ。 担当のは基本的に古い人間だから、あまりコンパイラ任せにするなとか言うんよな…。 Fortran90っぽい77形式の文も、「完成した後で直します」とか言ってそのままだったり。 implicit realもcommon文もどうにかしたいけれど、きっと文句言うんだろうな。
497 名前:デフォルトの名無しさん mailto:sage [2009/02/18(水) 02:22:54 ] >>496 PURE 属性はもともと HPF で導入されたものなので、それなりのメーカならコンパイラ にも最適化のノウハウの蓄積があるはず? ELEMENTAL も一変数用にサブルーチン書いて、配列を渡せばいいので、DO..LOOPを あからさまに書かずにすむ。時々ソースがすごくすっきりして楽になることがある。 でも、ついでだから古い人間を擁護してみるかw FORTRAN77 にも、むきだしの良さがあるw Fortran90 以降だとソース上は簡潔になっても、影で動的にテンポラリ配列とか取るので 気持ち悪いところもある。長時間並んだJOB がStackOverflow とかで止まっていたり すると殺してやりたくなる。古い時代の人はその辺が嫌なのかもしれないw COMMON もグローバル変数だと思うとむかつくだろうが、 自分でガベージコレクション しながら、変数領域を自由自在に再利用して操っていると思うと、結構気持ち良い。 メモリーが貴重だった時代には、利用価値が高かった。 IMPLICIT に関していえば IMPLICIT NONE をつけた上で、頭文字を守ればいい。 C と違ってローカルスコープの捨て変数が使えないから、頭文字を守らないと いちいち宣言部に戻って型を確かめないといけないのでめんどい。 Fortran では数値の精度が致命的に重要で、倍精度計算中に1個単精度が混じるだけでも すべての結果が単精度のゴミになるのだから、数値精度に無頓着の他のおしゃれ言語の 連中の言説を信じると痛い目に会わされるw
498 名前:デフォルトの名無しさん [2009/02/18(水) 13:19:26 ] pure属性付けたサブルーチン内で pure属性付けた他のサブルーチン呼ぶ時には interfaceで引数部分の性質を教えて置かないといけないんだね。 f77書式で書いてるのに interface intent が 現れるのでムズムズするけどムズムズするだけなのでそのまま。
499 名前:デフォルトの名無しさん mailto:sage [2009/02/26(木) 16:08:37 ] OpenMPを試してみてるんだけど、いまいちうまくいかないんだが・・・ ifort -QParallel でコンパイル+実行するとうまくいくんだけど、 同じソースをifort -Qopenmp でコンパイル+実行すると Program Exception - stack overflow っていうエラーが出る ソース中にOpenMP構文は use omp_lib だけ これってどうしたらいいのかな?
500 名前:499 mailto:sage [2009/02/26(木) 16:22:10 ] おk事故解決 -auto_scalar オプションでいけた
501 名前:デフォルトの名無しさん [2009/02/26(木) 16:49:38 ] >>500 だたの -auto や -static でうまく行くこともあるよ。あとは実行時の環境変数の setenv KMP_STACKSIZE 16M とかデフォより大きめに取ると幸せなことが多い気がする。
502 名前:デフォルトの名無しさん [2009/02/26(木) 16:50:50 ] >>500 ていうか、 -auto_scalar ってデフォルトになってない?
503 名前:デフォルトの名無しさん mailto:sage [2009/02/26(木) 17:23:54 ] -openmpだとデフォで動的(-auto)になるんだっけか >>499 は単にスタック不足なだけでは? ところで、KMP_STACKSIZEってunlimitedに設定できないの?
504 名前:デフォルトの名無しさん mailto:sage [2009/02/26(木) 17:58:56 ] 動的っていってもヒープとスタックがあるよね。 Fotranの場合ってどういう風に割り当てられるんだろう・・・そういやあまり意識したことなかった。
505 名前:デフォルトの名無しさん mailto:sage [2009/02/27(金) 02:43:33 ] >>504 元々はAUTOMATIC変数の類はスタックに、ALLOCATE命令のときはヒープだった気がする。 ただ歴史的経緯のせいでサブルーチン側で巨大な配列をとっているプログラムが多くて それがSTACKOVERFLOWを引き起こすから、IntelFortranなんかはデフォールトでは スカラー変数はスタックで、配列の類はヒープで確保するようになった気がする。 インテルの掲示板に、デフォールト・オプション切り替えの話が出ていた旗もするのだが 昔のことなので記憶がはっきりしない。 OpenMPを指定すると、オプションが切り替わってしまう話はこのスレに出ている。 software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/59627/ FortranはFORTRAN66時代がSTATICに変数をとっていた関係で、 FORTRAN77で規格の上ではサブルーチン類の変数はAUTOMATICでありうるように なったにもかかわらず、互換性の観点からデフォールトでSTATICに変数を とっていることが多くて、それはFortran90でもしばらく続いていたという歴史的経緯がある。
506 名前:デフォルトの名無しさん mailto:sage [2009/02/27(金) 11:54:19 ] >>505 そのスレのSteveさんが言ってるlocal scalar variablesって、配列じゃない(次元1の)フツーの変数のことだよね? だとしたら、 If you say /Qopenmp (or /Qopenmp-stubs), this changes to /automatic - ALL local scalar variables are allocated on the stack. のALL local scalar variablesはALL local variables(つまりローカルスカラ変数だけじゃなく、ローカル配列変数も含む)の間違いじゃないかな? 勘違いしてたらすいません
507 名前:デフォルトの名無しさん mailto:sage [2009/02/27(金) 13:12:01 ] >>506 そうなんじゃないかな? 配列までスタックにとるからoverflowしていると考えるとつじつまが合う?
508 名前:506 mailto:sage [2009/02/27(金) 13:52:41 ] >>507 そうだよね。SteveさんIntelのスタッフなんだし書き間違わないでくれよぉ・・・ OpenMPの場合にデフォルトで全てのローカル変数(スカラも配列も)がスタックになるのは スレッドセーフのためってあるけど、逆に言えばそれらをstaticに扱ったらスレッドセーフに ならないってことだよね。それってやっちゃまずいことなんだろうか? OpenMPまともに使った経験がないもんで・・・識者の方コメントおながいします
509 名前:デフォルトの名無しさん [2009/02/27(金) 14:48:49 ] -openmp つけてコンパイルすると、仮にautomaticは嫌いだっと -noauto つけても消されるはず。なのでopenMPを読んだ状態だと 有無をいわさずにぜんぶautomaticになる・・・と理解しているけど。 shared属性をつけてかつcommonブロックに貼り付けるとかして やや無理なことをしないとstatic領域には配置されないと思ふ。 -staticはその名のイメージとは違って共有ライブラリを使わない (というか実行ファイルに埋め込んじゃう)オプションだし。 spec.orgにあるOMP2001の情報のところに試した人たちが 実際に使ったオプションが載ってるので、自分のところのシステムに 近い(or 同じ)マシンがあったらそれと同じモノをだいたい使っているけど、 まあ大間違いではないと思う。お薦めできるのかは分らないけど・・・。
510 名前:デフォルトの名無しさん mailto:sage [2009/02/27(金) 15:30:30 ] え、OpenMPだとサブルーチン内ではstatic配置ってできないわけ? 数値計算では馬鹿でかい配列は可能な限りstaticにするのが基本じゃない? サブルーチン渡る度に配列をコピーとかやってられんでしょ? その代わりメモリのアロケーションはコーディングする側がきちんと考えてあげないといけないけど。 この辺がリソースをある意味富豪的に使うことが前提とされるJavaやC#などのオブジェクト系言語との違いだね。
511 名前:デフォルトの名無しさん [2009/02/27(金) 16:56:15 ] 510はちょっと尋ね方が変だな。 副プログラムが並列のloop内にあるのか、 副プログラム内で並列のloopがあるのかで答は変わる。
512 名前:510 mailto:sage [2009/02/27(金) 19:38:52 ] 的外れな質問してたのかな、ごめん・・・。 >>511 の両方のケースとも知りたいので、よかったら教えてほしい。 流体とかの数値計算では行列の反復法とかはサブルーチン内でやるけど、 そういうケースでメモリのアロケーションはどうすべきなのか、という視点で興味があります。
513 名前:デフォルトの名無しさん mailto:sage [2009/02/28(土) 00:58:18 ] >>512 引数に載ってれば、Fortranは参照呼出しなんだから配列のコピーが生じるはずもない。 CやPASCALとは違う。(まぁ最近はVALUE属性も出来るようになったが) ここでは副プログラム内で新たに割り付けられる配列の話だろう。 それが動的に取られるとして、スタックに取られるか、ヒープに取られるかの違い。
514 名前:510 mailto:sage [2009/02/28(土) 01:28:49 ] >>513 >副プログラム内で新たに割り付けられる配列 あ、そういう話か・・・ありがとう。 自分は一時作業用の配列も全部メイン側で用意してやって引数渡ししてるんだけど、 そういうのはサブルーチン内でスタックやヒープで取ってやる方がいいのかな? 皆さんどうしてますか?
515 名前:デフォルトの名無しさん [2009/03/03(火) 06:16:03 ] allocatableを副プログラム内で作ってそれ(先頭アドレスやらサイズその他)を メイン階層や他の副プログラムに行き渡らせるのが割りと 面倒臭いのでメイン階層でやってる。 メイン階層が長くなるのは正直あまり好みではない、けど まあ好みの問題なだけなので気にしないようにしている。 allocatable使うと場合によってはプログラム内で明示するサイズより大きいメモリを扱えたり (コンパイラはハンドルできるメモリサイズ < OSがハンドル出来るメモリサイズ、なので)、 格子数(データ数)の違う処理を同じ実行イメージで出来る(コンパイルしなおさなくて良い)のが いいけど、最近ではサイズをプログラム内で固定変数で明示していちいちコンパイルしている。 その方がミスは少ない気がする。気のせいかもしれないけど。
516 名前:デフォルトの名無しさん mailto:sage [2009/03/03(火) 12:11:34 ] 何がスタックやヒープに割り当てられるのか分からんかったのでググった。 ブログだけどw ttp://monologuemidnight.blogspot.com/2009/01/blog-post_03.html module中の大域的な変数、save属性付きの変数→.bss allocatable属性な配列→ヒープ 普通にサイズが宣言されている自動配列→スタック 手続き中の変数(mainでも同様)→スタック ってことらしいが…。 この辺は規格ではないっぽいので、コンパイラの仕様をちゃんと確認したほうがいいな。
517 名前:デフォルトの名無しさん [2009/03/11(水) 18:46:48 ] ifortで複数の数字を出力すると勝手に改行されるんだけど、改行を抑制するオプションってある? gforntranでは改行されないんだけど。 real(8) a(5) write(*,*) a(:) とするとa(3)とa(4)の間で改行されちゃう。
518 名前:デフォルトの名無しさん mailto:sage [2009/03/12(木) 04:57:59 ] >>517 気持ち悪いけど、下記のようにしてもだめかな? クラシックな書き方だけど。 write(*, '(100f10.5)') a(:)
519 名前:デフォルトの名無しさん [2009/03/12(木) 09:37:42 ] >518 ありがとん。 write(*,'(100f)') a(:) でいけた。
520 名前:デフォルトの名無しさん mailto:sage [2009/03/15(日) 01:01:35 ] 改行抑制なら、write文ならadvance='no'を付ければできるはず 出力するものが決まってるなら、改行してしまう書式の箇所に\(バックスラッシュ)を入れてもいい
521 名前:デフォルトの名無しさん mailto:sage [2009/03/15(日) 11:34:42 ] >520 advanceはフォーマット文がいるから、結局519と同じでは?
522 名前:デフォルトの名無しさん mailto:sage [2009/03/17(火) 03:12:33 ] >>521 '(100f)' なんて書くよりはスマートな気がするけど? ま、どうでもいいことだな
523 名前:デフォルトの名無しさん [2009/03/18(水) 04:24:12 ] do i = 1, 5 write(*, '(f10.5,$)') a(i) enddo write(*,*) '' はダメかな? 改行するなよ、の$は非標準だけどDEC以来ほぼ標準と思っていいのではないだろうか
524 名前:デフォルトの名無しさん mailto:sage [2009/03/18(水) 21:51:40 ] ちょっとテストしてみた@Intel Fortran 10.1 integer::i integer,parameter::imax=5 real(8)::f(imax) do i=1,imax ; f(i)=i ; enddo print *, "print *,f" print *, f print *, '---' print *, "write(*,'(f)') f" write(*, '(f)') f print *, '---' print *, "write(*,'(f)') (f(i),i=1,imax)" write(*, '(f)') (f(i),i=1,imax) print *, '---' print *, "write(*,'(f\)') f" write(*, '(f\)') f print *, '---' print *, "write(*,'(f)',advance='no') f" write(*, '(f)',advance='no') f print *, '---' print *, "write(*,'(f)',advance='no') (f(i),i=1,imax)" write(*, '(f)',advance='no') (f(i),i=1,imax) print *, '---' end
525 名前:>>524の結果 mailto:sage [2009/03/18(水) 21:52:34 ] print *,f 1.00000000000000 2.00000000000000 3.00000000000000 4.00000000000000 5.00000000000000 --- write(*,'(f)') f 1.0000000000000000 2.0000000000000000 3.0000000000000000 4.0000000000000000 5.0000000000000000 --- write(*,'(f)') (f(i),i=1,imax) 1.0000000000000000 2.0000000000000000 3.0000000000000000 4.0000000000000000 5.0000000000000000 --- write(*,'(f\)') f 1.0000000000000000 2.0000000000000000 3.0000000000000000 4.0000000000000000 5.0000000000000000 --- write(*,'(f)',advance='no') f 1.0000000000000000 2.0000000000000000 3.0000000000000000 4.0000000000000000 5.0000000000000000 --- write(*,'(f)',advance='no') (f(i),i=1,imax) 1.0000000000000000 2.0000000000000000 3.0000000000000000 4.0000000000000000 5.0000000000000000 ---
526 名前:デフォルトの名無しさん mailto:sage [2009/03/18(水) 22:07:03 ] ごめん。 print文かwrite文か、また出力並びをfとするか(f(i),i=1,imax)とするかで、 出力結果が違うのかと思ってやってみたが、違いはないっぽい。 というわけで、>>524 をもっとすっきりさせた。 integer::i real(8)::f(3) do i=1,3 ; f(i)=i ; enddo print *, "write(*,*) f" write(*,*) f print *, '---' print *, "write(*,'(f)') f" write(*,'(f)') f print *, '---' print *, "write(*,'(f\)') f" write(*,'(f\)') f print *, '---' print *, "write(*,'(f)',advance='no') f" write(*,'(f)',advance='no') f print *, '---' end
527 名前:デフォルトの名無しさん mailto:sage [2009/03/18(水) 22:19:08 ] ↑の結果 write(*,*) f 1.00000000000000 2.00000000000000 3.00000000000000 4.00000000000000 5.00000000000000 --- write(*,'(f)') f 1.0000000000000000 2.0000000000000000 3.0000000000000000 4.0000000000000000 5.0000000000000000 --- write(*,'(f\)') f 1.0000000000000000 2.0000000000000000 3.0000000000000000 4.0000000000000000 5.0000000000000000 --- write(*,'(f)',advance='no') f 1.0000000000000000 2.0000000000000000 3.0000000000000000 4.0000000000000000 5.0000000000000000 --- 結論 @書式省略すると、適当な位置で改行してくれる(規格で決まってるんかな?) A書式指定すると、書式の中身が終わる度に改行 B書式に\を付けると改行抑制 C書式にadvance='no'(デフォルトはyes)を付けるとwrite文が終了したときに行う改行を抑制(Aとの違いに注意) って感じかな。 改行抑制の\と改行指定の/が混ざるとどんな出力になるんだろう。
528 名前:デフォルトの名無しさん mailto:sage [2009/03/18(水) 22:20:24 ] ごめん、>>526 は real(8)::f(3) do i=1,3 ; f(i)=i ; enddo は↓に修正。 real(8)::f(5) do i=1,5 ; f(i)=i ; enddo
529 名前:デフォルトの名無しさん [2009/03/22(日) 01:30:43 ] >@書式省略すると、適当な位置で改行してくれる(規格で決まってるんかな?) コマンドプロンプトの右端で改行だと思う 違うかなー
530 名前:デフォルトの名無しさん mailto:sage [2009/03/22(日) 10:23:20 ] >>529 他のコンパイラでは改行しないので、コンパイラのせいだと思います。 >>524-528 ありがとうございます。 参考になりました。 write(*,'(f\)') f が良さそうですね。
531 名前:デフォルトの名無しさん mailto:sage [2009/03/23(月) 15:14:13 ] >>529 Fortranに限らず、プロンプトのサイズは関係ないよ