我有这行代码:
base_num = (arr[j]/base)%256;
此行在循环中运行,操作“/”和“%”需要大量资源和时间来执行。我想更改此行并应用位操作以最大化程序性能。我怎么能这样做?
感谢。
答案 0 :(得分:7)
如果base是2的n次方,则可以用右移n位替换除以它。然后,由于取整数的mod 256相当于取其最后的8位,因此可以将其与0xFF进行AND运算。或者,如果您使用256 * base然后将位移到右侧,则可以反转操作。
base_num = arr[j] >> n;
base_num &= 0xFF;
当然,任何半合半的编译器都应该能够为你做到这一点。
答案 1 :(得分:3)
将-O1
或更高版本添加到编译器选项中,编译器将为您执行此操作。
在gcc中,根据文档,-O1
启用-ftree-slsr
,
对树木进行直线强度降低。这可识别涉及乘法的相关表达式,并在可能的情况下用较便宜的计算替换它们。
这将替换模数,如果它是常数,则替换基数。但是,如果您知道基数将是2的非常数幂,您可以重构周围的代码,为您提供该数字的log2
,并>>
减去该数量。< / p>
答案 2 :(得分:1)
您也可以将base_num
声明为8位整数:
#include <stdint.h>
uint8_t base_num;
uint16_t crap;
crap = 0xFF00;
base_num = crap;
如果您的编译器符合标准,它会将byte(0xFF00)
(0x00
)的值放入base_num
。
我还没有遇到一个在普通C(C ++或C#都没有)中进行饱和算术的编译器,但如果确实如此,它会使sat_byte(0xFF00)
的值大于0xFF
,它会将0xFF
放入base_num
。
请记住,在这种情况下,编译器会警告您精度损失。在这种情况下,您的编译器可能会出错(Visual Studio与Treat Warnings as Errors
On)。如果发生这种情况,你可以这样做:
base_num = (uint8_t)crap;
但这似乎是你想要避免的。
你试图做的似乎是去除模数运算符,因为它需要除法和除法是最昂贵的基本算术运算。我通常不会认为这是任何方式的瓶颈,因为任何“智能”编译器(即使在调试模式下)都会“优化”它:
base_num = crap & 0xFF;
在一个支持的平台上(我听说过的每个主流处理器 - x86,AMD64,ARM,MIPS)都应该是这样的。听到处理器没有基本的AND和OR算术指令,我会傻眼。