在特殊情况下:是否比%更快?
我看到了这个职位的select答案 。
我很惊讶,如果x是一个无符号整数(x & 255) == (x % 256)
,我想知道在n = 2^a (a = [1, ...])
,x是一个正整数。
由于这是一个特殊情况,我作为一个人可以决定,因为我知道程序将处理哪些值,编译器不知道。 如果我的程序使用了大量的模运算,我可以获得显着的性能提升吗?
当然,我可以编译并查看反汇编。 但这只会回答我的问题,一个编译器/体系结构。 我想知道这是否原则上更快。
如果你的整型是无符号的,编译器会优化它,结果是一样的。 如果签了字,事情就不一样了
这个程序:
int mod_signed(int i) { return i % 256; } int and_signed(int i) { return i & 255; } unsigned mod_unsigned(unsigned int i) { return i % 256; } unsigned and_unsigned(unsigned int i) { return i & 255; }
将被编译( 通过GCC 6.2与-O3;铿锵3.9产生非常相似的代码 ):
mod_signed(int): mov edx, edi sar edx, 31 shr edx, 24 lea eax, [rdi+rdx] movzx eax, al sub eax, edx ret and_signed(int): movzx eax, dil ret mod_unsigned(unsigned int): movzx eax, dil ret and_unsigned(unsigned int): movzx eax, dil ret
mod_signed
的结果集是不同的
如果乘法,除法或模数expression式的两个操作数具有相同的符号,则结果是肯定的。 否则,结果是否定的。 模运算的符号的结果是实现定义的。
和AFAICT,大部分实现都决定了模数expression式的结果总是和第一个操作数的符号相同。 请参阅此文档 。
因此, mod_signed
被优化(来自nwellnhof的评论):
int d = i < 0 ? 255 : 0; return ((i + d) & 255) - d;
从逻辑上说,我们可以certificate,对于所有的无符号整数, i % 256 == i & 255
,因此,我们可以信任编译器来完成它的工作。
我用gcc做了一些测量,如果a /
或者%
的参数是一个2的幂的编译时间常量,gcc可以把它转换成相应的位操作。
这里是我的一些分区基准什么有更好的performance:乘法还是分裂? 正如你所看到的,那些静态已知幂数为2的除数的运行时间明显低于其他静态已知的因数。
所以如果/
和具有静态已知功率的两个参数描述你的algorithm比位操作更好,可以自由select/
和%
。 你不应该失去任何体面的编译器的performance。