5ちゃんねる ★スマホ版★ ■掲示板に戻る■ 全部 1- 最新50  

■ このスレッドは過去ログ倉庫に格納されています

くだすれFORTRAN(超初心者用)その4

1 :デフォルトの名無しさん:2009/01/24(土) 18:32:01
このスレッドは、他のスレッドでは書き込めない超低レベル、
もしくは質問者自身何が何だか分からない質問を勇気を持って書き込むスレッドです。
FORTRAN使いが優しくコメントを返しますが、
お礼はFORTRANの布教と初心者の救済と次期Fortran2008規格でのCOMEFROM文採用をお願いします。

●注意事項
・質問する前にGoogle等の検索サイトで検索しましょう。
・回答者にわかりやすい様に、質問内容はできる限り詳しく書きましょう。
・エラーの場合は起きた状況、環境(OS・コンパイラ・バージョン)、エラーメッセージも詳しく書きましょう。


●前スレ
くだすれFORTRAN(超初心者用)その3
http://pc11.2ch.net/test/read.cgi/tech/1196384126/

くだすれFORTRAN(超初心者用)その2
http://pc11.2ch.net/test/read.cgi/tech/1164121236/

くだすれFORTRAN(超初心者用)
http://pc8.2ch.net/test/read.cgi/tech/1138063703/


●関連スレ
FORTRAN W
http://pc11.2ch.net/test/read.cgi/tech/1163319215/


2 :デフォルトの名無しさん:2009/01/24(土) 21:22:49
>>1
スレ立て乙です

3 :デフォルトの名無しさん:2009/01/25(日) 21:38:41
気象庁とかが推奨している、配列の代入にコロンを明示する方式でのスピード低下率の
まとめがあった。

ttp://www.ifremer.fr/ditigo/molagnon/fortran90/f90col.html

たとえば、以下のような場合

CALL( A )

CALL( A(:) ) −> ALLOCATE( TMP(SIZE(A)) ) ; TMP = A ; CALL (TMP) ; A = TMP ;DEALLOCATE(TMP)

ソースの意味的には同じだが、下の書き方だと、コンパイラが一度テンポラリに
Aの中身をコピーしてテンポラリを読んだりする実装がされたりする。

最近は少し賢くなったようだw

4 :デフォルトの名無しさん:2009/01/26(月) 01:32:56
それ最近の記事?

5 :デフォルトの名無しさん:2009/01/26(月) 06:57:57
へ〜
allocateして動的にメモリの空きを探して確保してコピーして、って
素で考えると手間がかかるだけな気がするけど、わざわざそうするということは
何か別な利得が発生するのかな?

6 :5:2009/01/26(月) 06:59:41
allocateして、は消してね。
a(:)が添字範囲全部の場合も、一部だけの場合でも両方対応するようにしたけど、
範囲全部の場合だけ別にする事を忘れただけなのかな?

7 :デフォルトの名無しさん:2009/01/26(月) 12:03:14
その記事は古いアルよ。
出ているコンパイラやOSを見る限り。

8 :デフォルトの名無しさん:2009/01/26(月) 16:23:18
じゃ、今は気にせんでおkってことね?

9 :デフォルトの名無しさん:2009/01/27(火) 21:09:52
do I = 1 , N
if(条件式) then
endif
done



do I = 1 , N
if( ! 条件式) cycle
done

は、やってることは等価だけど、速さも同じ?

10 :デフォルトの名無しさん:2009/01/28(水) 00:00:36
両方コンパイル時に止まるから速さも同j(ry

まあ、コンパイラにもよるから自分で試してみてくれ。

11 :デフォルトの名無しさん:2009/01/28(水) 01:53:01
最近大学でfortranを使い始めたのですが、インテルMKLを使うときはコンパイル時に
「ifortl」というコマンドを使うように指示されたのですがうまくいきません
どなたかわかる方いらっしゃいませんでしょうか?

環境は
OS Linux バージョン不明
コンパイラ Intel Fortaran 10.0
MKL Intel MKL9.1
コンパイラの購入時に「ifortl」コマンドを使うと自動でMKLのリンクが張られる〜
のような説明を受けたらしいのですが、使用すると引用したモジュールが見つかりません
という旨のエラーメッセージがでます。
リンクオプションをきちんと記述するとコンパイルできます
MKLへのリンクの環境変数が通っていないんだと思うのですが、
設定方法がわからない状態です

12 :9:2009/01/28(水) 02:42:17
>>10
>両方コンパイル時に止まるから速さも同j(ry
意味わからん。文法ミスって意味?
普通に使えてるんだが

13 :デフォルトの名無しさん:2009/01/28(水) 02:49:33
>>11
ウチのIntel Fortran 11.0 x86_64版には"ifortl"なるコマンドはないし、
ちょっとググってもそれらしい物はヒットしない。
とりあえず

file `which ifortl`

で ifortl の位置と種類を確認して、シェルスクリプトか何かなら

cat `which ifortl`

で中身を確認、書き換えられそうなら自力で修正
という感じで。

14 :デフォルトの名無しさん:2009/01/28(水) 03:00:18
>>11
「ifort」の間違いってオチじゃないよね…

15 :デフォルトの名無しさん:2009/01/28(水) 09:59:39
教官殿が気を利かせてMKLライブラリリンク用のを作ってくれたのかも知れんね。
13の通りwhichしてその内容をさらしてみるべし。

16 :デフォルトの名無しさん:2009/01/28(水) 10:00:09
MKLライブラリ、って書き方はおかしかったな・・。

17 :11:2009/01/28(水) 12:33:23
>>13->>16
ありがとうございます、無事解決できました。
>>15
まったくその通りでした
うっかり「ifortl」という隠しコマンドでもあるのかと思ってました。
リンクを張ったつもり〜でしたが、実際は一部しか張ってなかったです
それにしてもなんというゆとりコマンド・・・

18 :デフォルトの名無しさん:2009/01/28(水) 12:45:50
そーいう余計なことは正直やめてほしいよなぁw

19 :デフォルトの名無しさん:2009/01/28(水) 17:55:31
ちょっと年代ものの他人が書いたf77のコードなのですが、

FW=CB(2)-CB(1)  //計算領域の幅を算出
CW=FW/NCX //幅をセル数で割ってセルの幅を算出

となる部分で、FWが1.33、NCXが200で、CWが6.65E-03となるはずが、
なぜか6.6500003E-3となっています。ちなみにFWはここで突如出現、
それ以外は特に型の宣言無くCOMMON文の中で定義されています。
何となく型の宣言が問題のような気がするんですが、原因と解決法
(ぴったり6.65E-3にしたい)を教えていただけませんか?

20 :19:2009/01/28(水) 18:05:01
あ…すいません、FWもCOMMON文中に定義してありました。

21 :デフォルトの名無しさん:2009/01/29(木) 01:01:07
>>19
単精度なら有効桁からいって7〜8桁目にゴミが出てもおかしくない。
ゆえに気にするな。

フォーマットを与えずに*で書かせれば、自動的に精度の範囲内で出力するので
ゴミは見えなくなるだろう。フォーマットは浮動小数点での表現を単に何桁でも
十進法に直して書くだけだから、単精度でもF30.20とか書けば小数点以下20桁とか
書いてくれるが、有効数字的には6〜7個しか意味ない。



22 :19:2009/01/29(木) 09:49:23
>>21
回答ありがとうございます。なるほど、7〜8桁目は有効数字外なんですね。
実害があってですね、粒子の位置の判定ををするとき、粒子の位置Xを
セルの幅CWで割って、

LCX=(X/CW)+0.999999 //Xが3.5、CWが1だとすると4.499999、整数に代入して4で4番目のセルに入る

みたいな処理があるんです。このとき、CWがずれてるとセルナンバーが大きいところだと、
想定外の変なセルに入っちゃう粒子が増えてきます。でも有効数字の問題だとすると、倍精度にしたとしても、
頻度は減るにせよ、根本的解決ではないってことになりますね?やっぱりこの処理自体に問題があるんでしょうか?
問題があるとしたらどういう方法にするべきでしょうか?

23 :デフォルトの名無しさん:2009/01/29(木) 10:17:31
小数点捨てにしよ四捨五入にせよ、数値誤差や丸め誤差やら打ち切り誤差で致命的に
結果が変わるようなモデルが悪い。そんなの窓から投げ捨てちゃえw

24 :23:2009/01/29(木) 10:25:56
とはいっても粒子数がいっぱいあれば、離散化した箱の中の数が一個二個違うくらいではそんなに
変わらないだろうな。同じ問題は倍精度にしてもたぶん起こるよ。いまのCPUは単精度と倍精度で
ほとんど計算コストが変わらないので気が向いたら倍精度でやってみよう。

25 :デフォルトの名無しさん:2009/01/29(木) 11:05:29
>いまのCPUは単精度と倍精度でほとんど計算コストが変わらない
ほんとに?!
普通に考えれば倍精度になればデータが倍になるから、スピードは半分になるような
その辺考えてあえて倍精度じゃなく単精度を使ってるコードもあるじゃん

26 :デフォルトの名無しさん:2009/01/29(木) 11:33:48
>>25
いまの計算機ってメモリ・CPU間のデータ転送をクレバーに
さばくからあまり目立っては違わない。
ほとんど変わらないとは思わないけどコードにもよるけど
単精度でしても2割速くなれば御の字じゃないかな。
メモリ節約して粒子数なり格子数を増やす方にメリットがあると
当然単精度でするだろうけど。仮に2倍速になるにしても、
高々2倍のスピードを求めてあえて単精度で計算する、
というのは何か間違っていると思うよ。

27 :デフォルトの名無しさん:2009/01/29(木) 12:04:26
ディスクアクセスが非常に多い場合はそこでのロスを減らすために
単精度ですることは良くある
たくさんの測定データを読み込んで処理するときとかは特に
測定値だと元から倍精度の精度はないし

28 :デフォルトの名無しさん:2009/01/29(木) 13:25:25
>>22
はじめに一言。
四捨五入をしたいだけなら、NINTという関数があるのでそれを使うとよい。

ただNINTを使っても、十進表記にこだわると、今回の問題は解決しないかもしれない。
その理由を簡単に言うと以下のようになる。

Fortranでいうところの実数は、数学的な意味での実数ではない。
いわゆる浮動小数であって、有限個の有理数点で実数を代表させている。
ある種の区間をあらわす代表の数である。

その区間は、二進数表記で区切りのいい点で切っているので、十進数表記では
切りのいい点になっていない。

十進数で四捨五入しようとしても、そもそも閾値に幅があるのだから、その幅分の誤差が
出てもしょうがない。単精度ではそれが、有効数字7〜8桁目にくる。

数直線をかみそりで切り分けるイメージではなく、木材をのこぎりで切るイメージで
考えればおk。切るとき、おがくずが出て、切った材木にはのこぎりの歯の幅だけの誤差がでる。
それは避けられない。









29 :デフォルトの名無しさん:2009/01/29(木) 15:08:31
>>26
クレバーってどういう意味?データ転送のレイテンシ隠蔽をがんがってくれるって意味?
普通のアプリでは役に立つけど、数値計算のようなデータを単純にガバガバ読むプログラムじゃ
そういうテクの恩恵はあんまないでしょ。
メモリから演算器へ転送するデータ量が単純に倍になるんだから・・・

30 :デフォルトの名無しさん:2009/01/29(木) 15:30:11
違いは計算のコードや計算機の種類によりそうだけどね。
ベクトル化をすごく気にしたコードとか
一つのループを短くしたコードだとデータ転送の頻度がたぶん
すごく高いから29の通り単精度倍精度の違いは大きいだろう。
ループを細切れにせずに一つのループ内でながめな処理をするタイプだと
計算中に次に使うデータを取ってきたり更新の済んだ分をメモリに戻す暇が
出来そうだ。

31 :デフォルトの名無しさん:2009/01/29(木) 15:56:06
非線形系だと誤差って結構重要なんだよね
簡単に見えて意外に厄介

32 :デフォルトの名無しさん:2009/01/29(木) 16:36:30
>>31
んだ。超厄介
>>30
キャッシュ内ですっぽり収まる程度の長さのループなら
ループの頭でlocalな変数に大配列の一部を複写してからの方が
編集やバグ探しが楽になるからまあ良いんだけど。
いまはだいぶ楽ちんだけど、ちょっと前はある長さを境にして
ガクンと遅くなることがあったな。他人のコードってあんまり見た
こと無いから判らないけど,ループは長いor短い方が良い、
とかtemporalな変数にうつすor大きい配列をガンガン右辺に持ってこよう、
とか、今の流行というか推奨はどっちなんだろう。

33 :19:2009/01/29(木) 17:45:46
なるほど…ひとまず倍精度にしてみてどれくらい遅くなるか
見てみることにします。情報を小出しにしちゃって申し訳ないんですが、
一番問題なのは、上の処理をすると、領域ぎりぎりに粒子があったとき、
50までしかセルがないのに51セル目を見ようとしちゃうことですね。
このエラー自体が不可避ならとりあえずそこの例外処理だけは入れといたほうがよさそうですね。
いろいろありがとうございます。上記件について何かいいアイデアあればぜひ。

34 :デフォルトの名無しさん:2009/01/29(木) 23:00:06
>>33
50セルがMaxなら、いったん10000倍なり拡大して整数に入れて、その整数の世界で
切り分ければいい。

整数がオーバーフローすると問題だが、50セルがMaxなら大丈夫だろう。


35 :デフォルトの名無しさん:2009/01/30(金) 00:07:25
分からないので質問させてください。
拡大係数行列Pに対して、部分ぴぼっと選択と行基本変形を繰り返して、
ガウスの消去法をするプログラムを書きました。

ここでPのある縦列が全て0のとき、たとえぴぼっと選択していても、
(*)のところで0の割算が出てしまいます。
これを回避するうまい方法or常套手段はありますか?



36 :35:2009/01/30(金) 00:07:53
! Searching the factor and its location which held the maximum number in a column j
do j = 1,sizeN
ValMax = 0.0d0
ImaxHeld = 0
do k = j, sizeN
if( ValMax < abs( P(j,k) ) )then
ImaxHeld = k
ValMax = abs( P(j,k) )
end if
end do
write(*,*) 'ImaxHeld=', ImaxHeld, 'ValMax=', ValMax

! Two rows are exchanged so that the maximum factor is placed at a diagonal
tmp(:) = P(:,j)
P(:,j) = P(:,ImaxHeld)
P(:,ImaxHeld) = tmp(:)

! Now the diagonal factor P(j,j) is a pibot
P(:,j) = P(:,j) / P(j,j) ! <=(*)
do i = 1, sizeN
if (i /= j) then
P(:,i) = P(:,i) - P(j,i)*P(:,j)
end if
end do
end do

37 :デフォルトの名無しさん:2009/01/30(金) 01:55:43
>>35
一列全部0なら、シンギュラーな行列なんだから、そもそも解が無いだろ!

線形代数の教科書を100回読み直せ!w


38 :デフォルトの名無しさん:2009/01/30(金) 07:23:57
pivot?

39 :35:2009/01/30(金) 11:25:16
そうでした。すみません。
『行列式も0になって、クラメールも使えなくてどうしよう』などと考えてしまいました。

やりたいことは最小二乗法の正規方程式を解くことなのですが、問題は
データの与えかたによって、解が有ったり無かったりする
(列が全部0になったり、ならなかったりする)事です。

こんなとき、システマティックにやる方法はありますか?

40 :35:2009/01/30(金) 11:31:51
今見直したら、最小二乗法で与える近似関数として、
間違ってsin(0)を与えていたために係数行列の列が全て0になっていました。

>>37さんありがとうございました。

41 :デフォルトの名無しさん:2009/02/07(土) 00:28:19
CrayがFortran2003完全対応のコンパイラをリリースしたらしいな。

ついでにFortran2008にも部分対応らしいな。
といっても、CoArrayはもともとCRAYがやっていたので当然なんだが(笑


42 :デフォルトの名無しさん:2009/02/07(土) 02:48:21
caryってまだ生きてたんだ・・・

43 :デフォルトの名無しさん:2009/02/07(土) 11:42:24
>>42
Crayはここ10年くらいのアメリカの護主義のおかげで復活してる。
一時期の低迷は脱している。


そういえば、東工大のつばめに刺さっていたクリアスピード社が、イギリスの経済壊滅の
余波で株価急落、資金繰りにもつまってきたというニュースが先週流れてきてた。
ETA10の夢ふたたびw



44 :デフォルトの名無しさん:2009/02/07(土) 16:20:54
この不況でスパコン業界の勢力図も相当変わるだろうな

つーかCrayってもう石は作ってないんだよな?
その他大勢の単なるシステム屋さんに成り下がっちまった

45 :デフォルトの名無しさん:2009/02/07(土) 22:16:59
>9

アセンブルコードを吐かせてサイズを比較しろ

46 :デフォルトの名無しさん:2009/02/08(日) 07:53:42
>>9
1CPUなら後者が速いことが多い・・・とおもう。
並列だとたぶん前者・・・とおもう。並列処理すると代償でマスキング処理が抑制されることがあるから。
個人的にはif-endifで処理しない・する範囲を明示する方が好き。

47 :デフォルトの名無しさん:2009/02/08(日) 16:14:46
if文の行うマスク処理って、ベクトル処理のときの話じゃない?
違ったらごめん

48 :デフォルトの名無しさん:2009/02/08(日) 18:01:42
超初心者で恥ずかしながらご質問させていただきます。Compaqのvisual fortranを使ってます。
先輩からいただいたプログラムのファイルは2つあり、ひとつが本プログラム、もうひとつがサブルーチンプログラムです。
この状況で、もうひとつのサブルーチンプログラムをworkspaceのところで作成し、compile、excecutionをしたのですが、
どうもerrorなどはないのですが、write文などの結果が既存のサブルーチンプログラムからの結果が出力され、
新しいプログラムでの結果が出力できません。どうやったら、新しいプログラムの結果が
出力できるのか、教えていただけますでしょうか。
大変、初心者の質問で申し訳ございません。

49 :デフォルトの名無しさん:2009/02/08(日) 18:08:07
↑ちょうど友達から電話があり、教えていただきました。どうもご迷惑をおかけいたしました。
無視してください。また、お世話になるかと思いますが、どうぞよろしくお願いいたします。

50 :デフォルトの名無しさん:2009/02/08(日) 19:23:15
>>47
あってるよ。
でも並列処理するときに誤作動防止で
ベクトル処理を抑制することがあるというのはありそうではある

51 :デフォルトの名無しさん:2009/02/10(火) 15:42:39
MKL(というかライブラリ一般)の使い方を初心者に解説してるサイトや本ってありませんか(英語可)
Matlabから移行してきたんですが、公式マニュアル見てもプログラミング関係の単語がわからずで。ラッパーとか。
数値計算に関しては、噂に聞いてたよりも使いやすいなあ、と思ってるんですが。
よろしくお願いします

52 :デフォルトの名無しさん:2009/02/10(火) 17:32:15
gfortranでコンパイル時、下記のエラーが発生して困っています。

gfortran -i8 '-mcmodel=medium' -fdefault-integer-8 -O2 -mtune=opteron -m64 -c hoge.f
In file hoge.f


 C(1) = LShift(I1,32).or.(I2.and.NM32)
              1
Error: Operands of logical operator '.and.' at (1) are INTEGER(8)/INTEGER(8)

似たような問題を見つけましたが、対処方法がよく分かりません。
ttp://gcc.gnu.org/ml/fortran/2005-07/msg00416.html

どなたか教えて頂けないでしょうか。

ENV: RedHat 4, GCC 4.1.2


53 :デフォルトの名無しさん:2009/02/11(水) 00:36:13
>>52
何をしたいのか、それだけでは意味不明だが、『hoge』などというUNIX系の方言を
しゃべるところを見ると、C言語とかと混同して論理演算とビット操作を勘違いしていると邪推?

> C(1) = LShift(I1,32).or.(I2.and.NM32) 
(LShift という関数は、Fortranの標準関数には存在しない。が、ベンダー拡張の
ビット操作演算子としてよく存在しているので、ビット操作演算子だと仮定する。)

これは、論理演算とビット操作と論理演算を混用しているので、コンパイラが怒っていると
思われる。

正しくは、
INTEGER(8) :: i1, i2, nm32
INTEGER(8) :: ic(整数)

ic(1) = IOR( ISHFT(i1, 32), IAND(i2, nm32) )

Fortranには、論理型と整数型の区別がある。 .and. や .or. は論理演算子であって
真偽の二値しかもたない論理型の変数(あるいは定数)に作用する。

一方、整数型の変数(や定数)に対するビット演算子も存在している。
それは二引数をとる関数で IAND や IOR、あるいはビットシフト演算子 ISHFT である。


cを整数として使うのは、暗黙の型に反するので、どうしてもと言う理由がなければ
やめたほうがいいと思う。

なお、Fortranの論理変数の内部表現は規格では不定であって、処理系によってことなる。
一般的にLSBが1か0かで真偽を区別していることが多い。
C言語のように0が偽で、その他が真というわけでない。
よって、論理演算を行ってもLSBしか変化していなかったりする。
しりたければEQUIVALENCEをかけるか、TRANSFER関数で内部表現を見れば分かる。

54 :デフォルトの名無しさん:2009/02/11(水) 10:15:01
>>53
的確かつ詳細な回答有り難う御座います。大変参考になりました。
お察しの通りC言語の経験者ですが、Fortranは皆無です。
ご指摘を参考に勉強致します。有り難う御座いました:-)


55 :デフォルトの名無しさん:2009/02/15(日) 15:04:38
Intel Visual Fortran の update 通知が来てたけど、F2003対応は進展したかい?


56 :デフォルトの名無しさん:2009/02/16(月) 22:01:19
FORTRANのG77をダウンロードしたいのですが、よくわかりません。
Vistaに対応した無料FORTRANが出来るようになるサイトを教えてください。
申し訳ありませんが、よろしくお願いします。

57 :デフォルトの名無しさん:2009/02/16(月) 23:42:15
>>56
http://pc11.2ch.net/test/read.cgi/tech/1163319215/2

58 :デフォルトの名無しさん:2009/02/17(火) 11:11:13
>>56
俺的にこれがお勧め
ttp://www.download.com/Silverfrost-FTN95/3000-2069_4-10491439.html
Plato3と言うソフトが一緒にインストールされるから、それを起動して
File->Newもしくは左上の白いアイコンをクリックするとNew Fileと言うウィンドウが出る
FORTRAN77のコードを書きたいならFixed Format Fortran fileを
Fortran90/95のコードを書くならFree Fomat Forrtran fileを選択しOpenボタンを押す。
あとはコードを書いて、左上に青い再生ボタンがあるのでクリック、変なダイアログが出ても
OKおせばおk。あと、黒いウインドウを閉じる時は、右上の×じゃなくて、キーボードの
Enterを押さないと落ちる事があるので注意

59 :デフォルトの名無しさん:2009/02/19(木) 17:28:26
Intel Fortran11が出たけど、初物には飛びつかんほうがいいかなーやっぱ

60 :デフォルトの名無しさん:2009/02/19(木) 18:30:00
そういえばWindows XP SP3の対応って11からだっけ?>Intel Fortran

61 :デフォルトの名無しさん:2009/02/19(木) 19:56:36
>>55
bug fixが中心だろう
Memory allocation error in for_array_copy_in()
とか
11.0 message catalog produces garbled messages with Japanese compiler
とかあったから、とりあえず入れといた

62 :デフォルトの名無しさん:2009/02/19(木) 23:33:41
IntelFortran6.0使ってたんだけど、
11.0でコンパイルしなおしただけで計算時間が1/3になってワロタ
別に最適化オプション何も使ってないデフォルトなんだけどな
これでOpenMPで最適化したら一体どうなるんだ

63 :デフォルトの名無しさん:2009/02/20(金) 04:02:32
>>61
黒カエラーはまだ直ってないなw
誰もIntelに通報してないのか?


64 :デフォルトの名無しさん:2009/02/20(金) 13:43:56
>>62
7になった時にですごく良くなった気がする。
あとはあまり変化は大きくない気がする。
・・・といって今使ってるのが9のままなので10,11でまた進歩があったのかな?
SSE絡みでは順次良くなったそうだけど
明示的にそれを使うことは少ないからなあ。

65 :デフォルトの名無しさん:2009/02/20(金) 14:23:19
DECのエンジニアが入ったのが7からだっけ?
見違えるように良くなったって話だが

66 :デフォルトの名無しさん:2009/02/21(土) 00:20:22
昔のはVisualC++へのプラグインだったからなぁ。


67 :デフォルトの名無しさん:2009/02/21(土) 10:32:37
つまらないことなんですけど
みなさんはエラー系の出力はwrite(0,*)を使っていますか?
それとも、標準出力もエラー出力も全部print *を使っていますか?

68 :デフォルトの名無しさん:2009/02/21(土) 19:42:57
>>67
標準出力とエラー出力があるっていうのはUNIXの話だから、
メインフレーム上がりでUNIXをおもちゃと馬鹿にしているおっさんたちは、
そんなもの存在も知らず、相変わらず6番に出力していると思う。



69 :デフォルトの名無しさん:2009/02/22(日) 00:56:09
program mtest
integer, allocatable :: imem(:)
msize = 1000*1000 * 200
call alloc4i(imem, msize)
c :
stop
end

subroutine alloc4i(imem, msize)
integer, allocatable :: imem(:)
if ( .not. allocated(imem) ) then
allocate( imem(msize), stat=ier )
if (ier .ne. 0) stop
else
stop
endif
return
end

こんな感じでメモリ割付をするサブルーチンを作りたいのですが、サブルーチン側の
配列宣言でコンパイルエラーになってしまいます。このように親側でallocatableにした
配列は、サブルーチン側でどのようにallocateするのでしょうか?

70 :69:2009/02/22(日) 00:57:29
>>69
先頭のスペースが全て削除されてしまったようです。
c: の行は無視してください。

71 :デフォルトの名無しさん:2009/02/22(日) 01:47:54
>>69
外部サブルーチンだからエラーが出んじゃない?
内部サブルーチンやモジュールで使ってるけど
エラーは出ないよ

72 :69:2009/02/22(日) 02:58:23
>>71
program memtest
integer, allocatable :: imem(:)
msize = 1000*1000 * 200
call alloc4i
stop

contains
 subroutine alloc4i
  if ( .not. allocated(imem) ) then
   allocate ( imem(msize), stat=ier )
   if (ier .ne. 0) stop
  else
   stop
  endif
  return
 end subroutine
end program

レスどうもです。こんな感じでしょうか?
たしかにコンパイルは通りました。ただ、ライブラリ化
したいため、分割コンパイルしたいのです。何とか
外部プログラムで実現できないでしょうか・・・


73 :デフォルトの名無しさん:2009/02/22(日) 04:39:47
>>72
MODULEに入れるか、本体側でINTERFACEを書けばいいんでね?

ALLOCATABLE属性をつけても、77式に裸にしておくと、引数がマッチしているのか分からんから
怒られるんだと思うが。




74 :69:2009/02/22(日) 09:30:19
>>73
module malloc
 integer, allocatable :: imem(:)
 contains
  subroutine alloc4i(imem, msize)
  integer::imem(:)
  integer::msize
  allocate ( imem(msize), stat=ier )
  if (ier .ne. 0) stop
  return
  end subroutine
end module
program memtest
use malloc
 integer::msize
 msize = 1000*1000 * 200
 call alloc4i(imem, msize)
stop
end program

う〜ん・・・ f90に疎くて、こんなコードしか書けませんでしたorz
ホントは、下みたいな感じで、program側で複数の配列確保に使える
サブルーチンが欲しいのですが・・・

program memtest
  :
 call alloc4i(imem1,msize)
call alloc4i(imem2,msize)
  :


75 :デフォルトの名無しさん:2009/02/22(日) 13:30:21
>>74
やりたいのはこんな感じかな?
MODULE m_test
CONTAINS
subroutine alloc4i(imem, msize)
integer, allocatable, INTENT(OUT) :: imem(:)
integer, INTENT(IN) :: msize
if ( .not. allocated(imem) ) then
allocate( imem(msize), stat=ier )
if (ier .ne. 0) stop
else
stop
endif
return
end subroutine alloc4i
END MODULE m_test

program mtest
USE m_test
integer, allocatable :: imem1(:), imem2(:)
msize = 1000*1000 * 200
call alloc4i(imem1, msize)
call alloc4i(imem2, msize)
stop
end


76 :69:2009/02/22(日) 20:12:35
>>75
レスどうもです。
ズバリ75のコードなのですが、私のコンパイラ(Fortran PowerStation 4.0)ではエラーが出ます。
4行めがイカンと言っているようです。

malloc.f90(4):error FOR3435: symbol IMEM is a dummy argument
- cannot be ALLOCATABLE detected between IMEM and (

文法的には間違っていないと思うのですが・・・
別のコンパイラでも試してみようと思います。
コードの調整までして下さり、本当にありがとうございました。


77 :デフォルトの名無しさん:2009/02/22(日) 23:41:01
>>76
俺のおぼろげな記憶では、ALLOCATABLE な配列をサブルーチン側で ALLOCATE して
返せるようになったのは Fortran95 以降だった気がする。

Fortran90ではPointerでやるんじゃなかったかな?

文法書で確かめてくれw ガセネタだったらすまんこ。




78 :69:2009/02/23(月) 06:31:29
>>77
統合環境のオンラインマニュアルを良く読むと、以下の記載がありました。
 >Remarks
 >You can only use the ALLOCATABLE attribute to declare an array
 > that is not a dummy argument or a function result.

不注意でしたorz
どうやら仰る通りのようです。ポインタを勉強したいと思います。

実は、先輩がメインフレームで使っていたコードを引き継いだのですが、昔風のメモリ管理を
していて、ブロック名を直接メモリ域に書き込んだりしていたので、PC上ではコンパイル
出来ずに困っていました。それで、Fortran90を使って書きなおそうと考えた次第です。

重ね々々ありがとうございました。


79 :デフォルトの名無しさん:2009/02/24(火) 00:15:50
>>78
POINTERに直すだけなら簡単。
ただALLOCATABLEに比べて自由度が大きい分最適化やチェックに支障が出るらし。

MODULE m_test
CONTAINS
subroutine alloc4i(imem, msize)
integer, POINTER :: imem(:)
integer, INTENT(IN) :: msize
if ( .not. ASSOCIATED(imem) ) then
allocate( imem(msize), stat=ier )
if (ier .ne. 0) stop
else
stop
endif
return
end subroutine alloc4i
END MODULE m_test

program mtest
USE m_test
integer, POINTER :: imem1(:), imem2(:)
msize = 100*100 * 200
call alloc4i(imem1, msize)
call alloc4i(imem2, msize)
PRINT *, SIZE(imem1), SIZE(imem2)
stop
end

ASSOCIATED だけでいいのか今一自信なし。

80 :69:2009/02/24(火) 07:04:42
>>79
何から何まで申し訳ありません。
コードはコンパイル1発でOKでした。

allocate後は配列と同じように使えるみたいですし、cのポインタより保護されている感が
あっていいですね。危険性に関しては、昔のメモリマネジメントより随分安全と感じますが、
別ルーチンでしっかりチェックするつもりです。

ただ、f90は利用情報が少ないので、少しずつ勉強しながら使って行こうと思います
(周りに利用者がいない。f77かcかVB)。特にPCの処理系では、方言等ありそうですね。
規格にも目を通したいと思います。

色々とありがとうございました。


81 :デフォルトの名無しさん:2009/03/11(水) 02:17:57
モジュールで宣言した変数って自動的にsaveになるんですか?

82 :81:2009/03/12(木) 21:16:17
すいません。>>81は勘違いでした。

もう一つお聞きしたいんですが、INTERFACEって使ってますか?
外部プログラムを書いてから、また同じようなのをイチイチ書くのは
面倒臭いし、モジュールで全部代用できる気がするんですが・・・。



83 :81:2009/03/12(木) 21:27:41
ちなみに何故>>81で勘違いしたかですが、下のようなテストをしたところ
sub2でもi=1だったので、変数iはsave属性なのかと思ったためでした。
同じモジュール中の変数をuseしたから同じもの(実体)を見てるだけで
あって、save属性が付いているわけではない、が正解でしょうか?

以下、ソース(行頭タブは全角スペースにしてます)
module module0
 implicit none
 integer::i
contains
 subroutine set(j)
  integer,intent(in)::j
  i=j
  end subroutine
end module

subroutine sub1
 use module0
 call set(1)
 print *, 'in sub1 : i=' , i
end subroutine

subroutine sub2
 use module0
 print *, 'in sub2 : i=' , i
end subroutine

program main
 call sub1
 call sub2
end program

84 :デフォルトの名無しさん:2009/03/13(金) 08:47:00
>>83
変数のスコープや寿命について勉強してみてはどうかな?

85 :デフォルトの名無しさん:2009/03/13(金) 13:10:10
>>82
interface は使わないで済む事が多いよね。
pure 属性つけたサブルーチン内で
pure 属性つけたサブルーチンを呼ぶ時には
interface で前もって教えておかないとintel fortran に怒られるようなので
使うけど。これも多分使わないですむやり方がありそうな気もする。
>>83
愛が・・・

86 :83:2009/03/13(金) 14:02:12
どうもmoduleのuseを、Cでいうクラスのインスタンス生成みたいに
考えてたのが混乱の原因だったようです。

で、結局>>83の理解は間違っていますか?
教科書にモジュール変数をグローバル変数とする場合はsaveを付けろと
あるんですが、実際>>83のmodule0のiにsaveを付けても付けなくても、
module0をuseしたプログラムでiの値を確認すると、値が保持されているようです。

87 :デフォルトの名無しさん:2009/03/13(金) 22:22:24
>>86
教科書に書いてることは正しい。
Fortranの規格からすると、Module変数はSAVE属性は無い。
Fortran Handbook なんかにもわざわざ書いてある。

本来の規格の上では >>83 でiが消えてもいいように思う。
NAGあたりの規格への忠実さを目指したコンパイラで試してみればいいのではないかと思う。

>>82
INTERFACE は、ソースが無くてバイナリ-だけで配られているような、
ライブラリを呼ぶようなときに必要になるもんだと思う。
ソースが揃っているなら、Moduleにまとめておけばおk?



88 :85:2009/03/14(土) 03:06:21
>>87 の後半
正統なFortranではOKとおもう。が、
ソースが揃ってるか一つのファイルにまとまっているなら interface文は無くてもいい子・・・
と思ってたらifortは文句行ってきた・・。まあ害が無いなら、interface を呼ぶ側でぺたぺた
使ってもいいと思う。
呼ばれるサブルーチンの頭の部分を変更した時に、呼ぶ側全部でそれを意識していたかを確認できるし。
手間が増えるだけな気もするけど、勘違いやバグ防止の対価と思えば高くもない、かな。

89 :デフォルトの名無しさん:2009/03/15(日) 02:09:34
>勘違いやバグ防止の対価と思えば高くもない
たしかにそうね
先人が書いた得体の知れないFORTRAN77な外部副プログラムを安全に呼ぶために使う、とか

つーかinterfaceって名前が、javaやc#と意味が全然違くて紛らわしいというか、いまいち気に入らんw

90 :83:2009/03/15(日) 20:19:01
>>87
>本来の規格の上では >>83 でiが消えてもいいように思う。
とすると、>>83は実際には規格外の動作ということですか?
コンパイラはIntel Fortran 10.1です。(確かにintelはけっこう拡張してるからなぁ・・・)

メンバ変数みたいな真似をmoduleでやらせようかと思ってたんですが、
この方法じゃ駄目ぽいですね。そういうオブジェクト指向的なことって
Fortran2003をちゃんと勉強すればできるのかしら・・・?

91 :デフォルトの名無しさん:2009/03/16(月) 22:18:43
サブルーチンがたくさんあるプログラムを作る時はmoduleよりもinterfaceの方が良いですか?
module間で相互にmoduleを参照(use)するとエラーが出て、悲しい状態です。
誰か教えてください。
ちなみに、moduleについて詳しく書いてある本があればそれも教えてください。

92 :デフォルトの名無しさん:2009/03/17(火) 03:15:21
そのエラーがどんなものか分からないことには何とも・・・

確かにmoduleはよく考えて使わないと面倒な目に合うな
個人的にはFortranやるなら、あんまり細かく部品化しすぎないほうがいいと思う

93 :デフォルトの名無しさん:2009/03/17(火) 06:23:06
>>91
module の前方参照のみしか許していないコンパイラーが多いよね。
ソースの前方に書いたmodule だけをuse するようにしてごらん。

94 :デフォルトの名無しさん:2009/03/17(火) 14:24:33
>>91
コンパイラは何?

95 :91:2009/03/21(土) 12:36:18
返事遅くなりました。すんません。
>92
サブルーチンは使いまくってます。
サブルーチンがないと不便です…。
>93
前方参照はmoduleをprogramより前に書けってことですよね?
moduleは別ファイルです。こんな感じになってます。
ファイルa.f90
module a
use b
contains
subroutine foo
...
end module a
ファイルb.f90
module b
use a
contains
subroutine bar
...
end module b
わかりにくい質問ですんませんでした。
>94
コンパイラはifort(ver.11)です。

inteface使えよって意見は出ないもんなんですね。
みなさんはサブルーチン使うとき、どうやってるでしょう?

96 :デフォルトの名無しさん:2009/03/21(土) 19:50:38
>>91
>module間で相互にmoduleを参照(use)する
相互にuseするのって不可能じゃないの?
コンパイルするときにuseするモジュールの.modファイルが必要だし。
というか、fortranに限らず相互に呼び合うようなのは概念的に許されるのかな・・・?
もし許されるとしても、混乱の元だろうし非常にまずいような・・・・


>inteface使えよって意見は出ないもんなんですね。
>みなさんはサブルーチン使うとき、どうやってるでしょう?
interfaceの主な用途としては、fortran77で書いた外部サブルーチンを
そのままいじらずに、より安全に使いたいとき、などじゃないかな。
形状引継ぎ配列や割付け配列などの機能を使いたいときは、
いずれにしろそのサブルーチンの修正が必要になるので、そのときは大人しく
モジュールで囲ってモジュールサブルーチンに変更すべきかと思うが。

97 :91:2009/03/22(日) 10:19:29
>>96
ありがとうございます。
相互に呼び出さないようにするためにはツリー構造を考えないといけないですね。
ちょっと面倒くさい気がします。

98 :デフォルトの名無しさん:2009/03/23(月) 20:26:55
結局>>91のエラーは解決したの?

99 :91:2009/03/24(火) 08:27:42
相互参照しないように書けば、エラーは消えます。
ただ、皆さんがどういう風に対応してるのか知りたかったのです。
お相手ありがとうございました。

100 :デフォルトの名無しさん:2009/03/25(水) 12:58:20
>>99
オレ、一個の超特大module にしている。

39 KB
■ このスレッドは過去ログ倉庫に格納されています

★スマホ版★ 掲示板に戻る 全部 前100 次100 最新50

read.cgi ver 05.04.00 2017/10/04 Walang Kapalit ★
FOX ★ DSO(Dynamic Shared Object)