過去の履歴です
●2/24,25
・atanのテスト終了
-ランダムな100万入力に対してテスト
-仮数部末尾1bit分の誤差のみ許容
・cosのテストにミス発見
-sinの入力は -2^30<=x<=2^30 としたが、cosではこれだと絶対値の大きな数で
仮数部の後ろから5bit分程度の誤差が現れるので、-2^20<=x<=2^20とした。
・invのテスト終了
-以前アップしたプログラムに比べて、初期値の場合わけを増やすことで、浮動小数全体の範囲からの入力を受けられるようにした
-ランダムな100万入力に対してテスト
-仮数部末尾1bit分の誤差のみ許容
・finvsqrtのテスト終了
-invと同様
・作ったものについては一通りテストが終わったので、テスト用プログラムと、テストの結果に従って調整したライブラリ
のファイルをこのページにあげておきます
・50MHzではINV,FINVSQRTはライブラリよりもFPUを使ったほうが速いはず
●2/21
・sin,cosについて、ランダムな100万パターンの入力に対しテストし、ライブラリ内でのループ回数を
精度が落ちない程度に極力少なくしました(19->9)
-入力は -2^(30)<= X <= 2^(30) の範囲のもののみ採用
-誤差は仮数部の末尾1bit分のみ許容(符号、指数部は完全一致)
-cosに対しては、入力が小さい(0に近い)場合に、
Perlのライブラリ(double型で処理)の結果が"00111111100000000000000000000000"
作成したライブラリの結果が "00111111011111111111111111111111"
となる。これも許容した
- FPUについての質問です!
入力信号にCLKが入ってるけど、これって使う予定ありますか?
-- yastak (2007-02-23 21:15:42)
- 使う可能性はあります。
FINVSQRTはどうしても1clockには入らないので、
パイプライン化するときにCLKを読む必要があります。
また、現時点ではFADD,FSUBも50MHzで1clockの動作が
できていないので、パイプライン化が必要になってCLK
を使うことになるかもしれません。
逆に、1clockに収まらない命令のパイプライン化を諦めたり、
FINVSQRTをライブラリで実現するのならCLKなしにすることも
出来る(?)かと思います。 -- tsuy (2007-02-23 22:43:23)
- 了解です。ありがとう~。 -- yastak (2007-02-23 23:03:26)
●2/19・20
・引き続きライブラリのテストプログラムを作成中
・sinの入力について、非常に小さい数の場合は正しく動くことを確認
・大きい数の入力も10の9乗程度までは正しく動いているらしい(?)
・それ以上になるとうまく動いていない
-ライブラリが悪いのかテスト方法が悪いのかテストプログラムが悪いのか
-floatで円周率を表した場合、10^(-7)< ε <10^(-6)となる誤差が入る
ため、入力があまりに大きいと結果が全く違う値になるらしい(これに気付くのに6時間かかったorz)
(テストの比較用データはdouble型の入力を使ったので、floatよりある程度
大きい入力まで真の解に近い値になる)
-というわけで、ライブラリのsin、cosはあまり大きい数(10^9程度以上?)を引数に
取らないということに勝手に仮定してテストしますが、問題ありませんよね?
●2/17
・ライブラリのテスト用のプログラムを作っています
-FPUの時と似た感じのもの(入出力ファイルから読みだして計算)にしようかと思っています
-平方根や逆数の実現はどうしましょうか。それによってライブラリのINVやFINVSQRTを使うかどうか
変わってくるので、テストの手間が大幅に変わってくるのです
●2/13
・FADD,FSUB:562,26.884ns -> 546,26.151ns
-うまくやればシフトの回数を減らすことで大幅に高速化できそうなのですがうまくいきません
・FPUに乗せる命令なのですがINVを外してFINVSQRTを乗せるということでいいでしょうか。
そうすれば割り算はライブラリを利用しないで出来るし、
平方根を求める場合に使うライブラリのINVは
ライブラリのFINVSQRTに比べて簡単に出来るので有利かなと思うのですが。
(もしくはFPU上でFINVSQRTの結果2つを掛け合わせたものにFINVSQRT
の方がいいのかな?)
・ライブラリで何を実装すればいいのかいまいちわかりません。
int_of_floatとかprint_intとかcreate_arrayとか通信ライブラリも必要なんですかね?
- create_arrayはコンパイラに組み込まれています。
int_of_floatあたりは後で組み込むつもりです。
基本的に、1命令に対応するようなものは、コンパイラの方でなんとかしますので、
浮動小数点数演算を実装していただければ。
FADDの高速化、やってみたいけど、コンパイラが…。
レジスタ割り付け難しい…(&面倒…)。 -- buyobuyon (2007-02-14 13:11:30)
- なるほど、了解しましたー。
レジスタ割付頑張ってください -- tsuy (2007-02-14 20:25:16)
●1/24
・FMULのアンダーフロー処理を外してみました
-18.784ns->17.396ns
-1clockに収めるのは厳しいかも?
●1/2
・あけましておめでとうございます
・年末は風邪で寝ていました
・ライブラリについて、とりあえず必要そうなものについて
C言語で書いたものをOCamlで書き直してみました。
・精度等は後で考えるとして、大体それなりに動くものをアップしておきます
・こんな方針でいいですかね?
・明日からは溜まっている連続形の課題をやります
- あけましておめでとうございます~!
風邪大丈夫ですか?お大事にしてください(>_<)
私も課題ためてます…。お互い頑張りましょう! -- yastak (2007-01-03 01:27:37)
- クロックについて。
1月は25MHz案、了解です~! -- yastak (2007-01-03 01:28:43)
- どうもありがとうございます
連続系難しいです… -- tsuy (2007-01-03 09:27:43)
●12/21
・昨日の話を受けて、FADD,FSUB,FTOIに入力が0.0のときの例外処理を入れました。
-何故かFADD,FSUBは速く、FTOIは小さくなりました。意味がわかりません
・百万入力に対するテスト終了
-FADD,FLESS,FTOI,ITOF,INV,FSUB,FINVSQRT問題なし
-FINVSQRTの初期値はテストでの確率的にも大丈夫なはずだし、ソースを見て
直すべきだろうと判断できる部分はすべて直したので多分大丈夫
-全命令で仮数部末尾1bit分以内の精度
・アンダーフローの実装は必要ないそうです
-来年はずします
●12/20
・INVの誤差を修正しました
-初期値の表のミスでした
-Gbit切り上げより切り捨てのほうが精度が良い
・FINVSQRTの誤差を修正しました
-これまた初期値のミスでした
-プログラムで自動生成した初期値は所々1bit分ずれていて、そのずれが出力の大きな差になる
-今回のテストで判明しなかった初期値ミスがあるかもしれない…!
・今度は百万パターンの入力についてテストを行っています
-出力ファイルを作るだけで1つの命令につき15分かかる…
-とりあえずFMULは問題なし
・テストで判明した問題なのですが、指数部が"00000000"だが仮数部は0でない入力はどうしましょうか
-そのような数をFPUの入力として与えないようにするか、FPU内部で0.0として判断するようにするか
-そのような数を0.0として判定するようにすると、そのための遅延時間と回路サイズがかかる
<- 0.0として判定するようにした方が早いと思うんだけど…。そもそもだいたいの関数は0.0に関して例外的な処理をしないといけないんだから、むしろ指数部だけで0が判断できた方が良いと思うんだけど…。明日FMULを改造してみたいのですが…。(buyobuyon)
<- 扱う値が0.0かどうかの判断は指数部のみ見るということは確定しています。それとは別の問題として、FADD,FSUB,FTOIに関しては、入力のビット列がすべて0のときは例外として扱わなくても正しい答えが返ってくるのですが、仮数部が0でないような0.0が与えられると答えがずれるので、例外として扱う必要が出てくるわけです。それ以外の命令では、おっしゃるとおり、指数部だけで0.0かどうか判定し、例外処理するようにしています。(tsuy)
<- わかるようなわからないような…。0.0以外なら演算時に仮数部の一番上に'1'を連接しなければならなく、0.0なら'0'を連接しなければならないはずですよね。でも例外として扱わなくて良いの?って、実際に手を動かしているtsuyさんがそうおっしゃっているのだからそうなのだろうけど…。私も手を動かして落とし穴にはまってみるか。ってそんな暇があるならコンパイラをやりなさい、私。(buyobuyon)
<- すいません、どうやら手動でのテストに見落としがあったようです。仮数部の先頭に'1'を連接したあとの、指数部の差によるシフト量が大きい場合しかテストしていなかったので、仮数部に加えるシフト後の数が0になっていたようです。結局、入力が0.0の場合の例外処理は入れる必要があるわけですね。ご指摘ありがとうございます。(tsuy)
●12/19
・50MHZ・1clockで動かす場合の遅延時間の目安は15ns
・オプションのI/Oバッファが勝手に付いているせいで、本来よりも約5ns遅くなっていた
-FLESS,FTOI,ITOFは1クロックで動くらしい
・オーバーフロー、アンダーフロー、入力・出力がNaNの場合は未定義でよいと勝手に仮定して、
とりあえず100パターン入力で誤差のみを見るテストを行いました
-FMUL,FADD,FSUB,FLESS,FTOIは問題なし(FMUL、FADD、FSUBは仮数部の末尾分のみの差、FLESS、FTOIは完全一致)
-ITOF,INV,FINVSQRTで問題があった→ITOF修正(しかしサイズ2倍)その他の命令の修正は明日
●12/18
・FMULについて100パターンの入力に対してテストし、誤りを訂正しました。
-オーバーフローは無視するとして、アンダーフローは処理する必要あるんでしたっけ?
-無視していいならFMULの精度に問題なし
●12/16、17
・来週あたりには帰省しないといけないので、大急ぎでFPUテスト用プログラムを書いています
とりあえず、
1:ランダムに作成した入力ビット列ファイルを用意する
2:1を読み込んだFPUから出力されたビット列を書き込んだファイルを用意する
3:Perlで1から読み込んだビット列を小数に変換してPerl上で演算する
4:3をビット列に変換して2のビット列と比較する
5:4で相違があればそれを出力
6:3~5を数百万パターン繰り返す
という感じにしようかと思っています。
問題はperlの小数が倍精度なのですが、それで問題無いかということです。
FPUが扱うのは単精度なので、それよりは精度が高いから大丈夫だろうと高を括っているのですが、
どうでしょうか。
- ↑別に問題ないと思いますが…。でもなぜPerl?(buyobuyon)
- 丸めの問題とかで必ずしもビット列は一致しないだろうから、どの程度ずれているかのレベルに応じて出力を区別した方が良さそうですね。(buyobuyon)
- あと、NaNなどの例外的な値に対する挙動は別にやった方がいいのかな?一応手動ではやってたよね?(buyobuyon)
- Perlなのは教官の方がおっしゃていたからです。実際使ってみると、ビット列の文字列が扱いやすいので、これでいいかなと。(tsuy)
- 丸めの問題については、仮数部の末尾1bitの相違のみ見逃して、それ以外は結果のビット列等を出力ということにする予定です。(tsuy)
- 非正規化数に対しては、FPUでサポートしないことにしたので、例えば入力がNaNである場合やオーバーフローする場合はノーチェックで通そうかと思います。(tsuy)
- ビット列を比較して仮数部末尾1bitの相違のみOKってことはもしかして、例えば仮数部を8bitだとしたときに、仮数部が "01111111" と "10000000" であったらNGとされてしまうわけ?(buyobuyon)
- 非正規化数サポートしないって、コンテストルール上大丈夫なんだっけ?(buyobuyon)
- 仮数部末尾1bit「分」の間違いでした。仮数部を整数に変換して、その差が1以内だったらOKということにします。その例だと127と128なので問題ないと判断します。(tsuy)
- 5班6班の方々は非正規化数はサポートしていないそうです。ルールの方もそれで大丈夫だったかな…?(tsuy)
●12/14
・非正規化数の処理をはずしました
・それぞれのサイズを合計すると30%と、ぎりぎり入りそうなのですが、FPU全体として
コンパイルすると38%になるのでサイズオーバー
・さらに、18×18の乗算器の数が足りない(最大40個で、現在48個使っている)
・ライブラリについて、sin,cons,atanのC言語版を本から写して動作確認しました
・FMUL,FADD,FSUBは出来れば20ns以内に収めたいが、全然うまくいかない
●12/13
・FINVSQRTをニュートン法で実装しました
-516(10%)、104.486ns
-非正規数と、2,5,6,0.625,2^(-127)などで動作確認
-高速化→508(10%)、98.210ns
・上記のFINVSQRTでは初期値を8bit取りました
-一度計算するごとにどの程度真の答えに値が近づくか分からなかったので、
多めに精度をとった
-上記のものとは別に、初期値を7bitとったものも作りました
-443(8%)、97.727ns
-テストを行って精度に問題がなければこちらを使う
-いくつかの値で手計算をしたところ、問題はなさそう
・近いサイズのビット列同士の掛け算を分割することで高速化する場合は、
大体半分に分割すると速くなる傾向がある
逆に極端なわけ方をすると遅くなる
・6班の方にFPUについていろいろと教えていただきました
-シフトはSHL,SHRなどを使うといい
→速くなる場合と遅くなる場合、大きくなる場合と小さくなる場合がありました
ITOF:121(2%)、18.539ns→108(2%)、18.673ns
FTOI:172(3%)、18.365ns→170(2%)、18.371ns
FADD,FSUB:590(11%)、39.528ns→580(11%)、39.078ns
-非正規化数はいらないそうです
→近いうちに非正規化数の処理をはずします
●12/12
・INVを高速化しようとしたが…
-初期値を7bitから13bitに増やして繰り返し計算を1回に減らそうとした
-初期値のテーブルのファイルサイズが64倍(752kb)になり、10分経ってもコンパイルが終わらない
-ためしにテーブルでの条件分岐数を1/4に減らすと、遅延10nsでサイズ5%
->むしろ遅くなるし大きくなる
-この方法での高速化・省サイズは無理
-FINVSQRTがサイズ的に入らない場合は、CLKを読んで部品を使いまわすことも考える
->4クロックから6クロック以上に
->5%から3%に
・FADD,FSUBの高速化
-足し算、引き算を行いつつ、符号等の処理を平行して行うように(buyobuyon氏提案)
-かなり高速化・省サイズ化ができそうだったが、0.0やNaNの符号がマイナスになるなどの
問題を解決するうちに遅くなってきました
-スライス:629(12%)→590(11%)、遅延:41.493ns→39.548ns
-別のところで39.548ns→39.528ns
●12/8
・やはりFINVSQRTをハードで実装してみて性能比較することに
・性能比較して実際にFPU上で使用する命令を選んだ後は、テストを行って
誤差等に問題がないか調べれば終わりかな?
-使用する命令はFADD,FSUB,FMUL,FLESS,FTOI,ITOF,INVは多分確定
●12/7
・FINVSQRTを実装中
-計算が複雑で大きな誤差が入る
-やっぱりソフトウェア実装のほうがいいかも
●12/6
・INVを実装しました。
-初期値を4bitの精度で求めて3回計算を繰り返す方式と、
初期値を7bitの精度で求めて2回計算する方式で実装しました。
-4bitで3回→サイズ7%,96.895ns
-7bitで2回→サイズ5%,69.014ns
-というわけで後者を採用
-仮数部はGbit切り上げによる丸め
●12/1
・INVのためにNewton法を勉強
-VHDLでできるか不安だったけど、意外と何とかなりそう
-±Inf=>+0.0
-±0.0=>±Inf
-NaN=>Nans
●11/30
・itof
-20.620ns=>18.539ns(buyobuyon氏に多謝)
●11/29
・FADD,FSUB
-40.758ns=>41.493ns
-遅くなったがサイズが大幅に減ったので採用
-丸めをGbit切り上げに
●11/28
・FMULについて
-丸め方式をGbitの切上げに変更
-31.295ns=>28.036ns
・FLESS
-11.858ns
・ITOF
-22.419ns=>20.620ns
・FADD,FSUB
-42.831ns=>40.758ns
・回路サイズが一向に減りません
●11/22
・高速化と回路サイズの縮小
-ftoiが18.365nsの遅延で動くように
-itofがどうしても20nsきれない…
●11/21
・FADD,FSUB,FMUL,FDIVにオーバーフローとアンダーフローを実装
-いずれも
exp <= 0 ->+0
1 <= exp <= 254 ->Normal
exp >= 255 ->Inf
●11/16
・正規化数以外のサポートが全命令で終了
-詳しくは下記の仕様に
・今後は回路サイズを小さくする
●11/15
・正規化数以外をサポート
-詳しくは下記の仕様に
・FADD,FSUB,FMUL,FDIVが終了
●11/14
・SQRTのミスを修正
・FINVSQRTを実装しました
-SQRTとFDIVをそのまま利用しただけですが…
・正規化数は一通り対応できたはずなので、次は正規化数以外に対して
実装しようと思います。
-とりあえずグラデュアルアンダーフローなしで
●11/9
・とりあえず正規化数についてのみ一通り実装しております。
・FDIV,SQRTのミスを修正
・精度ってどのくらいあればいいんでしょうか?
●11/8
・SQRTのミスを修正
・FINVSQRTの実装を勉強しております。
・テストの方法を考え中です。
-昨日聞いた話だと入力信号をファイルで数百万パターン用意して読み出して出力を
別ファイルに書き込み、別のプログラミング言語(Perlがいいらしい)を用いて
入力の計算結果と出力の値を比較という方法がある(?)
●11/7
・FDIVを実装しました。
・SQRTを実装しました。
-2bitずつ筆算の様に計算する方式で実装しました
-入力が負ときにはNans(="0 11111111 10000000000000000000000")を出力
-仮数部をround evenで丸め
-入力の32bitは浮動小数でいいんでしたっけ?
●11/2
・function文の組み合わせ回路への書き換えは終わりました。
・現在FDIVを実装しております。
-0で割ったときにはNans(="0 11111111 10000000000000000000000")を返す
-とりあえず「ゲート数は多いがクリティカルパスはできるだけ短く」なるよう書いているつもりです。
-4bitずつ引き算処理を繰り返す方法で実装しています。
-クロックを利用する場合には同じ回路を使いまわして引き算処理を最小で9クロック繰り返す
->回路サイズ小さいが遅い?
利用しない場合には同じ回路を9つ繋げて繰り返しを処理する(利用しない方で実装しています)
->回路サイズ大きいが速い?
●11/1
・buyobuyonさんアドバイスありがとうございます
とりあえず一通り実装が終わったら速度の測定を行おうと思います
・現在functionで書いたものを同時処理文に書き換えています
-FMUL,FADD,FSUB,FLESS,ITOFが終わりました
●10/31
・現在FTOIの実装とFDIVについての勉強をしております。
-FTOIは小数点以下四捨五入
-結果がsigned intの最大値(最小値)を超える場合は INT_MAX(INT_MIN) を返す
-INT_MINって"10000000000000000000000000000001"でしたっけ?
-> "10000000000000000000000000000000"ですよ。
a_31 a_30 ... a_0 が -(2^31)*a_31+(2^30)*a_30+(2^29)*a_29+ ... + a_0 を表します。(buyobuyon)
- +0.0 -> +0 , -0.0 -> +0
・と思いましたが、先に順次処理でないものを作ろうと思います。
-速度の測定方法が分からない…
-> FPUの入り口と出口にフリップフロップを入れて、クロックに適当な周波数を設定して
合成ツールでコンパイルしたときの、警告が出ない限界の周波数を調べる、のかな?
VHDL周辺はよくわからない…。 (buyobuyon)
●10/30
・今後の予定
-正規数について一通りの命令を実装
-非正規数についてもサポート
-順次処理部分を極力減らす
-詳細にFPU動作確認を行う
-FPU高速化とライブラリ
-というつもりです
●10/27
・FADD、FSUBについて
-基本的には「符号を無視して、指数部・仮数部についてそれぞれ加・減算の処理を行う」という
働きをする
-オペランドの符合が一致する場合にはそのまま上記の処理
-一致しない場合には、オペランドの符号や絶対値の大きさによりオペランドの符号を変更し、
FADDならFSUB、FSUBならFADDに渡す。
例) FADD(-A,+B) -> (-A)+(+B) -> (+B)-(+A) -> FSUB(+B,+A)
-TAの方が「ADDができたならSUBは一瞬でできる」的なことをおっしゃっていたので、
もっとうまいやり方があるのかも
-- メモ(主に自分用)
●作ったものと同じ動作をするものをC言語か何かで作って、
VHDLで作ったものの結果と比較する
Cならunsigned int
普段使い慣れている言語で作るとミスが少ない
●余裕があればプライオリティエンコーダを入力数の少ないもの
の組み合わせで作って、性能を比較する
●余裕があればシフタの場合わけを数段に分けてみて性能を比較
●FSUBのプライオリティエンコーダやシフタはITOFのものを使い回していいのか
●FSUBの丸めは左シフトの前に行えばいい?
●FSUBは特に丸めがある場合の動作確認を念入りに行う
(MANT_buf = "111…1"で丸めにより繰り上がる場合など)
●FADD,FSUBではそれぞれの関数に投げるよりも、自分の関数内で条件分岐で処理を分けた方が
多分速い。ただし、コードはかなり乱雑になる。-> component化により解決
●プライオリティエンコーダはfunctionのままでも大丈夫なはず -> 結局同時処理で書いた
●functionでシミュレーションすると時間0で返る
やっぱり書き直しが必要 -> 書き直し終了
●プライオリティエンコーダ30
バレルシフタ33
●RountBit <= '1' when A(x downto y) /= "00…0";
●FADDについて、MANT_buf(27 downto 1)がすべて'1'となることはないので、
EXP + 2 は考えなくてよい
●FDIVは6bitずつや12bitずつ処理すればさらに速まる?
●SQRTの最初の1桁目の計算は、結果は決まっているので省略できる
●テストは、例えばファイルから数万パターン入力を読み込んで出力を別ファイルに書き、
Perl等でチェックする方法がある。
●SQRTの最後、when Nans = '1'の行とwhen Zero = '1'の行を入れ替えることで - 0 の扱いを変更可能
●FDIVの1/100の精度が悪い -> 訂正済
●回路サイズ
-FADDとFSUBの入り口をまとめる
-要らない回路(Sequent24to26とか)を削る
-丸めの見直し
-FINVSQRTの扱い
-クロックを入れる
-priority31とleftshifter31は速くて大きいのと遅くて小さいのができた
-fsub_sでは、priority31の入力の先頭の5bitがなので、条件処理を減らせる
-それにともないleftshifter31も条件処理を減らせる
-入力信号のサイズを減らす
-条件部分を代入式へ移動
最終更新:2007年03月02日 19:02