创建一个快速Sine()函数来改善fps?快速正弦()函数?

时间:2012-10-24 02:19:28

标签: c++ c performance math sin

我实时渲染500x500点。 我必须使用atan()和sin()函数计算点的位置。通过使用atan()和sin(),我得到 24 fps (每秒帧数)。

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

如果我不使用sin(),我会得到 52 fps

如果我不使用atan(),我 30 fps

所以,最大的问题是sin()。我怎样才能使用Fast Sin版本。我可以为此创建一个查找表吗?我没有任何特定的值来创建LUT。在这种情况下我该怎么办?

PS:我也尝试过快速的ASM功能,但没有任何区别。

感谢。

4 个答案:

答案 0 :(得分:10)

等一下......

你有一个三角形,你正在计算低能量。首先,您需要atan(value)获取角度,然后再次使用valuesin来计算h。所以我们有三角形的一边是1的场景:

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

你真正需要做的就是计算h = sqrt(value*value + 1); ......但是,sqrt并不是最快的函数。

也许我错过了这一点,或者你已经遗漏了一些东西。我总是使用sincos的查找表,发现它们很快。如果你不提前知道值,那么你需要近似,但这意味着乘法,截断为整数(并可能是符号转换)以获得数组索引。如果你可以将你的单位转换成整数(有效地使你的浮点数成为定点),它会使查找更快。

答案 1 :(得分:6)

这取决于您需要的准确性。 sin的最大导数是1,所以如果x1和x2在彼此的epsilon之内,则sin(x1)和sin(x2)也在epsilon之内。如果您只需要精确到0.001,那么您可以创建一个1000 * PI = 3142点的查找表,并只查找最接近您需要的值。这可能比本机代码更快,因为本机代码(可能)使用多项式系数的查找表,然后进行插值,因为这个表可以小到足以容易地保留在缓存中。

如果你需要在整个范围内完全准确,那么你可以做的更好。

如果你愿意,你也可以在(1 / sin(x))上创建一个查找表,因为那是你感兴趣的实际功能。无论哪种方式,你都要小心sin(x)= 0,因为sin(x)中的一个小错误会导致1 / sin(x)出现大的错误。定义容错对于确定可以采用的快捷方式非常重要。

您可以使用以下内容创建查找表:

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

并将访问类似

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

此代码未完成(将崩溃,因为数组范围超出0&lt; x&lt; 1以外的任何内容),但应该让您入门。

答案 2 :(得分:2)

对于罪(但不是atan),你实际上可以比表更简单 - 只需创建

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 ];

我的猜测是,这会让你提速。

答案 3 :(得分:1)

我碰巧偶然发现了这个开源的javascript库,它包含了一个有趣的三角函数近似值(sin和其他的tan)。 它似乎快速而准确。
也许你可以用c / c ++重写它。
图书馆:http://danisraelmalta.github.io/Fmath/