c++ cscope配置 - 是<快于<=?





gtags使用 find (12)


他们有相同的速度。 也许在某些特殊架构中,他/她说的是对的,但在x86家族中,至少我知道它们是相同的。 因为为此,CPU将执行减法(a - b),然后检查标志寄存器的标志。 该寄存器的两位称为ZF(零标志)和SF(标志标志),并且在一个周期内完成,因为它将通过一次掩码操作完成。

我正在读一本书,作者说if( a < 901 )if( a <= 900 )快。

与这个简单的例子不完全一样,但是在复杂的循环代码上有轻微的性能变化。 我想这必须用生成的机器代码来做,以防万一。




这将高度依赖C编译的底层架构。 一些处理器和体系结构可能具有等于或小于等于的明确指令,其以不同数目的周期执行。

这将是非常不寻常的,因为编译器可以解决它,使它不相关。




至少,如果这是真的,编译器可以优化a <= b to!(a> b),所以即使比较本身实际上比较慢,除了最天真的编译器之外,你也不会注意到有什么区别。




其他答案都集中在x86体系结构上,我不知道ARM体系结构(您的示例汇编程序似乎是)足以对所生成的代码进行具体评论,但这是micro-optimisation一个示例,它非常适合体系结构具体而言,并且很可能是一种反优化,因为它是一种优化

因此,我认为这种micro-optimisation货物崇拜编程的一个例子,而不是最好的软件工程实践。

这可能是一些优化的架构,但我知道至少有一种架构可能是正确的。 历史悠久的Transputer体系结构只有机器代码指令等于大于或等于 ,因此所有比较必须从这些基元构建而成。

即使在那时,在几乎所有情况下,编译器都可以按照这样的方式排列评估指令,实际上,没有任何比较有任何优势。 最糟糕的情况是,它可能需要添加一个反向指令(REV)来交换操作数堆栈中的前两项。 这是一个单字节指令,需要一个周期才能运行,所以可能有最小的开销。

这样的微型优化是一种优化还是一种反优化取决于你正在使用的特定架构,所以习惯使用体系结构特定的微观优化通常是一个坏主意,否则你可能本能地如果这样做不恰当,就使用一个,看起来这就是你正在阅读的书正在倡导的。




实际上,它们的速度将完全相同,因为在装配层面它们都采用一条线。 如:

  • jl ax,dx (如果AX小于DX,则跳转)
  • jle ax,dx (如果AX小于或等于DX,则跳转)

所以不,也不是更快。 但如果你想获得真正的技术,我认为如果你想在电子电流水平上检查它,它会稍微快一点,但不会接近你会注意到的速度。




也许这本未命名的书的作者已经读过, a > 0运行速度超过a >= 1并且认为这是普遍的。

但是这是因为涉及0 (因为CMP可以取决于体系结构,例如用OR取代)而不是因为<




假设我们正在谈论内部整数类型,没有办法可以比另一个更快。 它们在语义上显然是相同的。 他们都要求编译器做同样的事情。 只有一个可怕的破碎的编译器会为其中的一个产生较差的代码。

如果有一些平台的<<=简单的整数类型更快,那么编译器总是应该将<=转换为<常量。 任何编译器不会只是一个糟糕的编译器(针对该平台)。




对于浮点代码,甚至在现代架构上,<=比较的确可能会更慢(只需一条指令)。 这是第一个功能:

int compare_strict(double a, double b) { return a < b; }

在PowerPC上,首先执行浮点比较(更新cr ,条件寄存器),然后将条件寄存器移至GPR,将“比较小于”位移入原位,然后返回。 它需要四条指令。

现在考虑这个函数:

int compare_loose(double a, double b) { return a <= b; }

这需要与上面的compare_strict相同的工作,但现在有两点兴趣:“小于”和“等于”。 这需要一个额外的指令( cror - 条件寄存器按位或)将这两个位合并为一个。 所以compare_loose需要5条指令,而compare_strict需要4条。

你可能会认为编译器可以像这样优化第二个函数:

int compare_loose(double a, double b) { return ! (a > b); }

但是,这将错误地处理NaN。 NaN1 <= NaN2NaN1 > NaN2需要评估为假。




你可以说在大多数脚本语言中这一行是正确的,因为额外的字符会导致代码处理速度稍慢。 但是,正如最佳答案指出的那样,它在C ++中应该没有任何作用,并且任何使用脚本语言完成的事情可能都不是关心优化。




我发现这两者都不是更快。 编译器在每个条件下生成具有不同值的相同机器代码。

if(a < 901)
cmpl  $900, -4(%rbp)
jg .L2

if(a <=901)
cmpl  $901, -4(%rbp)
jg .L3

我的例子, if是从Linux上的x86_64平台上的GCC。

编译器编写者是非常聪明的人,他们会想到这些事情,而我们大多数人认为这是理所当然的。

我注意到,如果它不是一个常量,那么在任何一种情况下都会生成相同的机器码。

int b;
if(a < b)
cmpl  -4(%rbp), %eax
jge   .L2

if(a <=b)
cmpl  -4(%rbp), %eax
jg .L3



即使有任何差异,你也不应该注意到这种差异。 此外,在实践中,除非你打算使用一些魔术常数,否则你必须做a + 1a + 1的附加条件,这是非常糟糕的做法。




Swift Array性能重新审视:

我写了自己的基准,比较Swift和C / Objective-C。 我的基准计算素数。 它使用以前的素数数组来寻找每个新候选人的素数因子,所以它非常快。 但是,它会进行数组读取,而不会写入数组。

我原先是对Swift 1.2做这个基准的。 我决定更新该项目并针对Swift 2.0运行它。

该项目让您选择使用普通的swift数组和使用数组语义的Swift不安全内存缓冲区。

对于C / Objective-C,您可以选择使用NSArrays或C malloc'ed数组。

测试结果与最快,最小的代码优化([-0s])或最快,最积极(最快(最快)]优化似乎非常相似。

在关闭代码优化的情况下,Swift 2.0的性能仍然很糟糕,而C / Objective-C的性能只是稍微慢一些。

底线是C malloc'd基于数组的计算速度最快,幅度不大

使用最快,最小的代码优化时,带有不安全缓冲区的Swift比C malloc'd数组长1.19X - 1.20X。 与快速,积极的优化相比,差异似乎稍微小一些(Swift比C更长1.18倍到1.16倍。

如果你使用普通的Swift数组,与C的差别稍大 。 (Swift花费大约1.22到1.23。)

普通的Swift数组比DRAMATICALLY速度上要快于在Swift 1.2 / Xcode 6中的速度。它们的性能非常接近Swift不安全的基于缓冲区的数组,使用不安全的内存缓冲区看起来并不值得麻烦,这很大。

顺便说一句,Objective-C的NSArray性能很糟糕。 如果你打算在两种语言中使用本地容器对象,Swift的运行速度会更快。

您可以在SwiftPerformanceBenchmark上的github上查看我的项目

它有一个简单的用户界面,使收集统计很容易。

有趣的是,Swift中的排序似乎比C中的稍快,但这个素数算法在Swift中仍然更快。





c++ performance assembly relational-operators