0

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

我的问题是:这两种方法的性能有什么区别吗?在第一个中我使用 If-Else 语句,在第二个中我省略了 Else,因为 If 情况非常罕见。

编辑:假设我需要做的不仅仅是在满足条件时分配真/假,因此直接分配不是唯一需要做的事情。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();
                        }
                    }
                }
            }
...
4

5 回答 5

5

在您的示例中直接分配应该非常好:

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

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

关于 if/else 的更新问题:

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

猜测

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

在第一个中我使用 If-Else 语句,在第二个中我省略了 Else,因为 If 情况非常罕见。

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

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

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

在一般情况下, else 可能(将)包括通过称为branch prediction failure. 现代 CPU 会“猜测”程序流是否会通过ifelse并执行该分支。如果它后来发现它做出了错误的猜测,它必须回溯并通过正确的分支。

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

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

性能缓慢的第二个原因是没有利用称为数据局部性或参考局部性的东西。这意味着您应该使用靠近在一起的数据(例如 myArray[100] 和 myArray[101])。

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

先写一个正确的程序。然后优化它的痛处。也就是说,分析器显示您的程序花费了太多时间。优化无关紧要的事情是没有用的。

于 2013-05-22T17:43:23.110 回答
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);

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

于 2013-05-22T17:26:40.490 回答
0

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

于 2013-05-22T17:24:18.763 回答
0

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

于 2013-05-22T17:30:04.827 回答