我在SO <>
语句中看到“=
比!=
”或“==
”快if()
更快的评论。
我想知道为什么会这样。你能在asm中展示一个例子吗?
谢谢! :)
编辑:
这就是他所做的。
function Check(var MemoryData:Array of byte;MemorySignature:Array of byte;Position:integer):boolean;
var i:byte;
begin
Result := True; //moved at top. Your function always returned 'True'. This is what you wanted?
for i := 0 to Length(MemorySignature) - 1 do //are you sure??? Perhaps you want High(MemorySignature) here...
begin
{!} if MemorySignature[i] <> $FF then //speedup - '<>' evaluates faster than '='
begin
Result:=memorydata[i + position] <> MemorySignature[i]; //speedup.
if not Result then
Break; //added this! - speedup. We already know the result. So, no need to scan till end.
end;
end;
end;
答案 0 :(得分:19)
我声称这可能是错误的,除非在非常特殊的情况下。编译器可以毫不费力地将一个重构为另一个(仅通过切换if
和else
个案例。)
答案 1 :(得分:6)
它可能与CPU上的分支预测有关。静态分支预测将预测不会采用分支并获取下一条指令。但是,几乎没有人再使用它了。除此之外,我会说这是公牛,因为比较应该是相同的。
答案 2 :(得分:6)
我认为你的previous question中有一些关于你试图实施的算法是什么的混淆,因此声称“加速”声称要做什么。
这是Delphi 2007的一些反汇编。优化。 (注意,优化关闭稍微改变了代码,但不是以相关的方式。
Unit70.pas.31: for I := 0 to 100 do
004552B5 33C0 xor eax,eax
Unit70.pas.33: if i = j then
004552B7 3B02 cmp eax,[edx]
004552B9 7506 jnz $004552c1
Unit70.pas.34: k := k+1;
004552BB FF05D0DC4500 inc dword ptr [$0045dcd0]
Unit70.pas.35: if i <> j then
004552C1 3B02 cmp eax,[edx]
004552C3 7406 jz $004552cb
Unit70.pas.36: l := l + 1;
004552C5 FF05D4DC4500 inc dword ptr [$0045dcd4]
Unit70.pas.37: end;
004552CB 40 inc eax
Unit70.pas.31: for I := 0 to 100 do
004552CC 83F865 cmp eax,$65
004552CF 75E6 jnz $004552b7
Unit70.pas.38: end;
004552D1 C3 ret
如您所见,这两种情况的唯一区别是jz与jnz指令。这些将以相同的速度运行。更可能影响事情的是分支的使用频率,以及整个循环是否适合缓存。
答案 3 :(得分:5)
如果从string.op_Equality
和string.op_Inequality
方法查看IL,您会看到两个内部调用string.Equals。
但是op_Inequality
反转了结果。这是两个IL声明。
我会说它们的性能是相同的,对于==语句可能有一个小的(非常小的,非常小的)更好的性能。但我相信优化器&amp; JIT编译器将删除它。
答案 4 :(得分:4)
虽然自发;代码中的大多数其他内容会影响性能,而不是==和!=(或=和&lt;&gt;取决于语言)之间的选择。
当我在C#中进行1000000次迭代比较字符串测试时(包含字母表,a-z,其中一个字母反转最后两个字母),差异在0到1毫秒之间。
之前已经说过:编写可读性代码;当确定它会产生影响时,将其转换为性能更高的代码。
编辑:用字节数组重复相同的测试;一样;性能差异是可以忽略的。
答案 5 :(得分:4)
这也可能是对实验误解的结果。
大多数编译器/优化器都假定默认采用分支。如果反转运算符和if-then-else顺序,并且现在采用的分支是ELSE子句,则可能会在高度计算代码中导致额外的速度效应(*)
(*)显然你需要为此做很多操作。但是对于例如最紧密的环路来说,它可能很重要。编解码器或图像分析/机器视觉,您可以在其中传输50MByte / s的数据。 ....然后我甚至只是为了真正重复使用的代码而屈服于这个级别。对于普通的商业代码,这是不值得的。
答案 6 :(得分:2)
我声称这是错误的完全停止。平等的测试总是与不平等的测试相同。使用字符串(或复杂的结构测试),您总是会在完全相同的点上中断。在达到这个突破点之前,平等的答案是未知的。
答案 7 :(得分:1)
如果你能提供一个清楚显示差异的小例子,那么我确信Stack Overflow社区可以解释原因。但是,我认为你可能难以构建一个明确的例子。我不认为在任何合理的范围内都会有明显的性能差异。
答案 8 :(得分:1)
我强烈怀疑速度有什么不同。例如,对于整数类型,您将获得CMP指令和JZ(如果为零则跳转)或JNZ(如果不为零则跳转),具体取决于您使用的是=还是≠。这里没有速度差异,我希望在更高的水平上保持正确。
答案 9 :(得分:1)
ASM指令的这个列表(假设它在x86上)可能会有所帮助:
(免责声明,我只有非常基本的编写汇编程序的经验,所以我可能会脱离标记)
然而,它显然完全取决于Delphi编译器生成的汇编指令。没有看到输出,那就是猜测。我将保留我的唐纳德克努特的报价,因为关心这类事情,除了一系列应用程序(游戏,移动设备,高性能服务器应用程序,安全关键软件,导弹发射器等)就是你的事情。我认为最后担心。
“我们应该忘记小事 效率,约占97% 时间:过早优化是 万恶之源。“
如果您正在写其中一个或类似的,那么显然您会关心,但您没有指定它。
答案 10 :(得分:1)
它可能是或者它不可能,这是问题:-) 问题在于这取决于您使用的编程语言。 由于所有语句最终都将作为CPU的指令结束,因此使用最少量指令来实现结果的语句将是最快的。
例如,如果您说位x等于位y,则可以使用使用两个位作为输入执行XOR的指令,如果结果为0,则它不相同。那么你怎么知道结果不是0呢?如果你说输入a大于0,则使用返回true的指令。
所以这已经是你用来做的2条指令,但由于大多数CPU都有一个指令在一个周期内进行比较,这是一个不好的例子。
我所提出的观点仍然相同,如果不提供编程语言和CPU架构,就无法做出这种普遍的陈述。
答案 11 :(得分:1)
只是猜测,但鉴于你想保留逻辑,你不能只是替换
if A = B then
带
if A <> B then
为了保存逻辑,原始代码必须类似于
if not (A = B) then
或
if A <> B then
else
这可能比对不平等的测试要慢一点。