[英]With a single file descriptor, Is there any performance difference between select, poll and epoll and …?
[英]Is there any performance difference between for() and while()?
或者它是关于语义的吗?
简答:不,他们完全一样。
猜测它理论上可能依赖于编译器; 一个真正破碎的人可能会做一些略有不同的事情,但我会感到惊讶。
只是为了好玩,这里有两个变种,使用Ubuntu附带的x86 gcc版本4.3.3编译为完全相同的汇编代码。 您可以使用linux上的objdump检查最终二进制文件上生成的程序集。
int main() { #if 1 int i = 10; do { printf("%d\n", i); } while(--i); #else int i = 10; for (; i; --i) printf("%d\n", i); #endif }
编辑:这是一个“橘子与橘子”,而循环示例也编译成同样的东西:
while(i) { printf("%d\n", i); --i; }
如果for和while循环执行相同的操作,编译器生成的机器代码应该(几乎)相同。
比如几年前我做的一些测试,
for (int i = 0; i < 10; i++)
{
...
}
和
int i = 0;
do
{
...
i++;
}
while (i < 10);
将生成完全相同的代码,或者(和Neil在评论中指出)使用一个额外的jmp,这将不会在性能上产生足够大的差异而担心。
没有语义差异,不需要任何编译差异。 但这取决于编译器。 所以我尝试使用g ++ 4.3.2,CC 5.5和xlc6。
g ++,CC是相同的,xlc不是
xlc的差异在于初始循环条目。
extern int doit( int );
void loop1( ) {
for ( int ii = 0; ii < 10; ii++ ) {
doit( ii );
}
}
void loop2() {
int ii = 0;
while ( ii < 10 ) {
doit( ii );
ii++;
}
}
XLC输出
.loop2: # 0x00000000 (H.10.NO_SYMBOL)
mfspr r0,LR
stu SP,-80(SP)
st r0,88(SP)
cal r3,0(r0)
st r3,64(SP)
l r3,64(SP) ### DIFFERENCE ###
cmpi 0,r3,10
bc BO_IF_NOT,CR0_LT,__L40
...
enter code here
.loop1: # 0x0000006c (H.10.NO_SYMBOL+0x6c)
mfspr r0,LR
stu SP,-80(SP)
st r0,88(SP)
cal r3,0(r0)
cmpi 0,r3,10 ### DIFFERENCE ###
st r3,64(SP)
bc BO_IF_NOT,CR0_LT,__La8
...
while
循环测试中变量的范围比for
循环标题中声明的变量范围更宽。
因此,如果存在性能影响作为保持变量更长时间活动的副作用,那么在while和for循环之间进行选择会产生性能影响(并且不会在{}中包含while,以缩小其范围。变量)。
一个示例可能是并发集合,它计算引用它的迭代器的数量,如果存在多个迭代器,它会应用锁定以防止并发修改,但如果只有一个迭代器引用它,优化就会使锁定失败。 如果你在一个函数中有两个for
循环,在同一个容器上使用不同名称的迭代器,那么将采用快速路径,但是使用两个while
循环时将采用慢速路径。 同样,如果对象很大(更多缓存流量)或使用系统资源,可能会对性能产生影响。 但我想不出一个我见过的真正的例子,它会产生什么影响。
使用循环展开优化的编译器可能只在for-loop情况下这样做。
两者都是等价的。 这是一个语义问题。
唯一的区别可能在于做... while结构,在那里你推迟条件的评价,直到身体后 ,从而可节省1分的评价。
i = 1; do { ... i--; } while( i > 0 );
而不是
for( i = 1; i > 0; --i )
{ ....
}
我写编译器。 我们将所有“结构化”控制流( if
, while
, for
, switch
, do
... while
)编译成条件和无条件分支。 然后我们分析控制流图。 由于C编译器无论如何都必须处理一般goto
,因此最简单的方法是将所有内容都减少为分支和条件分支指令,然后一定要很好地处理这种情况。 (AC编译器不仅要在手写代码上做得很好,还要在自动生成的代码上做得很好,这些代码可能有很多很多的goto
语句。)
不。如果他们正在做相同的事情,他们将编译成相同的代码 - 正如你所说,它是关于语义。 选择最能代表您要表达的内容的那个。
理想情况下它应该是相同的,但最终它取决于您的编译器/解释器。 当然,您必须测量或检查生成的汇编代码。
证明可能存在差异:这些线使用cc65生成不同的汇编代码。
for (; i < 1000; ++i);
while (i < 1000) ++i;
Atmel ATMega虽然()比()更快。 为什么在AVR035中解释了这一点:AVR的高效C编码。
PS原始平台没有提到问题。
继续在for和while中表现不同:in for ,它改变了计数器, 而while通常不会
添加另一个答案:根据我的经验,优化软件就像是一个被人剃掉的大而浓密的胡须。
最后一个是for()
和while()
之间的差异,但可能不会产生影响。
PS我认识的程序员(他们都非常好,我怀疑是一个有代表性的样本)基本上从另一个方向去做。
就性能而言,它们是相同的。 我倾向于使用while
等待状态改变(例如,等待一个缓冲器被填充),并且当for
处理多个离散的对象(诸如一个集合中的每个项目去)时。
在某些情况下存在差异。
如果您处于这种差异很重要的位置,您需要选择更好的算法或开始使用汇编语言进行编码。 相信我,在汇编中编码比修复编译器版本更可取。
是while()
快/慢for()
让我们回顾一下有关优化的一些事情:
编译器编写器通过减少调用跳转,比较,增量以及它们生成的其他类型的指令来非常努力地削减周期。
另一方面,调用指令会消耗更多的周期,但是编译器几乎无能为力去除它们。
作为程序员,我们编写了很多函数调用,有些是因为我们的意思是,有些因为我们很懒,有些因为编译器将它们滑入而没有显而易见。
大多数时候,这并不重要,因为硬件太快了,而且我们的工作很小,以至于计算机就像一只小猎犬,狼吞虎咽地吃着她的食物并且乞求更多。
然而,有时候,这项工作足够大,以至于性能成为一个问题。
那我们做什么? 哪里有更大的回报?
编译器不能做后者。 只有我们程序员才能。
我们需要学习或教会如何做到这一点。 它不是自然而然的。 我们先天倾向于做出错误的猜测,然后押注于他们。 获得更好的算法是一个开始,但只是一个开始。 我们的老师需要教这个,如果他们确实知道如何。
Profilers是一个开始。 我这样做
Willie Sutton在被问到为什么要抢银行时的虚伪引用? :
因为这就是钱的所在。
如果您想保存周期,请找出它们的位置。
可能只是编码风格。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.