Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

DEGITAL UNIX のFortran90 のBug( あるいは不親切な仕様)

11 views
Skip to first unread message

Takao Kotani

unread,
Mar 13, 1998, 3:00:00 AM3/13/98
to

大阪大学理学部物理赤井グループの小谷です。
DEGITAL UNIX のFortran90 のBug(あるいは不親切な仕様)に
ついてです。
-------------------------------------------
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
-------------------------------------------
これをf90でa.outを作って、実行すると
Segmentation fault (core dumped)
で落ちます。

なにかわかればおしえてください。
よくわからないのですが、Cでも同様の事があるらしいとの
うわさは聞きました(確かでないです.).
Linkerの問題だろうから同じことかと思うのですが...

NTでは/stack:sizeのoptionが必要でした...
DECに電話しても門前払いでした...
(man ldしてみました。stackのことがいくらか書かれてましたがよく分かりませ
んでした...)


小谷岳生

HIRASHIKI Yasuhisa

unread,
Mar 14, 1998, 3:00:00 AM3/14/98
to

初めまして。平敷@気象協会と申します。

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>


NISHIMATSU Takeshi

unread,
Mar 14, 1998, 3:00:00 AM3/14/98
to

小谷先生こんにちは. 西松です.
f90 でしたら, 「動的メモリ割付け」を使うのはどうでしょう.

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)

Takao Kotani

unread,
Mar 16, 1998, 3:00:00 AM3/16/98
to

HIRASHIKI Yasuhisa wrote:
> 浅学なので曖昧な書き方になって申し訳ありませんが、
> > real(8):: hmat(nbloch)
> という定義に危うさを感じます。
> 私も主としてDigital Fortranしか使っていないので、他の処理系では
> よく分かりませんが、どうも仮引数を配列サイズに使った変数の宣言は
> うまくいかないことがあるようです。
>
平敷さま,

どうも,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なんかの関数」だけである.

Arasaki Yasuki

unread,
Mar 16, 1998, 3:00:00 AM3/16/98
to

In article <350D9E...@phys.wani.osaka-u.ac.jp>
Takao Kotani <kot...@phys.wani.osaka-u.ac.jp>さんwrote:

>> 蛇足ですが,ぼくの思うプログラム記述の原則を書いておきます.
>> (まとまり悪いです)意見等聞かせてください.

大筋においては同意しますが、

>> (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

jy@arl27

unread,
Mar 19, 1998, 3:00:00 AM3/19/98
to

山内淳@東芝基礎研です。
こんにちは。
私は最近77から90へ移行しつつあります。
というわけで、間違った事を言っていたり、もっと良い方法がある
ようでしたら教えて下さい。

他の人の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)
というような割り付けになったりすると非常に遅そうに思えます。

Takao Kotani

unread,
Mar 21, 1998, 3:00:00 AM3/21/98
to

小谷@阪大理です.
あいまいな事を書いててすみません.
まず,ぼくのcoding戦略というのは,「できるだけひとにやさしい書き方」
を考えましょうという路線です.あまりvector化は考慮に入れてません.

ぼくは,究極的には,(すくなくとも数値計算言語は)「無手順言語」にならない
といけない,
と考えてます.バグの元凶は「手順」という本来不必要なもの(計算機が処理す
べきもの)を,
人間がコントロールしないかんところにあります.

変数を「一回書いたら書き換えない」ことにするなら,原理的にはこれは可能で
す.
ルーチンの冒頭で,入力と,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を何種類か読みました)

独断偏見に満ちてますが,できるだけ意見が明確になるように書きましたので
...
ご容赦ください.

0 new messages