※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

FPU・ライブラリ関連の質問等


なんかcollisionして書き込みに失敗することが多かったので、
意見を書き込むところを勝手に分離しました。(buyobuyon)


  • そうですね。
    確かコンテストルールでは指数部が1~254で表される数と+0が適切に表現されていれば
    良いのでしたよね(あまりよくルールを読んでいないので間違っているかも…)。
    あと、-0をどうするかについてちょっと気になっているのですが。
    -0があると整数と同じ方法で比較が行えないことをすっかり忘れていて、
    浮動小数の比較命令を用意していなかったのですが…。
    一般にはどのように扱われているようですか? -- buyobuyon (2006-10-24 22:21:13)
  • 丸め方式は…、詳しくないのでよくわからないのですが。
    なんか感覚としては、銀行で使われるとk林先生が仰っていたあの丸め方式が、
    一番誤差が少なくなりそうな気はするけど、
    Firexhlとかで部分的に切り捨て方式が使われているということは、
    たぶん速度の面で問題があるのでしょうね。
    どうしましょう…。 -- buyobuyon (2006-10-24 22:33:01)
  • -0…。
    1.使わない
    2.検出したら+0に変える
    3.特別扱いでcmpを実装
    とかですかねぇ。
    1,2は本質的にそんなに変わらないのかな?
    3はできなくはないと思うのですが回路的にどうなんだろう?(よくわからんです) -- yastak (2006-10-25 14:22:52)
  • コメント書き込もうとしたら、collision起こして、書いたことすべて消えてしまった(; ;) -- buyobuyon (2006-10-25 15:26:31)
  • 改めて…。
    -0の件ですが、やや勘違いしていました。
    -0があると整数と同じ方法で比較が行えない → 負の値があると整数と同じ方法で比較が行えない
    でした。すみません。
    そういうわけで、結局、浮動小数点数比較命令flessが必要だと思います。
    flessを作成するとなると、-0ありにして、-0 < +0という扱いにすると良いかと。
    簡単だし。ルール違反じゃないよね?
    それから、浮動小数点数では=による比較は+-0との比較以外は普通使わないでしょうし、
    +-0との比較は0x80000000Uとのxorをとることで代用できますし、
    (もしどうしても必要なときは)0以外との比較は not(a > b or a < b)で代用できますので、
    浮動小数点数比較命令は<だけあれば良いと思います。

    というのが今の私の見解なのですが、どうでしょう。素人の意見なので、あまり信用しないでね。 -- buyobuyon (2006-10-25 15:33:37)
  • flessの仕様について。整数比較命令の仕様を決めるときには、とりあえず、
    真 → -1 (0xffffffffU) , 偽 → 0 (0x00000000U)
    としましたが、特に意味があってのことではないので、
    整数比較とflessとで形式があっていれば別に-1でも1でも良いかと。
    とは言いつつも、何となく-1の方が使い勝手がよさそうに見えるかな…。 -- buyobuyon (2006-10-25 21:33:01)
  • ごめん、比較結果をnotしたときに真偽が入れ替わるようにしたかったから
    真 → -1
    としたのでした。-1でお願いします。 -- buyobuyon (2006-10-25 21:55:00)
  • FDIVの仕様で、「±0で割る場合、出力の符合はSRC1の符号と一致」としているけど、
    0以外で割る場合と同様に、被除数の符号と除数の符号のxorをとって商の符号とした方が
    自然じゃないかな? -- buyobuyon (2006-11-17 01:22:07)
  • 自然だとは限らなさそうだな…。
    う~ん、-0がよくわからない…。-0に関しては、
    ・演算の答えとしては-0を生成しないようにする
    ・同じ値の引き算など、ちょうど0になる場合には+0と決めておき, それ以外なら答えの符号に応じて+0か-0かを決める
    のどちらかの方針をとることになると思うんだけど、今回はどっちの方針をとっているのかな? -- buyobuyon (2006-11-17 01:37:59)
  • とりあえずは「演算の答えとしては-0を生成しないようにする」という方針で行っています。
    tsuyのページの仕様の各命令の部分を見ていただければ分かるかと。
    また、「同じ値の引き算など、ちょうど0になる場合には+0」になるようにしています。
    とにかく、FPUからの出力が-0となることは無いように気をつけています。(実装で漏れがあるかもしれませんが)

    「それ以外なら答えの符号に応じて+0か-0かを決める」
    この部分がよく分からないんですけど、「それ以外」って「ちょうど0に」ならない場合?
    0にならないのなら+0にも-0にもならないような… 読解力なくてすいません -- tsuy (2006-11-17 17:59:19)
  • 昨日地下で聞いたときには、

    「±0で割る場合、出力の符合はSRC1の符号と一致」でいいんじゃない?

    的なことを言ってたではないですか><; -- tsuy (2006-11-17 18:05:00)
  • あっ、すみません。-0を生成しない方針をとっているのならいいんです。

    ちなみに、 「それ以外」 = 「ちょうど0でない」 というのは、
    計算した値の指数部がfloatで表せる範囲を(下に)超えてしまって、その結果、
    答えが+0か-0になった場合(NaNじゃなくて±0になるんでしたよね)のことを、言っていたつもりでした。
    FMULの仕様のところに、「オペランドの少なくとも一方が±0のとき、出力は+0」と書いてあったので、
    どちらのオペランドも±0でないが答えが±0になる場合には、出力が-0になることもあるのかな、と勘違いしていました。 -- buyobuyon (2006-11-17 23:44:43)
  • > 「±0で割る場合、出力の符合はSRC1の符号と一致」でいいんじゃない?
    > 的なことを言ってたではないですか><;

    そうだっけ…、ごめん。
    FPUが-0を出力しない以上、SRC2に-0が入っているのは、
    ユーザーがわざわざそのレジスタに+0でなく-0を入れた場合だから、
    出力の符号をSRC2の符号にも依存させた方がいいと思います。その方が、SRC2が-0の場合でも
    出力の符号 = SRC1の符号 xor SRC2の符号
    が成り立つから、例外的な処理が減って、回路が小さくなるような気もするし。 -- buyobuyon (2006-11-18 00:01:55)
  • >FPUが-0を出力しない以上、SRC2に-0が入っているのは、ユーザーがわざわざそのレジスタに+0でなく-0を入れた場合

    なるほど、了解しました。
    次回地下に降りたときにでも修正しておきます。

    >計算した値の指数部がfloatで表せる範囲を(下に)超えてしまって

    ここを読んで一部の命令にオーバーフローやアンダーフローしたときの処理を入れ忘れていることに
    気づいてしまった…
    さらに回路サイズが大きくなるんだね…
    -- tsuy (2006-11-18 17:42:10)
  • なるほど、アンダーフローが実装されていなかったから話がかみ合わなかったのか…。 -- buyobuyon (2006-11-18 20:50:21)
  • 正規化数のみサポートすることにしたのですが、
    ・INVに0、FINVSQRTに負の数を入力したときの処理
    ・オーバーフロー、アンダーフロー
    はどうしましょうか?
    特にオーバーフローアンダーフローをなくせば、命令によってはかなり高速化できそうなのですが… -- tsuy (2006-12-14 23:55:19)

  • ライブラリなのですが、やはりある程度私が関与した方が良いのですかね。
    というのは、例えば、ライブラリ内部で使用しているlfabs関数、
    これは最上位ビットを0にする命令(and)で置き換えられますけど、
    OCamlやMinCamlだと、型の関係でそういう処理は表せないですよね。
    とすると、
    1.ライブラリで作成する関数やライブラリ内部で用いる関数の一部をはじめからアセンブラで書く
    2.MLで書いたライブラリをコンパイルし、生成されたものを一部修正する
    3.自作コンパイラで記述できる構文を増やす(float同士のandなどを追加?)。
    4.諦めて、MLで記述できる構文のみで書く
    のどれかですよね…。どうします? -- buyobuyon (2007-01-11 14:36:14)
  • ライブラリのニュートン法で初期値を与えるところに大量の比較・分岐命令が入っていますが、
    例えばテーブルを作成するとか、適当な(かつ簡単な)連続関数の値を初期値とするなどの方法で、
    分岐命令数を減らせませんかね?
    無理そうなら、if{ }elseif{ }elseif{ }elseif{ }...を
    if{if{...}else{...}}else{if{...}else{...}}みたいに書き換える、
    使用頻度の高い分岐先には少ない回数の分岐で飛べるようにifの順番を変える、
    などの方法で平均実行命令数は減らせば良いとは思いますが。

    とは言っても、高速化は精度などの問題を突き詰めてからの話でしたね。

    あと、それに関連して、浮動小数点数の指数部分を取り出して整数型の値にするような
    命令はあった方が良いのかな?
    今ある命令の組合せで簡単に書けるけど、やはりOCamlでは表現できなかったり…。 -- buyobuyon (2007-01-11 15:49:35)
名前:
コメント: