【发布时间】:2013-12-31 01:22:46
【问题描述】:
我有一个 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 的帧速率。现在我想有一种更有效的方法来做到这一点。
正如您所注意到的,我已经将所有除法更改为乘法,但这对性能影响很小。
我怎样才能提高这个数学繁重的函数的性能?
【问题讨论】:
-
考虑到您在 4 中执行此操作,它可能非常适合转换为 SIMD(例如 SSE 内在函数),特别是如果您不介意使用浮点精度。
-
在我看来,A、B 和 C 值是完全独立的。为什么不生成 4 个线程,每个 sineX 一个线程?
-
您将
/ 300替换为* 0.00333似乎表明您对准确性的期望极低。通过使用sinf(写得很好的sinf比sin快)和单精度变量和常量,使整个计算成为单精度。它仍然比0.00333更准确,是1/300的精确近似值。 -
出于兴趣,该函数的目的到底是什么?从维度 POV 来看,
sin * sin(sin + sin) + sin已经够奇怪了,但这完全取决于当前系统时间?那有什么作用? -
我不知道为什么我的问题被搁置了?我的代码中有一个瓶颈,因为我经常调用 sin 函数,有什么解决方案可以解决这个问题?我不明白这是多么广泛。但如果是的话,我很抱歉。
标签: c performance math optimization trigonometry