C:使用沉重的sin()来提高功能的性能

 郝韵G 发布于 2023-02-07 13:47

我有一个C函数,它根据经过的时间计算4个正弦值.使用gprof,我认为这个函数使用100%(100.7%确切地说是lol)的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的帧速率.现在我认为这是一种更有效的方法.

正如您所注意到的那样,我已经将所有划分更改为乘法,但这对性能的影响非常小.

我怎样才能提高这个数学重函数的性能?

1 个回答
  • 除了在其他答案中给出的所有其他建议,这里是纯粹的算法优化.

    在大多数情况下,您正在计算某些形式sin(k * a + b),where abconst常量,并且k是循环变量.如果您还要进行计算cos(k * a + b),则可以使用2D 旋转矩阵来形成递归关系(以矩阵形式):

    |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)并且sin(a)哪些是常量).所以你消除了75%的trig函数调用(目前还不清楚可以为最终的trig调用集拉取相同的技巧).

    2023-02-07 13:48 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有