在循环中使用Else语句会导致性能下降吗?

时间:2013-05-22 17:21:47

标签: c# performance loops if-statement

我正在用c#编写蒙特卡罗模拟,我正在努力确保编写尽可能高效的代码 - 我正在运行数十亿个循环,而且事情变得越来越慢。我有一个关于在循环中使用Else语句的问题。

我的问题是:这两种方法的性能有何不同?在第一个我使用If-Else语句,在第二个我省略了Else,因为If案例非常罕见。

编辑:假设我需要做的不仅仅是在满足条件时分配true / false,因此直接赋值不是唯一需要完成的事情。 if-Else方式的执行速度是否同样快?

       //METHOD 1
 ...       
            for (int index = 0; index < 6; index++)
            {
                for (int x = 0; x < 50; x++)
                {
                    for (int y = 0; y < 50; y++)
                    {


                        bool ThingWhichIsVeryRarelyTrue = SomeFunction(index,x,y);
                        if (ThingWhichIsVeryRarelyTrue)
                        {
                            BooleanAnswerArray[index][x][y] = true;
                            DoSomeOtherStuff();
                        }
                        else
                        {
                            BooleanAnswerArray[index][x][y] = false;
                        }
                    }
                }
            }
    ...
    //METHOD 2
    for (int index = 0; index < 6; index++)
            {
                for (int x = 0; x < 50; x++)
                {
                    for (int y = 0; y < 50; y++)
                    {
                        BooleanAnswerArray[index][x][y] = false;
                        bool ThingWhichIsVeryRarelyTrue = SomeFunction(index,x,y);
                        if (ThingWhichIsVeryRarelyTrue)
                        {
                            BooleanAnswerArray[index][x][y] = true;
                            DoSomeOtherStuff();
                        }
                    }
                }
            }
...

5 个答案:

答案 0 :(得分:5)

您的样本中的直接分配应该非常好:

 BooleanAnswerArray[index][x][y] = SomeFunction(index,x,y);

旁注:尝试缓存数组访问可能是个好主意 - 应该能够缓存var row = BooleanAnswerArray[index][x],以避免在最里面的循环中进行额外的索引。

使用if / else:

更新问题

首先 - 这是性能问题,因此必须衡量不同的选项,看看代码是否符合目标。 Stopwatch类通常足以进行此类本地化性能比较,否则可能需要分析器。

思考

  • if将产生完全相同的影响,无论它是否具有一个或两个分支,尤其是在存在任何其他非平凡代码(如非内联函数调用)的情况下。
  • 循环展开可能会产生更多影响(也会降低代码的可读性)
  • 尽可能地缓存可能会产生更大的影响

答案 1 :(得分:2)

  

在第一个我使用If-Else语句,在第二个我省略了   否则,因为If案件非常罕见。

这只意味着你的第二个程序与第一个程序完全不同(除非你能证明永远不需要else ......)。所以这不是性能问题,你的第二个程序错误(假设你的第一个程序是正确的,而其他是必需的)。

没有输出正确结果的快速程序是件坏事。

在这种特殊情况下,一个好的编译器会将代码优化为像alzaimar的答案。不过,为了便于阅读,你应该这样写它。

在一般情况下,其他人可能(将)通过名为branch prediction failure的内容包含性能损失。现代CPU将“猜测”程序流是通过if还是else并执行该分支。如果它后来发现它做错了猜测它必须回溯并通过正确的分支。

如果这确实成为一个问题,您应该确保使用ifelse分支的顺序遵循一个简单的模式。

有关详细信息,请参阅this问题及其答案。

性能下降的第二个原因是不利用称为数据局部性或locality of reference的东西。这意味着您应该使用靠近的数据(例如myArray [100]和myArray [101])。

在您的特定情况下,请勿更改数组索引的顺序。

先写一个正确的程序。然后在受伤的地方进行优化。也就是说,探查器显示您的程序花费了太多时间。优化无关紧要的事情是没有用的。

答案 2 :(得分:1)

什么阻止您按如下方式简化代码:

for (int index = 0; index < 6; index++)
  for (int x = 0; x < 50; x++)
    for (int y = 0; y < 50; y++)
      BooleanAnswerArray[index][x][y] = SomeFunction(index,x,y);

抱歉踢踢牙套。我不太喜欢他们; - )

答案 3 :(得分:0)

第一个应该稍快一点。但如果我是你,我会更关心可读代码而不是表现良好的代码(直到你开始做数百万次的事情)...只是我的2c

答案 4 :(得分:0)

您的方法1只进行一次3级索引计算而不是两次。 编译器是否可以优化它是不确定的。 但当然,一切都取决于SomeFunction使用的相对时间。