5

500x500ポイントをリアルタイムでレンダリングしています。atan()関数とsin()関数を使用して点の位置を計算する必要があります。atan()とsin()を使用すると、24 fps(フレーム/秒)が得られます。

float thetaC = atan(value);
float h = (value) / (sin(thetaC)));

sin()を使用しない場合、52fpsになります。

atan()を使用しない場合、私は30fpsです。

したがって、大きな問題はsin()にあります。FastSinバージョンを使用するにはどうすればよいですか。そのためのルックアップテーブルを作成できますか?LUTを作成するための特定の値はありません。この状況で私は何ができますか?

PS:ASMの高速正弦関数も試しましたが、違いはありません。

ありがとう。

4

3 に答える 3

11

ちょっと待って....

あなたは三角形を持っています、あなたは斜辺を計算しています。まず、atan(value)角度を取得し、次にを使用valueしてsinを計算しhます。したがって、三角形の1つの辺が1であるシナリオがあります。

   /|
h / | value
 /  |
/C__|
  1

あなたが本当にする必要があるのは計算することだけですh = sqrt(value*value + 1);...しかし、それでは、sqrtどちらも最速の関数ではありません。

おそらく私は要点を見逃したか、あなたが何かを忘れてしまったのでしょう。私はいつもsinとのルックアップテーブルを使用してきましcosたが、それらは高速であることがわかりました。事前に値がわからない場合は、概算する必要がありますが、これは、配列インデックスを取得するための乗算、整数への切り捨て(および場合によっては符号変換)を意味します。単位を整数で動作するように変換できる場合(効果的に浮動小数点数を固定小数点に変換できる場合)、ルックアップがさらに高速になります。

于 2012-10-24T02:50:34.997 に答える
6

それはあなたが必要とする精度に依存します。sinの最大導関数は1であるため、x1とx2が互いにイプシロン内にある場合、sin(x1)とsin(x2)もイプシロン内にあります。たとえば0.001以内の精度が必要な場合は、1000 * PI = 3142ポイントのルックアップテーブルを作成し、必要な値に最も近い値をルックアップできます。ネイティブコードは(おそらく)多項式係数のルックアップテーブルを使用してから補間するため、またこのテーブルはキャッシュに簡単にとどまることができるほど小さいため、これはネイティブコードよりも高速になる可能性があります。

全範囲で完全な精度が必要な場合は、おそらくこれ以上のことはできません。

必要に応じて、(1 / sin(x))を介してルックアップテーブルを作成することもできます。これは、実際に関心のある関数だからです。いずれにせよ、sin(x)の小さなエラーが1 / sin(x)の大きなエラーを引き起こす可能性があるため、sin(x)=0の周りに注意する必要があります。エラー許容度を定義することは、どのショートカットを使用できるかを理解するために重要です。

次のようなルックアップテーブルを作成します。

float *table = malloc(1000 * sizeof(float));
for(int i = 0; i < 1000; i++){
  table[i] = sin(i/1000.0);
}

それにアクセスするようなもの

float fastSin(float x){
  int index = x * 1000.0;
  return table[index];
}

このコードは完全ではありませんが(配列の境界のため、0 <x <1以外ではクラッシュします)、開始する必要があります。

于 2012-10-24T02:26:13.583 に答える
2

罪(アタンではない)の場合、実際にはテーブルよりも単純にすることができます-作成するだけです

float sin_arr[31416]; //Or as much precision as you need
for (int i=0; i<31416; ++i)
   sin_arr[i] = sin( i / 10000.0 );

//...

float h = (value) / sin_arr[ (int)(thetaC*10000.0) % 31416 ];

私の推測では、これにより速度が向上するでしょう。

于 2012-10-24T02:36:00.260 に答える