是否存在“&”产生的性能低于“%”的情况?
Is there a case where '&' yields a lower performance than '%'?
以下两个代码序列产生相同的结果:
uint mod = val % 4;
uint mod1 = val & 0x3;
我可以同时使用两者来计算相同的结果。我知道在硬件中 &
运算符比 %
运算符更容易实现。因此我希望它比 %
运算符具有更好的性能。
我能否始终假设 &
具有更好或相等的性能?
编译器会自动优化吗?
(现代)编译器应该根据您的示例生成相同的代码,这种优化的原因是 rhs 是一个编译常量。
据我所知,&
运算符是用一条处理器指令完成的 and
;模运算符不是这种情况,它通常意味着更多的操作(计算整数除法的余数)。 AFAIK,它通常比乘法长;我认为只要一个整数除法。
您不能对这些操作中的任何一个进行任何假设,编译可以将两者优化为相同的指令。
而且,事实上,clang
和 gcc
都会将它们翻译成一条 and
指令。
不幸的是,由于 %
的性质自 ISO C99 起具有指定的 return 负值,signed
整数需要一些额外的工作。与 ISO C90 相反,负模是实现定义的。
两个操作的结果集,在 signed
和 unsigned
值上:
modulo
有符号整数:
mov eax, DWORD PTR [esp+4] ; grab `val`
cdq ; convert 32-bit EAX to 64-bit
; and fill EDX with the sign bit
shr edx, 30 ; shift EDX by 30 positions to the right
; leaving only the two left-most bits
add eax, edx ; add EDX to EAX
and eax, 3 ; do the AND
sub eax, edx ; subtract EDX from EAX
mov DWORD PTR [esp+8], eax ; move result on stack
这是一个巧妙的技巧,可以正确定义负值的行为。它对负值执行 ((val + 3) & 3) - 3
,对正值执行 val & 3
。
and
with signed/unsigned and modulo
with unsigned:
mov eax, DWORD PTR [esp+4]
and eax, 3
mov DWORD PTR [esp+12], eax
以下两个代码序列产生相同的结果:
uint mod = val % 4;
uint mod1 = val & 0x3;
我可以同时使用两者来计算相同的结果。我知道在硬件中 &
运算符比 %
运算符更容易实现。因此我希望它比 %
运算符具有更好的性能。
我能否始终假设 &
具有更好或相等的性能?
编译器会自动优化吗?
(现代)编译器应该根据您的示例生成相同的代码,这种优化的原因是 rhs 是一个编译常量。
据我所知,&
运算符是用一条处理器指令完成的 and
;模运算符不是这种情况,它通常意味着更多的操作(计算整数除法的余数)。 AFAIK,它通常比乘法长;我认为只要一个整数除法。
您不能对这些操作中的任何一个进行任何假设,编译可以将两者优化为相同的指令。
而且,事实上,clang
和 gcc
都会将它们翻译成一条 and
指令。
不幸的是,由于 %
的性质自 ISO C99 起具有指定的 return 负值,signed
整数需要一些额外的工作。与 ISO C90 相反,负模是实现定义的。
两个操作的结果集,在 signed
和 unsigned
值上:
modulo
有符号整数:
mov eax, DWORD PTR [esp+4] ; grab `val`
cdq ; convert 32-bit EAX to 64-bit
; and fill EDX with the sign bit
shr edx, 30 ; shift EDX by 30 positions to the right
; leaving only the two left-most bits
add eax, edx ; add EDX to EAX
and eax, 3 ; do the AND
sub eax, edx ; subtract EDX from EAX
mov DWORD PTR [esp+8], eax ; move result on stack
这是一个巧妙的技巧,可以正确定义负值的行为。它对负值执行 ((val + 3) & 3) - 3
,对正值执行 val & 3
。
and
with signed/unsigned and modulo
with unsigned:
mov eax, DWORD PTR [esp+4]
and eax, 3
mov DWORD PTR [esp+12], eax