[性能优化 ] 化绝对为相对

1. 核心思路

站在巨人的肩膀, 不香吗? 何必重新计算? 重复的计算是阻碍计算机性能发挥的一大杀手. 假设给我一个数列, 通项和递推关系, 我一定会选择后者, 花费计算可能更少, 效率更高.


2. 乘2 vs 左移?

众所周知, 遇到2的指数, 通过左右移可以快速计算.
但是请注意!

假设我想要计算 (a-b)/2的平方, 例如 a=14, b=29. 我们知道答案应该是 49 (以计算机整数计算)

    int a = 14;
    int b = 29;
    
    int err = ((a-b)>>1) * ((a-b)>>1);
    int crt = ((b-a)>>1) * ((b-a)>>1);
    
    printf("err=%d, crt=%d\n",err, crt);

运行后发现

在这里插入图片描述

在进行左右移运算时, 请务必检查目标数的正负符号, 否则符号位将会被一起移动, 导致结果大相径庭. 具体可百度二进制有无符号数 及 补码运算 进行了解.


3. 绝对指针 vs 迭代指针 ?

循环迭代是编写程序的家常便饭. 尤其是在迭代访问数组内存.

绝对指针是指每次都计算出该指针的偏移量指向, 不移动迭代器, 而是通过基地址计算而来的, 例如

for( int y=0; y<img_h; y++ ){
        for( int x=0; img_w; x++ ){
            size_t index = (ys+y)*(info_MainScreen.width)+(xs+x);
            
            info_MainScreen.pBuffer[ index ].R = xxx;
            info_MainScreen.pBuffer[ index ].G = xxx;
            info_MainScreen.pBuffer[ index ].B = xxx;
        }
    }

index 就是访问的索引偏移量. 每次计算index都需要耗费乘法运算, 相当累赘.

不妨…


Image_t* pIter = info_MainScreen.pBuffer + (ys)*(info_MainScreen.width)+(xs);

for( int y=0; y<src->height&&y<dst->height; y++ ){
        for( int x=0; x<src->width; x++,pIter++ ){
            pIter->R = xxx;
            pIter->G = xxx;
            pIter->B = xxx;
        }
        pIter -= src->width;
        pIter += dst->width;
    }

这样的迭代仅使用了++运算符. 很高效.

二维数组请格外注意迭代的内存对齐宽度

当然, 使用绝对地址index有助于我们DEBUG, 方便查看索取的索引是否正确. 各有利弊.



4. 公式代入计算 vs 前后做差计算 ?

在求一个函数的离散值时, 也许可以通过通项获得其递推关系, 利用递推节省算力.

以下 A采用直接代入函数求值, B则采用函数的递推进行累加.

    const ys = 70, ye = 80;
    int A = 0;
    for( int y=ys; y<=ye; y++ ){
        A  = (y-((ye+ys)/2))*(y-((ye+ys)/2));
        
        printf("A=%d\n", A);
    }

    int B = ((ye-ys)/2)*((ye-ys)/2);
    for( int y=ys; y<=ye; y++ ){
        printf("B=%d\n", B);
        
        B += 2*(y+1)-(ye+ys) -1;
    }
    

在这里插入图片描述在这里插入图片描述

两次的运行结果是相同的, 然而A使用了乘法, 而B只是用了累加.
当然, 你可以将 /2改成>>1, 就更高效了哦. 注意事项见上文.

推导证明, 日后有空再写~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值