查找两个之间的最大数,选择哪个实现
我想弄清楚,在找到两个之间的最大数量时,哪个实现比其他实现更具优势。作为一个例子,让我们检查两个实现:
实施1:
int findMax (int a, int b)
{
return (a > b) ? a : b;
}
// 汇编输出:(gcc 11.1)
push rbp mov rbp, rsp mov DWORD PTR [rbp-4], edi mov DWORD PTR [rbp-8], esi mov eax, DWORD PTR [rbp-4] cmp eax, DWORD PTR [rbp-8] jle .L2 mov eax, DWORD PTR [rbp-4] jmp .L4 .L2: mov eax, DWORD PTR [rbp-8] .L4: pop rbp ret
实施2:
int findMax(int a, int b)
{
int diff, s, max;
diff = a - b;
s = (diff >> 31) & 1;
max = a - (s * diff);
return max;
}
// 汇编输出:(gcc 11.1)
push rbp mov rbp, rsp mov DWORD PTR [rbp-20], edi mov DWORD PTR [rbp-24], esi mov eax, DWORD PTR [rbp-20] sub eax, DWORD PTR [rbp-24] mov DWORD PTR [rbp-4], eax mov eax, DWORD PTR [rbp-4] shr eax, 31 mov DWORD PTR [rbp-8], eax mov eax, DWORD PTR [rbp-8] imul eax, DWORD PTR [rbp-4] mov edx, eax mov eax, DWORD PTR [rbp-20] sub eax, edx mov DWORD PTR [rbp-12], eax mov eax, DWORD PTR [rbp-12] pop rbp ret
第二个产生了更多的汇编指令,但第一个有条件跳转。只是想了解两者是否同样好。
回答
首先,您需要打开编译器优化(我用于-O2以下内容)。你应该比较std::max. 然后这个:
#include <algorithm>
int findMax (int a, int b)
{
return (a > b) ? a : b;
}
int findMax2(int a, int b)
{
int diff, s, max;
diff = a - b;
s = (diff >> 31) & 1;
max = a - (s * diff);
return max;
}
int findMax3(int a,int b){
return std::max(a,b);
}
结果:
findMax(int, int):
cmp edi, esi
mov eax, esi
cmovge eax, edi
ret
findMax2(int, int):
mov ecx, edi
mov eax, edi
sub ecx, esi
mov edx, ecx
shr edx, 31
imul edx, ecx
sub eax, edx
ret
findMax3(int, int):
cmp edi, esi
mov eax, esi
cmovge eax, edi
ret
您的第一个版本产生与 相同的程序集std::max,而您的第二个变体则做得更多。实际上,在尝试优化时,您需要指定优化的对象。有几个选项通常需要进行权衡:运行时、内存使用、可执行文件的大小、代码的可读性等。通常您无法一次获得所有这些。
如有疑问,请不要重新发明轮子,而是使用现有的已经优化的std::max. 并且不要忘记,您编写的代码不是针对 CPU 的指令,而是对程序应该做什么的高级抽象描述。编译器的工作是弄清楚如何最好地实现这一目标。
最后但并非最不重要的是,您的第二个变体实际上已损坏。请参阅此处编译的示例-O2 -fsanitize=signed-integer-overflow,结果为:
/app/example.cpp:13:10: runtime error: signed integer overflow: -2147483648 - 2147483647 cannot be represented in type 'int'
你应该赞成正确而不是速度。最快的代码在出错时一文不值。正因为如此,可读性是列表中的下一个。难以阅读和理解的代码也难以证明是正确的。在编译器的帮助下,我只能在您的代码中发现问题,而std::max(a,b)不太可能导致未定义的行为(即使确实如此,至少这不是您的错;)。