我有一个 C 函数,可以根据经过的时间计算 4 个正弦值。使用 gprof,我发现这个函数使用了 100%(确切地说是 100.7%,哈哈)的 CPU 时间。
void
update_sines(void)
{
clock_gettime(CLOCK_MONOTONIC, &spec);
s = spec.tv_sec;
ms = spec.tv_nsec * 0.0000001;
etime = concatenate((long)s, ms);
int k;
for (k = 0; k < 799; ++k)
{
double A1 = 145 * sin((RAND1 * k + etime) * 0.00333) + RAND5; // Amplitude
double A2 = 100 * sin((RAND2 * k + etime) * 0.00333) + RAND4; // Amplitude
double A3 = 168 * sin((RAND3 * k + etime) * 0.00333) + RAND3; // Amplitude
double A4 = 136 * sin((RAND4 * k + etime) * 0.00333) + RAND2; // Amplitude
double B1 = 3 + RAND1 + (sin((RAND5 * k) * etime) * 0.00216); // Period
double B2 = 3 + RAND2 + (sin((RAND4 * k) * etime) * 0.002); // Period
double B3 = 3 + RAND3 + (sin((RAND3 * k) * etime) * 0.00245); // Period
double B4 = 3 + RAND4 + (sin((RAND2 * k) * etime) * 0.002); // Period
double x = k; // Current x
double C1 = 0.6 * etime; // X axis move
double C2 = 0.9 * etime; // X axis move
double C3 = 1.2 * etime; // X axis move
double C4 = 0.8 * etime + 200; // X axis move
double D1 = RAND1 + sin(RAND1 * x * 0.00166) * 4; // Y axis move
double D2 = RAND2 + sin(RAND2 * x * 0.002) * 4; // Y axis move
double D3 = RAND3 + cos(RAND3 * x * 0.0025) * 4; // Y axis move
double D4 = RAND4 + sin(RAND4 * x * 0.002) * 4; // Y axis move
sine1[k] = A1 * sin((B1 * x + C1) * 0.0025) + D1;
sine2[k] = A2 * sin((B2 * x + C2) * 0.00333) + D2 + 100;
sine3[k] = A3 * cos((B3 * x + C3) * 0.002) + D3 + 50;
sine4[k] = A4 * sin((B4 * x + C4) * 0.00333) + D4 + 100;
}
}
这是 gprof 的输出:
Flat profile:
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls Ts/call Ts/call name
100.07 0.04 0.04
我目前使用此方法获得的帧速率约为 30-31 fps。现在我认为有一种更有效的方法可以做到这一点。
正如您所注意到的,我已经将所有除法更改为乘法,但这对性能影响很小。
我怎样才能提高这个数学重函数的性能?
除了其他答案中给出的所有其他建议之外,这是一个纯粹的算法优化。
在大多数情况下,您正在计算以下形式的内容sin(k * a + b)
, where a
and b
是常数,并且k
是一个循环变量。如果你还要计算cos(k * a + b)
,那么你可以使用 2D旋转矩阵 http://en.wikipedia.org/wiki/Rotation_matrix形成递推关系(矩阵形式):
|cos(k*a + b)| = |cos(a) -sin(a)| * |cos((k-1)*a + b)|
|sin(k*a + b)| |sin(a) cos(a)| |sin((k-1)*a + b)|
换句话说,您可以根据上一次迭代的值来计算当前迭代的值。因此,您只需要进行完整的三角计算k == 0
,但其余的可以通过这个递归计算(一旦你计算了cos(a)
and sin(a)
,它们是常数)。因此,您消除了 75% 的三角函数调用(尚不清楚是否可以为最后一组三角函数调用使用相同的技巧)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)