2017-07-11 5 views
0

開発したプロセッサ(sparcアーキテクチャ)を使用して、ボード上のベアメタルプログラム(OSなし)で時間のかかるアルゴリズムを実行しています私たちのチーム、gcc elf toolchainを使用しています。ソフトフロートではうまく動作し、1時間以上経過しても望みの結果が得られます(純粋にソフトウェアが実行され、後の特別なハードウェアで大幅に短縮されます)。しかし、ハードフロートを使用して、私は15 minuites、良い結果でそれを行うことができます。 OKですが、ハードフロートの設定の中には、exp()関数が正しく動作していないことがあります。この場合、浮動小数点数を正しく印刷したい場合です。私はEXP()関数をテストするためのテストコードを書いているelf-gccでは、最初の呼び出しでexp()が正しく動作しません。

は、

ab_printf("------- exp test--------\n"); 
float a[5] = {-0.438984, -0.357934, 0.174203, 0.280720, 0.372380}; 
for(i=0;i<5;i++){ 
ab_printf("x = %f, y = %f\n", a[i], 1./(1.+exp(-1.*a[i]))); 
} 
ab_printf("------- end of exp test--------\n"); 

私は(Makefileの-msoft-フロート付き)ソフトフロートを使用して、私は正しい結果を得ることができます。

------- exp test-------- 
x = -0.438984, y = 0.391983 
x = -0.357934, y = 0.411460 
x = 0.174203, y = 0.543441 
x = 0.280720, y = 0.569723 
x = 0.372380, y = 0.592034 
------- end of exp test-------- 

その後、私はハードフロートに切り替える(ハードウェアFPUを使用して、=ハードウェア浮動小数点命令を生成するために-msoft-floatを除く)が、私はEXP()関数は、ソフトウェアを使用してツールセットによって実装されます理解しています。 (CPUにはexp命令がないので、ツールチェーンライブラリはテイラー展開などを使用します)。ハードフロートを使用する場合は、以下のようにリンカーに2つのライブラリを使用します。

LIBS  += -L/opt/abde/lib/gcc/sparc-ab-elf/4.6.2/soft/v8 # line 1 
LIBS  += -L/opt/abde/sparc-ab-elf/lib/soft/v8 # line 2 

私が代わりにライン1におけるソフト/ V8でのV8を使用している場合はそれはオプションではありませんので、フロート番号を印刷する場合、プログラムが停止します。私のツールセットは正しく構築されていないと思われますが、私のシステムでは今構築できません。

2行目のソフト/ v8の代わりにv8を使用すると、浮動小数点数の文字化けしたデータが表示されます。しかし、私はこのセットアップで良好な検出結果を得ることができると知っていますが、処理が進むにつれて小さな浮動小数点エラーが発生することがわかります。このセットアップではexp()関数もとにかく動作します(したがって、 。私はI = 0から実行すると、ハード・フロートモードでは、それは私にこの結果(初回のみ1が正しい働いていた)を与える

:私はI = 1からそれを実行したとき

------- exp test-------- 
x = -0.438984, y = 0.391983 
x = -0.357934, y = 1.000000 
x = 0.174203, y = 1.000000 
x = 0.280720, y = 1.000000 
x = 0.372380, y = 1.000000 
------- end of exp test-------- 

を、それが私にも(正しい、最初の1つだけ)

------- exp test-------- 
x = -0.357934, y = 0.411460 
x = 0.174203, y = 1.000000 
x = 0.280720, y = 1.000000 
x = 0.372380, y = 1.000000 
------- end of exp test-------- 

これはどのような場合ですか?問題は、今私のシステムでツールチェーンを構築できないことです。

+0

おそらく1つの可能性は、ab_printf処理の中にハードウェアの浮動小数点が混乱している可能性があります。その理論をテストするために、結果をループ内の配列に格納し、後のループからのみ出力することができます。 –

+0

それは良い推測だ、私はそれを試みたが、それは事実ではなかった。ありがとう! –

+1

'sin'、' atan'などの他の 'math.h'関数の結果が乱れているのですか、' exp'に特有の問題ですか?出力のためにfloatを10進数に変換するコードが 'exp'を実行するコードよりかなり複雑になる可能性があるので、' printf'の問題も考慮に入れておいてください。 –

答えて

0

プログラムをdouble値ではなく浮動小数点数で動作させます。 1.0のようなリテラルを使用すると、doubleです。代わりに1.0fを使用してください。 expはdoubleパラメータをとり、doubleを返します。 + exp(-1。* a [i])は[i]をdoubleに変換し、次にdouble演算を行い、次に再びfloatに変換します。これは精度に非常に重要な影響を与えます。 FPUが使用する数値(32または64ビット)はわかりません。それらをすべてFPUのものと同じにします。それはフロート印刷usinbのab_printfに問題があるように見えますが、float型(expf、EXP、正しくありません)に応じて、異なるEXP機能を持っている

ノート

+0

float、doubleには関係していないことを確認しました。明示的なインデックス0,1,2,3を使用してループなしで印刷すると、それはokを出力します。 ab_printf関数はループ内でfloat..inで印刷するときに問題があるようです。 –

+0

どうやって確認しましたか?あなたはそれらを浮かせるようにしましたか? –

+0

ab_printf( "x =%f、y =%f \ n"、a [0]、sin(a [0]))のように印刷すると、ab_printf( "x =%f、y =%f \ n"、a [1]、sin(a [1])); ab_printf( "x =%f、y =%f \ n"、a [2]、sin(a [2]));ab_printf( "x =%f、y =%f \ n"、a [3]、sin(a [3]));ab_printf( "x =%f、y =%f \ n"、a [4]、sin(a [4])); (i = 0; i <5; i ++)ab_printf( "x =%f、y =%f \ n"、a [i]、sin(a [i]))を使用した場合は、 が表示されます。 ;それは正しく印刷されません、値は間違っています。フロート/ダブル問題ではありません。 –

-1

。私は他のプラットフォームにフロートを印刷する別の問題があることがわかりました。 (https://github.com/esp8266/Arduino/issues/341)。

LIBS  += -L/opt/abde/lib/gcc/sparc-ab-elf/4.6.2/soft/v8 # line 1 
LIBS  += -L/opt/abde/sparc-ab-elf/lib/v8 # line 2 

このセットアップは私がフロートのprintf以外に何の問題もなく、ハードフロートを使用することができます:だから私は、このセットアップを使用することにしました。浮動小数点値を出力するように私は(int。)(1 ./(1。+ exp(-1。* a [i]))* 10000)。10進整数のプリントを使用します。誰かが別の良い解決策を得ることができることを願っています。

+0

詳細: 'ab_printf(" y =%f \ n "、1 ./(1. + exp(-1。* a [i])));) - ' float'を出力するのではなく、 「ダブル」。おそらく誤って動作する 'ab_printf()'は生の 'float'を出力することができますか?お試しください。 'float F = 1./(1.+exp(-1.*a[i))); ab_printf( "x =%f、y =%f \ n"、a [i]、F); ' – chux

関連する問題