给出以下执行的声明:
iNormVal = iVal / uRatio;
如果uRatio == 1
大多数(90%)的话,以下内容会更有意义(表现明智)吗?
if(uRatio > 1)
iNormVal = iVal / uRatio;
else
iNormVal = iVal;
感谢..
答案 0 :(得分:7)
由于您发现这是一个潜在的瓶颈,因此非常可能这个地点与您应用的整体速度完全无关。说真的,人类,甚至是大师程序员,都非常不善于发现真正的瓶颈。 (不同的是,优秀的程序员承认并宣传,而大三学生则花时间来优化不相关的点。)
一般来说,我发现这种优化方法最有帮助:
(显然,对于库代码而言,这是不同的,但是这几个步骤对您有很大帮助。)
答案 1 :(得分:4)
你需要profile来获得一个测量值,这太难猜了。编译器可能会认为您错了并删除了测试,因此请选择是否进行优化。
(整数)除法的实际成本可能相当低,特别是在现代桌面级处理器上。根据{{3}},现代(Wolfdale / Nehalem / Sandy Bridge)32/32位分区的成本分别为14-23 / 17-28 / 20-28周期。所以,如果你真的这么做了,它可能会加起来。在这种情况下,如果可能,请查看并行(矢量化)选项。
如果可能的话,我会尽量避免它,因为它引入了一个分支。分支有两个缺点:它们通过引入读取代码的程序员必须理解的多个路径使代码更复杂,并且它们也可能引入执行开销。
答案 2 :(得分:2)
取决于。
代码是否属于性能关键型应用程序?如果是这样,那么它可能有助于实现。如果不顺利,那么我通常会在旁边或可读性方面犯错,并且不会引入额外的if语句。
即使它位于性能关键型应用程序中,通常外部边界交互也占执行时间的95%,例如与数据库或外部服务的交互。编译器通常执行得非常快,而且语句非常便宜。当我们通常对我们的代码进行分析时,我们很少会进行更改,例如您所描述的仅针对性能原因的更改。滥用循环等有时可能会支持,但我们很少添加if描述的语句。
希望这会有所帮助......
答案 3 :(得分:2)
如果您决定使用分支,那么您可以先检查常见情况。它稍微更具可读性,性能稍好一点。
if(uRatio <= 1) {
iNormVal = iVal;
}
else {
iNormVal = iVal / uRatio;
}
为了更具可读性,您可以添加一个具有良好名称的局部变量来保存表达式的结果。
unsigned int uSmallRatio = uRatio <= 1;
if(uSmallRatio) {
iNormVal = iVal;
}
else {
iNormVal = iVal / uRatio;
}
编译器可以将其优化为与第一种方法相同的机器代码。我不确定这一点。
同样地,你可以这样做,但它并不漂亮:
iNormVal = uRatio <= 1 ? iVal : iVal / uRatio;
最后另一种方法是:
iNormVal = iVal;
if(uRatio > 1) { /*explain why you do this so it won't be changed by somebody else*/
iNormVal = iVal / uRatio;
}
我确信还有其他方法需要考虑。
...问候
答案 4 :(得分:1)
if子句实际上很可能会使程序变慢。对于性能而言,分支是非常糟糕,因为现代处理器是pipelined,并且分支阻止管道完全有效。这是一个非常重要的问题,branch prediction付出了相当大的努力,但在这种情况下,这并没有帮助。即使预测在90%的时间都是正确的,这意味着10%的时间是空管道,这比int分区差很多(特别是考虑到if子句本身需要时间)。
但很可能它根本不重要,因为你的代码大部分时间都花在一个完全不同的地方,这使得整个问题大大浪费时间。
答案 5 :(得分:1)
大多数性能问题要么是意识形态问题(你设计的方式错误),要么是实施较慢的算法(给定选择)。
除此之外,性能提升将在汇编级别进行,并且将取决于平台。
我几乎不建议将此作为对性能的实际关注,除非你真的受到性能的限制,此时你需要先检查上面的内容。
你所做的就是抬起那些维护你代码的人的眉毛。希望你有一个懒惰的程序员,只留下一些东西,否则你最终会失去这些代码。
因为在这个级别上没有任何保证,代码将在不同的平台上执行,如果给出不同的编译器,编译器选项和优化,您甚至可能会丢失编译器优化的代码。最好关注更大的问题。