在特殊情况下:是否比%更快?

我看到了这个职位的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。