なにかわかればおしえてください。
よくわからないのですが、Cでも同様の事があるらしいとの
うわさは聞きました(確かでないです.).
Linkerの問題だろうから同じことかと思うのですが...
NTでは/stack:sizeのoptionが必要でした...
DECに電話しても門前払いでした...
(man ldしてみました。stackのことがいくらか書かれてましたがよく分かりませ
んでした...)
小谷岳生
Takao Kotani さんの<3509C6...@phys.wani.osaka-u.ac.jp>から
>大阪大学理学部物理赤井グループの小谷です。
> program tst
> nbloch = 1000*1000/8 *3
> call testrw(nbloch)
> stop ' tst end'
> end
> subroutine testrw(nbloch)
> real(8):: hmat(nbloch)
> hmat=1d0
> print *,' tsrw end'
> end
浅学なので曖昧な書き方になって申し訳ありませんが、
> real(8):: hmat(nbloch)
という定義に危うさを感じます。
私も主としてDigital Fortranしか使っていないので、他の処理系では
よく分かりませんが、どうも仮引数を配列サイズに使った変数の宣言は
うまくいかないことがあるようです。
動作させることが目的なら、例えば、以下の文を主プログラムと
副プログラムの双方にincludeさせるわけにはいかないでしょうか。
PARAMETER (NBLOCH=1000*1000/8*3)
この1行だけを記述したファイルがsize.iであるとすると、
主プログラムと副プログラムは次のようになります(動作確認済)。
program tst
INCLUDE 'size.i'
call testrw
stop ' tst end'
end
subroutine testrw()
INCLUDE 'size.i'
real(8):: hmat(nbloch)
hmat=1d0
print *,' tsrw end'
end
* 平敷 安久 <hr...@jwa.go.jp>
program tstwithallocate
nbloch = 1000*1000/8 *3
call testrw(nbloch)
stop ' tstwithallocate end'
end
subroutine testrw(nbloch)
real(kind=selected_real_kind(10)),dimension(:),allocatable::hmat
allocate(hmat(nbloch))
hmat=1.0
print *, hmat(1), hmat(375000)
どうも,replyありがとうございました.
平敷さんの言われるようにやると,動的確保できません.
ぼくとしては,includeを使うとか,
parameterをprogramの途中に埋め込むとかは,極力避けたいんです.
makefileのcareに神経を使わないかんし...
f90においては,ぼくの書いたサンプルは正しい書式だと思います.
(かなり大きなprogramをcareしてますがちゃんと動いてます)
--------------------------------------
蛇足ですが,ぼくの思うプログラム記述の原則を書いておきます.
(まとまり悪いです)意見等聞かせてください.
(1)変数は可能なかぎり,使いまわしをしない(一回書いたものを書き換えない).
(2)可能なかぎりdo loopの数はへらす.
ベクトル表記のできるものは,できるだけそれを用いる.
(3)本質的な必要もないのにitterativeな構造は書かないこと(無意味なメモリ節
約はするな). pararellなものはpararellなように書く.
(4)itterativeな構造をもつdo loopはできるだけ小さい長さにする
(付随する量は後から計算すればいい).
(5)変数の依存関係(なにからなにを作るか)ができるだけ明瞭になるようにする
事.
(6)subroutineのi/oを明確にする.入出力を兼ねる引数は,できるだけ避ける.
(7)不要な媒介変数(work的エリア)はできるだけ用いない.
(8)ルーチンが長くなったからと言って細かいルーチンへわけるのは,意味がな
い.
(9)上位ルーチンから渡すような変数は,かならず整合配列で渡すべき.
サイズとarrayを同時に渡すべき.
(10)ぼくはglobal変数を使いたいときなんかは,たとえば,
logical function vefin()
vefin=.true.
end
などというような,functionを作って用いてます.これならlink事にbindされま
す.
(引用事には必ず()を忘れない事)
(11) commonは用いるべきでない.
(f77のときは一次元の巨大なstackとして利用していたが)
(12) includeやmoduleは用いるべきでない.f90のうちで,有効なのは,
「動的memory割付,ベクトル表記,sumなんかの関数」だけである.
>> 蛇足ですが,ぼくの思うプログラム記述の原則を書いておきます.
>> (まとまり悪いです)意見等聞かせてください.
大筋においては同意しますが、
>> (12) includeやmoduleは用いるべきでない.f90のうちで,有効なのは,
>> 「動的memory割付,ベクトル表記,sumなんかの関数」だけである.
includeもmoduleも使わないというのはちょっと極端な気がします。
複数のサブプログラムで変数を共有したい場合にはcommon(+include)か
moduleかどちらかを使わざるをえないと思います。サブプログラム間で
共有するすべての変数は呼び出し元から引数でわたす方がよい、
というふうにお考えでしょうか? (なぜ?)
「includeを使わなくて済むようにmoduleがあるんだから、commonやinclude
のような古い機構はもう使うな」とか、
「moduleは依存関係のあるコンパイルが処理系によって実装が違う
ので可搬性のあるライブラリを作るには不向き。include(+common)の方が
可搬性あり」
といった意見は聞いたことがありますが、両方ダメというのは初耳なのです。
>> (10)ぼくはglobal変数を使いたいときなんかは,たとえば,
>> logical function vefin()
>> vefin=.true.
>> end
>> などというような,functionを作って用いてます.これならlink事に
>> bindされます.
これもなぜcommonあるいはmoduleではないのかがちょっと気になります。
# makeがFortranに対応してないとか。たしかにそうですが。
--
新崎@名大人情
ara...@mns2.c.u-tokyo.ac.jp
他の人のCoding Policyはなかなか知る機会がないので、楽しんで見せて
もらっています。以下、私の感想を書きますが、私は本計算はvector機で
行っていますので、その点をお含み置き下さい。
In article <350D9E...@phys.wani.osaka-u.ac.jp> Takao Kotani <kot...@phys.wani.osaka-u.ac.jp> writes:
> --------------------------------------
> 蛇足ですが,ぼくの思うプログラム記述の原則を書いておきます.
> (まとまり悪いです)意見等聞かせてください.
(中略)
(1)~(3)、(5)、(6)、(9)、(11)は私も同じです。
> (4)itterativeな構造をもつdo loopはできるだけ小さい長さにする
> (付随する量は後から計算すればいい).
「iterativeな構造」というのがどう言うものか良く分かりませんので、
外しているかも知れませんが、vector化を考えるとdo loopの中は(vector化
出来る範囲で)長い方が良いと思っています。
> (7)不要な媒介変数(work的エリア)はできるだけ用いない.
これは意味が良く分かりませんでした。
> (8)ルーチンが長くなったからと言って細かいルーチンへわけるのは,意味がな
> い.
プログラムが見やすくなるのなら、分けます。
> (12) includeやmoduleは用いるべきでない.f90のうちで,有効なのは,
> 「動的memory割付,ベクトル表記,sumなんかの関数」だけである.
私の考えはちょっと違います。
commonを使う事の欠点は、各subroutine毎のcommon文の割当を間違え易い
というとと、データの流れが非常に見にくくなる事だと思います。
F90になって初め書き間違えの懸念がなくなったので、喜んで大半の変数を
muduleにしてしまい、データの流れがわからず、元に戻した事もありました。
現在は、変数宣言moduleは次のような使い方をしています。
1. moduleに入れる変数は、初期入力データ等ような一度書き込んだら中身が
変わらず、参照頻度の高いものに限る。
2. ``only'' attibute等を利用して、なるべく変数のscopeを明確にする。
3. 最下位の汎用性の高いsubroutineでは使用しない。これは後で、
subroutineを再利用する時に不便だからです。
他に、現状ではf90固有の機能を色々使って見たいのですが、どうコンパイル
されるのか分からないので、なかなか使用に踏み切れません。
例えば、整数と実数からなる構造体で、演算を行う時
通常ならメモリ上に
int,int,int,....
real,real,real,
と配置されてvector化が良く効きそうな場合でも、構造体を使うと
(int,real)(int,real)(int,real)(int,real)(int,real)
というような割り付けになったりすると非常に遅そうに思えます。
ぼくは,究極的には,(すくなくとも数値計算言語は)「無手順言語」にならない
といけない,
と考えてます.バグの元凶は「手順」という本来不必要なもの(計算機が処理す
べきもの)を,
人間がコントロールしないかんところにあります.
変数を「一回書いたら書き換えない」ことにするなら,原理的にはこれは可能で
す.
ルーチンの冒頭で,入力と,target(になる量)を指定してやれば,
「いかにtargetを入力から生成するか?」は計算機が決めればいいのです.
プログラムの各行は,原理的に順不同になります.
現状のfortranでも,できるだけそのpolicyをrespectするような書き方が望まし
いと
思っています.
まあ,個人的な趣味で,fortranのprepoceccorでも作れればなあ,とか思ってる
んですが...
(index文とかいうようなアイデアも考えた.また,もちろんアインシュタインサ
ムルールみたいなもの
もいるだろうと思う.そもそも,subroutineの頭で,i/oの指定をきちんとせな
いかん
[intentは信用してない.recursiveにcheckしないのでむしろ危険])
> > (4)itterativeな構造をもつdo loopはできるだけ小さい長さにする
> > (付随する量は後から計算すればいい).
> 「iterativeな構造」というのがどう言うものか良く分かりませんので、
> 外しているかも知れませんが、vector化を考えるとdo loopの中は(vector化
> 出来る範囲で)長い方が良いと思っています。
vector化=pararell化できるdo loopというのは,僕の言う意味での「itterative
な構造」
じゃないです.「原理的に漸化式であるもの」のことです.
f90では,sumやmaxval(最大値を見つける)とかは関数で処理できるので,
漸化式処理をしなくて済むようになりました.
do loopでも,完全にpararell化できるものは,それが明確になるよう(将来的に
は)
forallとかで書かれるべきでしょう[forallにsubroutineを挟めないのは難儀].
> > (7)不要な媒介変数(work的エリア)はできるだけ用いない.
> これは意味が良く分かりませんでした。
たしかにわからないです.自分で読んでも...
えっと,できるだけ意味のある変数をもちいること(意味づけを明確にする),と
か,
do loopで,次のcycleへ値を持ち越して変な事になるのを恐れてるとか言うぐら
いの事です.
> > (8)ルーチンが長くなったからと言って細かいルーチンへわけるのは,意味がな
> > い.
> プログラムが見やすくなるのなら、分けます。
これも,いろいろ意見があると思います.でもぼくの上述のpolicyで言えば,
個々のルーチンが長くなるのは平気のはずなんです.極端に言って,もし「無手
順言語」が
できた暁には,「2個所以上でcallされるルーチン」以外は分ける必要はないで
す.
いまでも,「変数の使いまわしをしない」を守るなら,多少ルーチンサイズが長
く
なっても問題はないです.むしろわけることによるトラブルが恐い.
わざわざ分けてもあまりメリットがない.
>> (10)ぼくはglobal変数を使いたいときなんかは,たとえば,
>> logical function vefin()
>> vefin=.true.
>> end
>> などというような,functionを作って用いてます.これならlink事に
>> bindされます.
これもなぜcommonあるいはmoduleではないのかがちょっと気になります。
# makeがFortranに対応してないとか。たしかにそうですが。
ええ,makeに依存関係を書くのが面倒だからです.
> > (12) includeやmoduleは用いるべきでない.f90のうちで,有効なのは,
> > 「動的memory割付,ベクトル表記,sumなんかの関数」だけである.
> 私の考えはちょっと違います。
> commonを使う事の欠点は、各subroutine毎のcommon文の割当を間違え易い
> というとと、データの流れが非常に見にくくなる事だと思います。
> F90になって初め書き間違えの懸念がなくなったので、喜んで大半の変数を
> muduleにしてしまい、データの流れがわからず、元に戻した事もありました。
>
> 現在は、変数宣言moduleは次のような使い方をしています。
> 1. moduleに入れる変数は、初期入力データ等ような一度書き込んだら中身が
> 変わらず、参照頻度の高いものに限る。
>
> 2. ``only'' attibute等を利用して、なるべく変数のscopeを明確にする。
>
> 3. 最下位の汎用性の高いsubroutineでは使用しない。これは後で、
> subroutineを再利用する時に不便だからです。
> 他に、現状ではf90固有の機能を色々使って見たいのですが、どうコンパイル
> されるのか分からないので、なかなか使用に踏み切れません。
> 例えば、整数と実数からなる構造体で、演算を行う時
> 通常ならメモリ上に
> int,int,int,....
> real,real,real,
> と配置されてvector化が良く効きそうな場合でも、構造体を使うと
> (int,real)(int,real)(int,real)(int,real)(int,real)
> というような割り付けになったりすると非常に遅そうに思えます。
---------------------------------------------------------------
>includeもmoduleも使わないというのはちょっと極端な気がします。
>複数のサブプログラムで変数を共有したい場合にはcommon(+include)か
>moduleかどちらかを使わざるをえないと思います。サブプログラム間で
>共有するすべての変数は呼び出し元から引数でわたす方がよい、
>というふうにお考えでしょうか? (なぜ?)
>
>「includeを使わなくて済むようにmoduleがあるんだから、commonやinclude
>のような古い機構はもう使うな」とか、
>「moduleは依存関係のあるコンパイルが処理系によって実装が違う
>ので可搬性のあるライブラリを作るには不向き。include(+common)の方が
>可搬性あり」
>といった意見は聞いたことがありますが、両方ダメというのは初耳なのです。
---------------------------------------------------------------
>私はmoduleを多用しています。
参考になります.
実際,ぼくはmoduleの説明をよんで,
「これはincludeに毛が生えた程度だなあ,使えんなあ.
(その他,interface文なんかも全く不要. そんなことはcompilarにさせろ)」
と独断的に切り捨てて利用法も知らないし,ひがみで,ちょっと挑発的に書いて
みたんです.
でも,なんでも「module化」できるというのはうさんくさいです.
ひとによってprogramの書き方が,ばらばらになってしまう.
(「なんでもできる」は「なにもできない」とほとんど等価です.
C++の悲惨な結末と同様になる).
compile事に取り込むなんてことをやりだすと,
fortranの最大の資産である「単純さ」が失われる事になる.
(fortranでは,(まあある程度のものであれば)人の書いたcodeを読むのは,
比較的容易です. 誰が書いても似たようなものになる)
moduleなんてのは,compilar開発者に都合のいいように,手抜きされた
仕様なんじゃないですか? なんでも「Cでやってるようにやるのがいい」
とは一つも思いません.
ぼくが思うに,データをmoduleで渡すのは大変危険です.
データの流れが分からなくなります.
もちろん,
> 1. moduleに入れる変数は、初期入力データ等ような一度書き込んだら中身が
> 変わらず、参照頻度の高いものに限る。
だとまだ何とかなると思いますが,それでもぼくはいやです.
そのルーチンでどのデータが必要だったのかがわからなくなります(まとめて渡
すため).
独立性がそこなわれます.(同様の理由で構造体の利用にも反対)
>サブプログラム間で
>共有するすべての変数は呼び出し元から引数でわたす方がよい.
とぼくは考えています.routineのheadが重くなります(長いと20行ぐらいになる
)が,
i/oは明確です.
(link事に,変数の数がずれてたら,compilarにもよるがcheckしてくれるはずで
す)
まあ,ぼくの読んできたcodeに影響されてます.
(おもに,バンド計算関係のcodeを何種類か読みました)
独断偏見に満ちてますが,できるだけ意見が明確になるように書きましたので
...
ご容赦ください.