0

I'm writing a Monte Carlo simulation in c# and I'm trying to make sure that I write code which is as efficient as possible---I'm running billions of loops and things are getting slow. I have a question about using Else statements inside loops.

My question is this: Is there any difference in performance between these two methods? In the first I use an If-Else statement and in the second I omit the Else, because the If case is quite rare.

EDIT: Lets assume I need to do more than just assign true/false when the condition is met, so that direct assignment isn't the only thing that needs to be done. Does the if-Else way perform just as quickly?

       //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();
                        }
                    }
                }
            }
...
FakeDIY
  • 1,425
  • 2
  • 14
  • 23

5 Answers5

5

Directly assigning should be perfectly fine in your sample:

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

Side note: it may be good idea to experiment with caching array access - should be able to cache var row = BooleanAnswerArray[index][x] so you avoid extra indexing in innermost loop.

On updated question with if/else:

First of - this is performance question so one must measure different options and see if code meets the goals. Stopwatch class is usually enough for such localized performance comparisons, otherwise profiler may be needed.

Speculations

  • if will cause exactly the same impact whether it has one or both branches especially in presence of any other non-trivial code like non-inlined function call.
  • loop unrolling may have more impact (also make code less readable)
  • caching as much as possible may have more impact
Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
  • 1
    The code is nicer here. I would hope the optimizer did exactly that. – zmbq May 22 '13 at 17:26
  • Lets assume, just for interest, that I need to do more than just assign true/false---ie I need to do a few things inside the if loop. I've updated the question slightly to reflect this requirement. – FakeDIY May 22 '13 at 17:33
  • @FakeDIY - I've added my thought on it - I strongly advise to try and measure - it will likely be very code specific. – Alexei Levenkov May 22 '13 at 17:47
  • Can you point me in the direction of some info on caching the array access? My code features a lot of similar operations and it sounds like it may be worth experimenting with. – FakeDIY May 23 '13 at 07:38
  • @FakeDIY in innermost loop you are getting element by all 3 indexes `[index][x][y]` - depending on JIT's ability it may be already optimized into `var row = BooleanAnswerArray[index][x]` in outer loop and `row[y]` in inner loop, or you may try to do it yourself and measure. – Alexei Levenkov May 23 '13 at 16:05
2

In the first I use an If-Else statement and in the second I omit the Else, because the If case is quite rare.

That just means your second program does not perform exactly as the first (unless you can prove that the else will never be required...). So it's not a problem of performance, your second program is wrong (assuming your first program is correct and the else is required).

Fast programs that don't output the correct results are kind of a bad thing.

In this particular case a good compiler will optimize the code to something like alzaimar's answer. You should write it like that too, though, for readability.

In the general case, an else may(will) include a performance penalty through something called branch prediction failure. A modern CPU will "guess" whether the program flow will go through the if or the else and execute that branch. If it later discovers it made the wrong guess it has to backtrack and go through the correct branch.

If this actually becomes an issue, you should make sure that the order in which the if and else branches are used follows a simple pattern.

See this question and its answers for more details.

A second cause of slow performance would come from not taking advantage of something called data locality or locality of reference. This means that you should use data that is close together (such as myArray[100] and myArray[101]) close together.

In your particular case, don't change the order in which you index your array.

Write a correct program first. Then optimize it where it hurts. That is, where a profiler shows your program spends too much time. It's no use optimizing things that don't matter.

Community
  • 1
  • 1
Andrei
  • 4,880
  • 23
  • 30
  • +1 for "Fast programs that don't output the correct results are kind of a bad thing." – aqua May 22 '13 at 21:17
  • I think if you read the code, you'll see that the end result is identical. – FakeDIY May 23 '13 at 07:38
  • @FakeDIY You mean without the `else`? Only if you guarantee that the array was previously initialized to `false`. – Andrei May 23 '13 at 19:38
  • @FakeDIY Sorry, I saw what you mean. I missed the part where is set the variable to false... I guess I was more focused on writing it as `BooleanAnswerArray[index][x][y] = SomeFunction(index,x,y);`. Now the version without the `else` has a change to behave worse, depending on the compiler. The conclusion still stands, write a correct program first, optimize it later as needed. – Andrei May 23 '13 at 19:47
1

What prevents you from simplifying the code as follows:

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);

Sorry for kicking the braces. I don't like them too much ;-)

alzaimar
  • 4,572
  • 1
  • 16
  • 30
  • Lets assume I need to do more than just assign true/false---ie I need to do a few things inside the if loop. I've updated the question slightly. – FakeDIY May 22 '13 at 17:33
  • That's what 50% of the programmers say who I talk to. The other 50% think, that having braces around single line statements make the code harder to read. Thanks god I have a formatter who takes care of either case. – alzaimar May 22 '13 at 18:19
0

the first one should be marginally faster. but if I were you I would care more about readable code than well performing code (that is till you start doing something millions of times)... just my 2c

Z .
  • 12,657
  • 1
  • 31
  • 56
  • I agree with you, readable code is the best kind of code---but I'm doing this literally billions of times so if I can get a performance boost by doing something simple then I would like to! – FakeDIY May 22 '13 at 17:26
0

Your method 1 does the 3-level index calculation only once instead of twice. Whether the compiler could optimize that is iffy. But of course, everything depends on the relative time used by SomeFunction.

Mike Dunlavey
  • 40,059
  • 14
  • 91
  • 135
  • `SomeFunction` is actually (`LookupTable[index][x][y] > someValue`) – FakeDIY May 22 '13 at 17:35
  • I would be inclined to be advancing a pointer, because that indexing can be a major cost. Being C#, you could do an equivalent thing by advancing a single index. – Mike Dunlavey May 22 '13 at 17:43