回到我学习C和装配的那一天,我们被教导,最好使用简单的比较来提高速度.例如,如果你说:
if(x <= 0)
Run Code Online (Sandbox Code Playgroud)
与
if(x < 1)
Run Code Online (Sandbox Code Playgroud)
哪个会执行得更快?我的论点(可能是错误的)是第二个几乎总是执行得更快,因为只有一个比较)即小于一,是或否.
如果数字小于0,第一个将快速执行,因为这等于为真,没有必要检查等于使得它与第二个一样快,但是,如果数字为0或更多,它将总是更慢,因为它然后必须进行第二次比较,看它是否等于0.
我现在正在使用C#,而在开发台式机时速度不是问题(至少没有达到他的观点值得争论的程度),我仍然认为这些论点需要考虑因为我也在为移动设备开发功能不如台式机,速度确实成为这类设备的问题.
为了进一步考虑,我说的是整数(没有小数)和数字,其中不能有负数如-1或-12,345等(除非有错误),例如,当你不能处理列表或数组时有一个负数的项目,但你想检查一个列表是否为空(或如果有问题,将x的值设置为负表示错误,一个例子是列表中有一些项目,但你不能由于某种原因检索整个列表,并指出你将数字设置为负数,这与说没有项目是不一样的).
由于上述原因,我故意忽略了显而易见的事实
if(x == 0)
Run Code Online (Sandbox Code Playgroud)
和
if(x.isnullorempty())
Run Code Online (Sandbox Code Playgroud)
用于检测没有项目的列表的其他此类项目.
同样,为了考虑,我们讨论的是从数据库中检索项目的可能性,可能使用具有所述功能的SQL存储过程(即标准(至少在该公司中)是返回负数以指示问题).
所以在这种情况下,使用上面的第一个或第二个项目会更好吗?
Dav*_*rtz 19
他们是完全相同的.两者都不比另一个快.他们都提出了相同的问题,假设x是一个整数.C#不是汇编.您要求编译器生成最佳代码以获得您要求的效果.您没有指定它是如何获得该结果的.
另见这个答案.
我的论点(可能是错误的)是第二个几乎总是执行得更快,因为只有一个比较)即小于一,是或否.
显然那是错的.看看如果你认为这是真的会发生什么:
<是<=因为它问的问题较少.(你的论点.)
>速度是相同的,<=因为它提出相同的问题,只是反复回答.
因此<比快>!但是这个相同的论点表明>比...更快<.
"只是一个倒置的答案"似乎偷偷进入另一个布尔操作,所以我不确定我是否遵循这个答案.
出于同样的原因,这是错误的(对于硅,它有时对软件是正确的).考虑:
3 != 4比计算更昂贵3 == 4,因为它是3 != 4一个倒置的答案,一个额外的布尔运算.
3 == 4比3 != 4它更昂贵,因为它3 != 4有一个倒置的答案,一个额外的布尔运算.
因此,3 != 4比自己更昂贵.
反向答案恰恰相反,而不是额外的布尔运算.或者,为了更精确,它使用不同的比较结果到最终答案的映射.双方3 == 4并3 != 4要求你比较3和4,这比较结果醚"平等"或"不平等".问题只是将"平等"和"不平等"映射到"真实"和"假"不同.两种映射都不比另一种更昂贵.
至少在大多数情况下,不,一个人没有优势.
A <=通常不会被实现为两个单独的比较.在典型的(例如,x86)CPU上,您将有两个单独的标志,一个用于表示相等,另一个用于表示负数(也可以表示"小于").除此之外,你将拥有依赖于这些标志组合的分支,因此<转换为a jl或jb(如果少则跳转或跳跃,如果低于 - 前者用于有符号数,后者用于无符号).A <=将转换为a jle或jbe(如果小于或等于则跳转,如果低于或等于则跳转).
不同的CPU将使用不同的名称/助记符作为指令,但大多数仍然具有相同的指令.在我所知道的每一种情况下,所有这些都以相同的速度执行.
编辑:哎呀 - 我想提一下我上面提到的一般规则的一个可能的例外.虽然它不是完全从<对<=,如果/当你可以比较0的,而不是任何其他的号码,有时可以得到一点点(微不足道)的优势.例如,让我们假设你有一个变量,你要倒数,直到达到最低限度.在这种情况下,如果你可以倒数到0而不是倒数到1,你可能会获得一点优势.原因很简单:我之前提到的标志受大多数指令的影响.我们假设你有类似的东西:
do {
// whatever
} while (--i >= 1);
Run Code Online (Sandbox Code Playgroud)
编译器可能会将其转换为:
loop_top:
; whatever
dec i
cmp i, 1
jge loop_top
Run Code Online (Sandbox Code Playgroud)
相反,如果你比较0(while (--i > 0)或while (--i != 0)),它可能会转换为类似的东西;
loop_top:
; whatever
dec i
jg loop_top
; or: jnz loop_top
Run Code Online (Sandbox Code Playgroud)
这里dec设置/清除零标志以指示减量的结果是否为零,因此条件可以直接基于来自的结果dec,从而消除cmp了其他代码中使用的结果.
但是,我应该补充一点,虽然这很有效,比如说,30多年前,大多数现代编译器都可以在没有你帮助的情况下处理这样的翻译(尽管有些编译器可能没有,特别是像小型嵌入式系统这样的东西).IOW,如果你关心一般的优化,你几乎可能有一天会关心 - 但至少对我而言,对C#的应用似乎充其量是值得怀疑的.
大多数现代硬件都有内置指令,用于检查单个指令中的小于或等于的通信,其执行速度与检查小于条件的指令完全一样快.适用于(更多)旧硬件的论点不再适用 - 选择您认为最具可读性的替代方案,即更好地将您的想法传达给代码读者的方案.
| 归档时间: |
|
| 查看次数: |
544 次 |
| 最近记录: |