[表示 : 全て 最新50 1-99 101- 201- 301- 401- 501- 2chのread.cgiへ]
Update time : 02/14 08:15 / Filesize : 180 KB / Number-of Response : 532
[このスレッドの書き込みを削除する]
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧] [類似スレッド一覧]


↑キャッシュ検索、類似スレ動作を修正しました、ご迷惑をお掛けしました

FORTRAN W



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/


490 名前:デフォルトの名無しさん mailto:sage [2009/02/12(木) 00:23:26 ]
うちの研究室の人たちがFortranでプログラミングしているけれど
お前らgoto使いすぎ・・・
というか自分の提出したプログラムがgoto文に書き換えられている・・・

subroutine、functionを使いすぎるのはスパコン計算に向かないと言っていたけれど
勉強してきた構造化プログラミングの手法自体がfortran向きでないということなの?

491 名前:デフォルトの名無しさん mailto:sage [2009/02/12(木) 02:32:22 ]
>>490
インラインされるようにしろw

コンパイラが安心してグローバル最適化できるように、付加的な情報を与えてやれ。
グローバルな構造が人間が見て分かりやすいならコンパイラも見て分かりやすい。

INTENT指定はつける。
FUNCTIONは、PURE (可能ならELEMENTAL)にする
とかすればDO..LOOP内で関数呼び出しとかしても並列化やベクトル化してくれるはず。
コンパイラによるが。

実際にベンチマークを取って、自分が勝利すれば、後は文句いわれないべw


492 名前:デフォルトの名無しさん [2009/02/12(木) 12:52:18 ]
>>491
intent属性つけると微妙に速くなるよね。
特にloop内で頻繁に呼ばれるやつだと全体で5から20%くらい違ってくる。
最近のコンパイラはF77で書いててもintentをわかってくれるから楽だ。

で・・・・pure,elementalの事はよくわからないので詳しく!

493 名前:デフォルトの名無しさん mailto:sage [2009/02/13(金) 00:04:13 ]
>>492
PUREもELEMENTALもFortran95で導入されたキーワードで、関数やサブルーチンの
副プログラムの性質をコンパイラに教える修飾語。

PURE FUNCTION unko(x) などのように宣言の頭につけて使う。

PUREというのは、大雑把には副作用がないこと。それゆえ、並列に動作させても
値が変わらないので、コンパイラは並列化など最適化をやれる。
(PUREを満たさねばならない条件はいくつかあるので、kwskはマニュアル見てくれ)

ELEMENTALはPUREの中でさらにいい性質を持ったもの。
本来は1変数で定義してあっても、配列を引数にとって、配列を返すように使ってもいいもの。

たとえば、
REAL :: a(10), b(10)
b = SIN(a)
こういう使い方が組み込み関数では出来るわけだが、自作の関数でもこうやって使っても
いい場合にELEMENTAL (要素毎の意味) をつける。 

これもコンパイラが利口なら、最適化をかけてくれるはず。

普通、DO..LOOP内に関数やサブルーチンの呼び出しがあると、呼び出し先で何が
あるかわからないので、最適化が抑止されるが、PUREやELEMENTALがあれば、
安心してコンパイラが最適化できる。(原理的にはw)



494 名前:デフォルトの名無しさん mailto:sage [2009/02/13(金) 08:29:24 ]
>>493
ありがとう。pure 属性は使い易そうだ。

495 名前:494 mailto:sage [2009/02/13(金) 11:01:13 ]
loop内で頻繁に呼ばれる4個つくらいの function や subroutine に pure 属性つけただけで
並列(OpenMP)の時にちょびっと速くなった。わーい。
もともとdo-loopで一つずつ処理しているので elemental を使える状況は少ないけど、
もう少し理解してから使ってみよう。
inlineを少し深くするようになったからかコンパイル時間がすこし長くなったけどまあ気にしない。

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に限らず、プロンプトのサイズは関係ないよ






[ 新着レスの取得/表示 (agate) ] / [ 携帯版 ]

前100 次100 最新50 [ このスレをブックマーク! 携帯に送る ] 2chのread.cgiへ
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧]( ´∀`)<180KB

read.cgi ver5.27 [feat.BBS2 +1.6] / e.0.2 (02/09/03) / eucaly.net products.
担当:undef