1

In a MATLAB-function the following code is used:

function stuff()

  if a == 2

    do1();

  else

    do2();

  end
end

This code is placed inside a simulation-loop and gets called 1000 times or more per second. The if-statement does only matter in the first call of the function, after that either do1 or do2 are used, the variable a will not change any more.

How do I prevent to waste processing time with this if-statement? Basically, how do I tell Matlab, to not check the if-statement any more, and just call the one function, that gets selected in the first call to stuff?

Adriaan
  • 17,741
  • 7
  • 42
  • 75
Lemonbonbon
  • 686
  • 5
  • 25
  • 1
    Before optimizing, I would run the [profiler ](https://www.mathworks.com/help/matlab/ref/profile.html) to check whether the `if` statement is taking too much time. What does `a` depend on? The outcome of `stuff`? Depending on where/what you need to compare, you could also pass the correct function handle to `stuff`. – rinkert Jul 08 '19 at 12:49
  • 1
    You can use a function handle that points to `do1()` or `do2()` and set the function handle once, this way you do not need to know in advanced which function to call. But, using a function handle may cost more in performance than an `if` statement... – Eliahu Aaron Jul 08 '19 at 12:50
  • Because your code is working and you are just trying to improve performance, you may find more help by moving the question to [Code Review](https://codereview.stackexchange.com/) – Eliahu Aaron Jul 08 '19 at 12:54

3 Answers3

5

Contrary to your beliefs this is not a problem, the compiler (should) automatically does this optimization for you. See e.g. Loop-invariant code motion.

What you can do to help the compiler is to move the calculation of the check outside as a flag, e.g.

flag = a==2;
for i = 1:100
    stuff(flag)
end

Then you only have to do the calculation once and it is clear to the compiler that the value does not change.

NOTE: Obviously, if your check really is a==2, this would not make much of a difference.

EDIT: I have not been able to definitely verify that MATLAB does this automatically. However, this is only the first layer of optimization that is done for you. All modern processors use what is called a Branch predictor, see e.g. this brilliant answer Why is processing a sorted array faster than processing an unsorted array?, or this wiki page. In short, the processor guesses the result of the if-statement, if it is correct, everything goes faster. I think it is fair to say that the processor guesses correctly in all of your cases.

TLDR: Do not wory about it.

Nicky Mattsson
  • 3,052
  • 12
  • 28
  • Nicely put. My first thought also was why worry. – Cris Luengo Jul 08 '19 at 19:46
  • Interesting! @Lemonbonbon, I suggest you try this out and get back to us. You could have both functions in fact be the same one (so that they have the same calculation times), and then see if executing the loop with the if is significantly slower than the loop with only 1 function? In order to not trigger the "loop invariation", both functions would in fact have to be just slightly different to avoid them being seen as the same code, if I understand this correctly... – sg1234 Jul 08 '19 at 20:16
3

Given the comments above, it seems what you are actually looking for is a way to dynamically chose the function to be run in your simulation. This choice should be dynamic (you do not know which function to use at runtime) but the choice should only be done once. This is easily achievable using function handles: https://www.mathworks.com/help/matlab/function-handles.html

Here is an example:

    function dynamicSimulation()
        if ( rand() > 0.5 ) % determine which function should be called dynamically
            sim=@func1;
        else
            sim=@func2;
        end
        other_params = [];

        for k = 1:5 % run the simulation
            sim( k, other_params );
        end
    end

    function func1( index, other_params )
        fprintf( 'Index=%d: Simulating using function 1\n', index );
    end

    function func2( index, other_params )
        fprintf( 'Index=%d: Simulating using function 2\n', index );
    end

If you run this several times you will notice that the (random) choice of func1 or func2 will mean you do not get the same function being run each time, although the same one is used for the entire simulation.

sg1234
  • 600
  • 4
  • 19
  • 3
    Is the overhead of the function handle larger or smaller than the overhead of an `if` statement? – Cris Luengo Jul 08 '19 at 13:32
  • This seems to be a good solution (by design), but I am really interested in how much time this takes compared with the if statement. As a further note, the code should be useable for codegeneration. Are function handles possible with codegeneration? As far as I know everything using this stuff (OOP etc.) is not compatible with CG. – Lemonbonbon Jul 08 '19 at 13:36
  • 1
    @Lemonbonbon the difference in timing is only measurable by you, since you are the only one with the original code. Simply run the profiler using both versions and you'll know soon enough. Whether function handles work with code-generation is a different question altogether, and should be asked separately. – Adriaan Jul 08 '19 at 14:05
  • 3
    I did a small test to compare the total time of calling a function in a loop in three ways: 1. Directly 2. Function handle 3. Call a similar function but with an if - else statement. The results showed a marginal impact on time of the if-else and a significant impact of using a function handle. This is why i did not post this as an answer. – Eliahu Aaron Jul 08 '19 at 14:29
  • 1
    joining in a bit late: thanks @EliahuAaron for doing the benchmark, and I agree with Adriaan, your mileage could vary with your specific use case. My guess is that function handles are very much like function pointers, so little overhead expected, but I do not actually know this. As for code generation, please go through that link I mentioned re: handles, you will find the function str2func which might suit your needs. – sg1234 Jul 08 '19 at 19:42
  • 1
    @Lemonbonbon: As for the question whether functions handles work with code generation: This is easy for you to test. All you need to do is copy-paste the function written in this answer and try to apply the code generation to it. Since you have access to the code generation toolbox, this is likely easier for you test than for any of us that don't have access to that toolbox. – Cris Luengo Jul 08 '19 at 19:45
1

I reckon you don't waste much time on checking the validity that if statement. However, since you specifically mention it only checks for the first iteration: why not get that out? So instead of:

for ii = 1:10
    if ii == 1
        k = 1;
    else
        k = k + 1;
    end
end

You could do

k = 1;
for ii = 2:10
    k = k + 1;
end

Thus eliminating the check.

NB: this scales badly of course, but as it is only a single iteration here I consider it a good option.

Adriaan
  • 17,741
  • 7
  • 42
  • 75
  • But how to tell MATLAB then, that it has to call a spectific funktion (`do1` or `do2`) from now on? – Lemonbonbon Jul 08 '19 at 11:59
  • @Lemonbonbon you get the call to `do1` first, and then loop over `do2`. At least, I presume you will loop, as you haven't shown how `a` increments. The idea remains the same: first do the single call, then do the rest afterwards. If very complicated to get it out, you could even write two functions: one wrapping around `do1()`, and the other around `do2()` and then you can do it like described here. – Adriaan Jul 08 '19 at 12:01
  • Oh, maybe my question was not clear enough. I do not know weather do1 or do2 are used in the loop. This decision gets evaluated in the first call to stuff. After that do1 OR do2 are called for the rest of the simulation. – Lemonbonbon Jul 08 '19 at 12:03
  • 2
    @Lemonbonbon: The problem is that you **described** your code instead of **showing** your code. Showing is always better, it avoids misunderstandings. See [mre]. – Cris Luengo Jul 08 '19 at 12:59