ToDo:
掲示板 にも書きましたが、Beam Line Element名での Caseの扱いが変です。 MAINレベルとか SADScript関数(LINE/Element/...)では Case Preserveかつ Case Sensitive Matchなんですが、FFSコマンドラインは Case Preserveで無い上に Case Sensitive Matchのようで、小文字混じりの要素を FITや FREE/FIXに 使えないことを見付けました...Orz
コマンド名を Case Insensitive Matchするのでなく、問答無用で 全てのtoken(コマンド名以外を含む)のCaseを正規化してから Case Sensitive Matchをかけてるっぽいのですが...
少なくともシステムの一貫性が損なわれている部分は修正すべきなのですが、 正しい仕様はなんなんでしょう?
script/bench2.sadにて、RFMARK2と宣言した要素を fit rfmark2 ...で参照するコードを発見
つまり、過去のコードは FFSコマンドラインでの要素名に対する Case Insensitive Match若しくはCase Normalizationを 期待している...頭痛くなって来たぞ Orz
たぶん、後方互換性を維持するには Case Matching Ruleを制御する フラグか関数を導入する必要があるとみた(Case Normalizationを 強要すると LINE/Element関数が Case Sensitiveで無くなるので、 それに依存したコードの互換性を損なうし...全ての要素名が 表れる部分にCase Normalizationを実装するのは面倒)
FFS command lineで、字句解析器がシンボル・コマンドを Upper Caseへ 強制変換してしまうので、小文字を含んだ element nameをFIT等で参照 できない問題への対処を始める。
PRSVCASEを指定すると element nameを Case Preservingに扱い、 NOCONVCASEを指定すると 字句解析器での Case変換を無効化する。
後方互換性のために、起動時はNOPRSVCASEかつCONVCASEで実装
現時点では、PRSVCASEフラグは FFS command全てのコマンドで 有効なわけでは有りませんが、通常使用する主要なコマンドは サポート出来ていると思います。
IP Coupling/Dispersion Knobまわりの話の一環として Coupling Correctionの荒っぽい評価をしてみる。
6極のミスアライメントをソースとする Coupling/Dispersion Errorを アーク部のSkew Q.で補正してみる。測定と補正モデルを作るのが 面倒なので、各直線部の真ん中で R1-4を拘束して Matchingするモデルを 採用する。当然、EYと EPYに誤差が残るので、EYを条件に追加すると Matching仕切れない....
各アークに Skew Q. 4台ではこれは当然の結果だが... なんで、6台入れなかったんだ?
マニュアルに増設したフラグの記述を追加した。
動作としては、CONVCASEを切ればFFSコマンドラインは問答無用で Case Sensitiveになるが、コマンドやオプション類は全て大文字で 無いと受け入れられないので要注意
また、PRSVCASEの実装状況(Rev.1362)だが ielm()経由で参照している 部分を中心に修正しているので、一部抜けがありえます(temat()/tmatch() 経由の参照が有ることが判明している。改修したファイル内に関しては、 一応修正してあるが...)
改修済みコマンドリスト
実用上は、DISP,FIT,COUP,FREE,FIXだけ 使えれば十分な気がする
どうしてもこれ以外のコマンドで小文字の要素名が必要な場合は、 NOCONVCASEに切替えてください
SAD/Tkinter周りで Backslash escape問題(GCC 4.2.x以前では発症しませんが)を修正。 原因は、OBJ_BACKSLASH_ESCAPEの更新し忘れ Orz
これは、バックポート必要だよね(たぶん Tru64には影響する)
KEKB HER Crab Opticsを使った Tracking(RFSW/RAD/FLUC付き)で 疑似乱数発生器の置き換え前後を比較する。
RADと FLUCで放射減衰と量子励起による拡散に疑似乱数列が使われているので、 コードの置き換え(PRNG本体の置き換え&iseedのインライン化された線形合同 法を関数呼び出しに置き換えた)に失敗している部分をなめると結果に 違いが出るはずというのが、試験動機です。
試験内容は、粒子数1000個の初期分布を与えて 1000ターンのTrackingを行い結果と消費CPUタイムを比較する。
まず、疑似乱数発生器に Random/SAD pluginを使った場合
code | result | time/turn |
---|---|---|
CVS MAIN | reference | 5.9914 |
amorita | match | 5.9528 |
amorita-noarray | match | 6.1047 |
使用された範囲のコードでの疑似乱数列参照の書き換えは成功している模様。
amoritaと amorita-noarrayの実行速度差を見ると、 疑似乱数生成ループを新設したtran_array_,tgauss_array_ (乱数配列を取ってくるAPI)へ置き換えたが速度向上に 寄与しているように見える。 また、インラインルーチンを関数呼び出しへ置き換えことに伴う速度低下を 乱数配列生成APIによる速度向上でカバーできたようである。
続いて、SeedRandom[]を使って疑似乱数列を Random/SFMT pluginに切替えた場合
code | result | time/turn |
---|---|---|
CVS MAIN | mis-match | 6.0000 |
amorita | reference | 6.0035 |
amorita-noarray | match | 6.2041 |
CVS MAINの疑似乱数発生器は線形合同法固定(Random/SAD相当)なので 一致しない、きちんと違う疑似乱数列が適用されていることが判る。
また、処理速度の悪化の問題はないようである。
writeb@tfprinta.fの変更は、IFCサポートぶち壊しな気がする
write文での改行制御などの標準外 format指定は、 激しくコンパイラ依存で、\$を後ろに付ける改行制御は IFCは受け付けなかったような...
IFCサポートを入れるときに、G77/DEC Fortran/Intel Fortran 全てで共通に使える改行制御を探すのにえらい苦労した記憶が... (I hope the below works for all compilers...って 希望するだけなら簡単だけど、それでは世の中のコンパイラは 動かないんだ...)
絶望した!I/Oを再定義出来ないのに、ベンダーが勝手に I/O書式制御を拡張する Fortranコンパイラに絶望した!
IFCだと#文字の characterを表示するのにa#という 書式指定も NGというか期待と違う動作をする
a#は、i#と同様に #bytesな characterと解釈されるので "abc"を a3でフォーマットすると出力は" a"となり、 一文字の character "a"を先頭に空白を付けて 3byte幅で出力する。
状況はかなりひどいようなので安定するまで バックポートは凍結かな?
GNU makeに関しては、既存の amsad/alsad/acsadでの makeで 発覚するはずなので、既存の環境での make試験をせずに commitしたのは明白。
CVS MAIN trunkに関しては KEKBの運転で使っている以上、 運転環境の構築で問題が出る変更を入れるのは NGなはず。
writebで使っている character*Nな bufferへの write文の結果だが、 Fortran規格をチェックしていないのだが、出回っているコンパイラの 出力を比較する限り実装依存な気がする。 全てのコンパイラで動くことを期待するなら、Fortranの標準規格の 範囲内で書くべきで、可能ならコンパイラの実装バグを避けるよう 実装が安定している範囲で書くべき。
Fortranの場合、1文字入出力等のプリミティブなI/Oが標準規格に無いので、 Cと異なりread/write文の実装が腐っているからといって置き換えを 作れないところが頭痛の種ですね。プリプロセッサで open/close/read/write系を Cの関数に置き換えるというのは原理的には 可能だが、それは Fortranの部分コンパイラを作ることであって、 腐った処理系の再実装に相当する。
SAD掲示板では、writeb論争が繰り返されておりますが、 write文と編集記述子の仕様を求めて Web上を彷徨い歩くはめに...
まずは、一個発見♪ XL Fortran 95のマニュアル には、Qと\$はIBM拡張とある。 明らさまに拡張と書かれている以上、Fortran95の編集記述子には 改行抑止制御は実装されていないことに...
Fortran2003には、この拡張は入っているのかな? Fortran2003完全準拠のコンパイラもまだ無いのに、 Fortran2008(2003のマイナーアップデート)が出てくるという話だが...
あと、編集記述子の要素数より多い要素をWRITE文に記述した場合の動作定義が判らない... Orz
HP Fortranのマニュアル にそれらしき記述を発見、それによると編集記述子の 最後まで使いきったら、一度出力終了して、再度出力を始める際に 基本的には制御は、入れ子レベル 1 の右端のグループの反復数に戻さる らしい。 さらに、入れ子レベル 1 の右端のグループに反復数が存在しなければ、制御はそのグループ自体に戻れ、 入れ子レベル 1 のグループが存在しなければ、制御は書式仕様内の最初の編集記述子に戻されるそうなので、同じ形式("A1")で 長さnのinteger*1配列から 文字列を吐き出させる場合(\$,nA1)と(\$,A1)は 同値ということか。
ふむ、少なくとも HP Fortranでのコードは簡単に書けることが判った。
ただ、これだけだとHP Fortranの実装がそうなっているのか Fortran規格でそう実装すべきを規定されているのか区別が付かない。
ふむ、 HP Fortranの編集記述子の 解説によれば、\$の改行抑制と同様の機能で 停留入出力と呼ばれ る機能が有り、これは Fortran90規格に含まれるようだ。 (やはり、\$は HP Fortranでの拡張と書かれている)
改行制御をまとめると、
ということか
write文に ADVANCE='NO'を指定して停留出力を使うと 最後の改行が抑制されるが、編集記述子の数が不足して使いまわされる際に 出力の停止と再開の間で改行が出力される (g95-0.91/gfortran-4.2.4pre/ifort-8.1で確認)
たぶん、Fortran90的には (#a1)な編集記述子を合成して、 ADVANCE='NO'で出力すれば OK、 IBM拡張を当てにするなら (\$,a1)で十分
ただし、ADVANCE予約語は g77の Fortran90モードでは 実装されていない Orz
write(form,*)lで整数lを文字列化した際に、 右詰め・左詰めの違いが出ることに関して SAD掲示板で下記の試験結果を
--- begin test.f --- integer num character*12 form num = 12 write(form,*) num write(*,*)'form=[',form,']' end --- end test.f --- 0. DEC Fortran on acsad0 % f77 test.f && ./a.out form=[ 12] 1. GNU Fortran (GCC) 4.2.4 20080213 (prerelease) % gfortran42 test.f && ./a.out form=[ 12] 2. GNU Fortran (GCC) 3.4.6 [FreeBSD] % g77-34 test.f && ./a.out form=[ 12 ] 3. Intel(R) Fortran Compiler for 32-bit applications, Version 8.1 Build 20060606Z % ifort test.f && ./a.out form=[ 12] 4. G95 0.91 % g95 test.f && ./a.out form=[ 12 ]
報告したが、整数変数記述子は右揃えなので write文に真面目に編集記述子(I12)を付ければ 全ての環境で右詰めで出力されることに、思い至った。 もし、そうでなければ...その Fortranコンパイラは壊れている。
_ alexd259 [Very nice site!]
整数を右詰めw桁に編集する記述子Iwですが、 一部のコンパイラではw=0のときは表現可能な 最小の桁数に編集するという意味を持つ (Nag Fortranのマニュアルで見付けた)ようですが、 案の定 g77では動きません。
Intel Fortran 8.1/gfortran-4.2.4/g95-0.91では、 使えるところを見ると Fortran90/95辺りに入っている?
XL Fortranのマニュアル だと "Fortran95は例外です" とあるから、 正式規格には入っていないのか...それともマニュアルの誤訳?
_ 管理人さん [Xserve RAID販売終了 購入から4年経過、そろそろだと思っていた。]
長らく放置されていた、ports/devel/libffiが新しくなっている。
SAD用のFFIインターフェースは libffiでいきますかね? printf見たいに、引き数列のフォーマットを渡して 外部関数を呼び出すような感じで...
SADの Binary Read/Writeのベンチマークで発見
Intel Fortran 8.1 + FGETC intrinsic functionの組合せで、ファイル上のLF(0x0a)を読むと FGETCは CR(0x0d)+LF(0x0a)を返して来て 1byteずれる... Orz
お〜ぃ、動いてるのは unix上だぞ!Windowsじゃないぞ
個人的には、MacOSX用の Intel Fortranでの動作が気になるところ(まさか、CR読むと CR+LFを返して来るのでは...)
なんらかのコンパイルオプションかディレクティブで制御できるのかな?
テストベクタと Read[]の戻り値の読み違えですた
正しくは、「CR(0x0d)+LF(0x0a)を FGETCで読むと LF(0x0a)だけが 返ってくる」です。
どちらにしろ、uni-byte streamを読みたくてFGETCを使っているのだから、 勝手に改行記号の変換してくれるのは迷惑以上の何者でもない...Orz
SADのコードには、Header RCSタグを含むものが有るのですが、 diffやマージ作業の邪魔以外の何者でも無いような...
タグに含まれる最終変更日と最終変更者は、repositoryに聞けば 判ることだし、RCS由来でパス名がレポジトリサーバー内での 絶対パスなのはいただけない。おかげで、mirror pserverと master repositoryから取得した working copyの diffを 取ると悲惨なことに Orz (master repositoryが VPN経由でしか参照出来ない& VPN使うと全てのパケットが VPN Gateway経由になるので、 commit時以外は mirror pserver使わないと不便なんですよね)
Subversionでは、この辺りの基本情報はsvn infoで オフラインからでも見れるのがありがたい (checkoutした revisionに対する diffやrevert操作も オフラインできる)
もっとも、working copyに checkout revisionのオリジナルが まるごと保管されているので、disk spaceは CVSの2倍消費しますが(w
GCC 4.3.0だとコンパイルエラーが出るのでいろいろ修正
signed intと unsigned intの比較で警告が出てるとか、 2次元配列の初期化子が一次元配列で警告出まくりとかは 可愛いものですが...
外部結合な関数を参照するのに classスコープ上で friend付きで関数を宣言しているのが、 GCC 4.3.0にそんなシンボルは名前空間が無いよと言われる。 確かに、classネームスコープには居ない関数だよね。
というか、組み込み型を引数に取って内部でも組み込み型の大域変数にしか 触らない関数はclass memberにアクセスしないのでfriend宣言は要らないと 思うのだが...なんで付いてるんだろう?
教えて、えらい人
どんな言語でもそうだけど、頼むから言語規格に目を通してから コードを書いてくれ Orz
Q編集記述子は、すでに調べた通りベンダー拡張なので 使うべきでは有りません。read文に置いては、Q編集記述子が 表れた時点でバッファ無いに有る文字数を返すので(Q,A)と 書けば、読み込んだ文字列の長さが判るわけです。 Fortranの文字列仕様(変数のサイズは固定でも中身のサイズが判らない)で パーサー書くには必須とも言える機能なので、新しいFortranには 同等の機能が無いはずは無いと思うのですが...やはり有りました(w
Fortran90の停留入出力での入力で、
integer :: nc character(len=256) :: s read(lfno, fmt='(A256)', advance='no', size=nc) s
という構文が使えます。ここでは、 sは長さ256の文字列バッファに 入力lfnoから改行・ファイル終端が来るか最大256文字読み込むまで 読み込み、読み込んだ文字数を ncに格納します。 停留入力なので、改行が来る前に書式指定の終端に達した場合は、 ファイルポインタはそこで停止します。 つまり、入力を1文字づつ読み込むことも可能です。
これ自身は、Fortran90規格に有るので g95でも使えるのが味噌
ただし、改行は特別扱いなので unibyte-stream入力には 厳しいですね。もちろん、改行記号が特定1-character のみな処理系なら改行を検知したところで、バッファに自前で 改行記号を送り込めば良いわけですが、移植性がありませんね (改行記号が1-characterでもCRかLFかそれ以外かは環境依存)
実際、Fortran I/O libraryが気を利かせている実装の場合、unix上でも CR-LFのシーケンスを改行記号に扱ったり(例えばg95/gfortran)、 単独のCRに対して次のLFを読みにいってCR+LFで無い場合は 改行記号扱いし次の一文字は読み飛ばしたままだったり(例えばgfortran) するのでunibyte-stream入力を停留入力で扱うのは難しそうです。
Fortran90から入った停留入力で制御文字"\\r"の振るまい奇妙なので、 実装ごとの挙動を調べてみました。
ここでは、"\\r","\\n","\\r\\n"などの改行記号が 入力列に含まれて際の read文からの戻り値を調べています。 サンプルとした入力列は、"abc\\rdef\\n\\nABCDEF\\r\\n123456\\neof"です。 この入力列は、標準入力(UNIT=5)とファイル経由(UNIT=10)で テストプログラムに入力され、read文で停留入力による読み取りが行われます。
g95 0.91 20080220の場合
標準入力 | "abc\\rdef",size=7,iostat=-2 | "",size=0,iostat=-2 | "ABCDEF",size=6,iostat=-2 | "123456",size=6,iostat=-2 | "eof",size=3,iostat=-2 |
ファイル | "abc\\rdef",size=7,iostat=-2 | "",size=0,iostat=-2 | "ABCDEF",size=6,iostat=-2 | "123456",size=6,iostat=-2 | "eof",size=3,iostat=-2 |
gfortran 4.2.4 20080220 (prerelease)の場合
標準入力 | "abc",size=3,iostat=-2 | "ef",size=2,iostat=-2 | "",size=0,iostat=-2 | "ABCDEF",size=6,iostat=-2 | "123456",size=6,iostat=-2 | "eof",size=3,iostat=-2 |
ファイル | "abc",size=3,iostat=-2 | "def",size=3,iostat=-2 | "",size=0,iostat=-2 | "ABCDEF",size=6,iostat=-2 | "123456",size=6,iostat=-2 | "eof",size=3,iostat=-2 |
gfortran 4.3.0 20080221 (prerelease)の場合
標準入力 | "abc",size=3,iostat=-2 | "ef",size=2,iostat=-2 | "",size=0,iostat=-2 | "ABCDEF",size=6,iostat=-2 | "123456",size=6,iostat=-2 | "eof",size=3,iostat=-2 |
ファイル | "abc",size=3,iostat=-2 | "def",size=3,iostat=-2 | "",size=0,iostat=-2 | "ABCDEF",size=6,iostat=-2 | "123456",size=6,iostat=-2 | "eof",size=3,iostat=-2 |
Intel Fortran Compiler Version 8.1の場合
標準入力 | "abc\\rdef",size=7,iostat=-2 | "",size=0,iostat=-2 | "ABCDEF",size=6,iostat=-2 | "123456",size=6,iostat=-2 | "eof",size=3,iostat=-2 |
ファイル | "abc\\rdef",size=7,iostat=-2 | "",size=0,iostat=-2 | "ABCDEF",size=6,iostat=-2 | "123456",size=6,iostat=-2 | "eof",size=3,iostat=-2 |
つまり、改行区切りなテキスト読み込み(itfgetbuf_)には使えるが、uni-byte stream入力には使えないと言うこと
itfgetbuf_の実装を
で行ったものを比較すると、read(2)が断トツに遅いのは予定通りだとしても、 停留入力がFGETCより遅いのは納得がいかないな
Intel Fortran 8.1で試すと、処理時間比は Q editing:FGETC:停留入力:read(2)で1:1.7:7:23ぐらいで、 FGETCに比べるて停留入力が4倍近く遅い... Orz
gfortranだと、FGETC:停留入力:read(2)で 1:1.6:8.9ぐらいでそれほど激しい差では無いですが停留入力の方が遅い
内容的には、I/O library側でループを組める&最適化できるので FGETCのループより早くてもよさそうなモノですが...
itfgetbuf_の実装に限れば、
ということですね。 実際は、binary Read[]で FGETC intrinsicが使われているので FGETCが未実装の場合、整合性を取ろうとするとread(2)で 全部実装するしかないのですが... (それでも、Write[]とFileSeek[]との完全には整合性しない)
カテゴリー: Admin | Emacs | EPICS | Fortran | FreeBSD | GCC | hgsubversion | IPv6 | KEKB | LHC | Lisp | LLVM | MADX | Ryzen | SAD | samba | tDiary | unix | WWW | YaSAI | お仕事 | イベント | 出張 | 宴会 | 数学 | 艦これ | 買いもの | 追記 | 雑記
_ 三菱 田中 [またLogBrowserの鯖が見えないようです ]