FPGAでsqrt(x)の小さい値の近似を実行する方法


8

私はの値の計算を含む固定小数点ルーチンを実装しようとしています x 小さい x 近づく 0。ターゲットアーキテクチャはFPGAです。1つの問題は、この関数がテイラーの展開の使用に向いていないことです。xの値が小さい場合、x 無限に行くとき x アプローチ 0、したがって、べき級数を使用して関数を評価するには、巨大な係数に小さな係数を乗算する必要があります x。したがって、この方法は数値的に不安定です。

Newton-Raphsonは、反復アプローチを使用して、次の反復方程式を生成します。 xn+1=xn2α2xn、近似しようとしているところ α。しかし、もう一度、α 小さいです、 xn同様に、解が収束するためには小さくなければなりません。方程式には小さな数値を別の小さな数値で除算することが含まれるため、固定小数点演算が失敗する可能性があります。

それで、小さな値の近似を実装する方法を知りたいです x 事前計算された係数または反復法を使用して、固定小数点演算を使用します。


2
FPGAをターゲットにしている場合、最初の最も重要な質問は、どの精度が必要かということです。あなたはフィックスポイントを使いたいと言います:入力にどの精度、結果にどの精度?固定小数点(整数など)では、「ゼロに近づく」ことはできません。あなたが興味を持っているだけで最小の数があります。
フィリップ

回答:


5

以前使用したルーチン(「適切な」ものかどうかはわかりません)は、分割統治法です。

まず、任意の上限値と下限値(たとえば、それぞれ5と0-検索する最大および最小の平方根)から始め、それらの間の中間点を見つけます。その値を二乗します。

二乗値がターゲットより大きい場合は、上限値を二乗値に設定します。低い場合は、低い値を設定してください。

二乗値がルックアップ値と一致するか、必要なだけ正確になるのに十分な反復を実行するまで繰り返します。

これは私がperlで一緒にノックした小さなバージョンです:

#!/usr/bin/perl

my $val = shift;

my $max = 5;
my $min = 0;

my $iterations = 0;
my $maxiter = 40;

while(($max > $min) and ($iterations<$maxiter))
{
    $iterations++;
    my $diff = $min + ($max - $min) / 2;
    my $square = $diff * $diff;

    if($square == $val)
    {

        print "Square root found at $diff\n";
        print "$iterations iterations\n";
        exit(0);
    } else {
        if($square > $val)
        {
            $max = $diff;
        } else {
            $min = $diff;
        }
    }
}

my $diff = $min + ($max - $min) / 2;
print "Approximate square root after $iterations iterations: $diff\n";

もちろん、これは浮動小数点を使用していますが、固定小数点に簡単に適合させることができます。反復制限を変更することにより、精度を変えることができます。各反復は、以前の反復よりもわずかに正確になります。

例:-9の平方根を求めます。

Approximate square root after 40 iterations: 2.99999999999955
   - or - 
Approximate square root after 10 iterations: 3.00048828125
   - or - 
Approximate square root after 5 iterations: 3.046875

値3が見つかった場合は、当然、早い段階で停止していました。

十分な反復を与えると、非常に正確になります。

./sqrt.pl 0.00284
Square root found at 0.0532916503778969
59 iterations

2
基本的に二分探索。
rfusca

開始値を選択する方法を知っていますか?
Ang Zhi Ping

これは、処理することが予想される最大数の平方根です。
Majenko

4

ここに、アセンデッドの超越的マスター/グルスコットダッタロのアイデアとルーティンをいくつか示します
それはもちろんグル(グル?)部分を除いて冗談です。スコットは素晴らしいです。

関連する議論。 2005&PICと一部はCですが、価値があるかもしれません。

スコット再び-2003

二人のマスター!!!
ダッタロとゴロフチェンコ。
さまざまな方法


3

「小さい値」または「近似値」で何を意味するのかを指定しなかった。だから私が提案しようとしていることはうまくいかないかもしれませんが、ここに行きます。

最も簡単なのは、ルックアップテーブルを作成することです。基本的に、アドレスバスが平方根にする数値であり、データ出力が結果であるROM。1つのBRAMで、9ビット入力、8ビット出力のLUTを実行できます。もちろん、より多くのBRAMはより大きなテーブルを提供します。

(BRAM = ROMとしても使用できるブロックRAMのザイリンクス用語。他のFPGAにも同様の機能があります。)

BRAMが提供するよりも高い精度が必要な場合は、2つのLUTエントリの単純な線形補間を実行できます。たとえば、12ビットの入力が必要で、BRAMは10ビットしかないとします。入力の上位10ビットを取り、それをLUTで調べます。それらの10ビットに1を加えて、その値も調べます。次に、2つの結果の間で単純な線形補間を行い、下位2ビットを使用して、ある値と他の値の比率を示します。もちろん、これは近似値を与えるだけですが、数学をやれば、それで十分かもしれないと思うでしょう。

この方法は低い値の数値では最も精度が低くなりますが、入力がより高い値になると精度はさらに高くなります。

上記の方法の最適化は、BRAMをデュアルポートROMとして使用することです。このようにして、使用するBRAMの数を増やすことなく、2つの値を読み取ることができます。これにより、すべてのクロックサイクルのSQRTを計算できます。

ちなみに、この方法はSINE / COSINEでも機能します。


小さい値は、xが0に近づくことを意味します。そのため、\ sqrt {x}の小さい値の近似に興味があります。
Ang Zhi Ping

1
@angzhiping "ゼロに近づく"は役に立ちません。範囲と精度を知る必要があります。あなたが与えたのは範囲の半分であり、正確さはありません。最終結果は、入力ビットと出力ビットの数を知ることです。また、必要な速度も重要です。クロック速度とsqrtあたりのクロックの観点からです。

3

次のアプローチを試してください

  • 数値が負の場合は、それに応じて処理してください。
  • 数値が0の場合、0を返します。
  • さもないと:
  • [1/4、1]の範囲内の数値に正規化する:x <<= 2上記の範囲内になるまで、kに4(Cで)を掛ける必要がある回数をカウントします。
  • 任意のアプローチ(多項式近似、sqrt a [n] =(a [n-1] + k / a [n-1])/ 2のニュートン法)を使用して、この範囲内の平方根を計算します
  • 非正規化:kビット右シフト

0

試す x=(y+d)2y2+2dy そうしましょう d=(xy2)/2y=(x/yy)1 そして次は y=y+d. MSbが右からnの場合、最初にy=1(n/2)。4回未満の反復で収束します。


0

試してください:第1変数の推測の改善

あなたの数は次のように考えることができます:A * 2 ^ n
最初の近似は次のようになります:A * 2 ^(n / 2)

32ビットの数値を使用していて、小数部の保持に24ビットが使用されているとします。数値> 1の場合:
1.整数部分で使用されるビット数をカウントします(N)
2.この数を半分にします(N '= N / 2、つまり1ビット
右シフト)3.元の数をN'右シフト:これはあなたの最初の推測です。

この形式では、最小数は2 ^ -24です。平方根は約2 ^ -12になります。したがって、1未満の数値の場合は、1
。セットビット(N)に到達するまで、小数部の「ゼロ」ビットの数をカウントします
。2.この数を半分にします(N '= N / 2、つまり1ビット右シフト)
3.元の数を変更後の数だけ左にシフトします。これが最初の推測です。

例:
0.0000 0000 0000 0000 1 [16個の先行ゼロ]は次の値に近似します:0.0000 0000 1

最後に、小さいAでまだ問題がある場合は、1 / Aを計算できますか?
もしそうなら、あなたの数を逆にし、そして逆平方根アルゴリズムを使ってみてください:
x' = 0.5x * (3 - Ax^2)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.