2

I need to use an array in a loop, and the loop time is very huge.

Case 1: define the array outside the for-loop and pass it to fun2

void fun1(){
    int temp[16];
    for(int i = 0;i <times; i++)
    {
        fun2(temp);
    }       
}

void fun2(int[]& temp){
    /**  do something with temp*/
}

Case 2: define the array in fun2:

void fun1() {
    for (int i = 0; i < times; i++)
    {
        fun2();
    }
}

void fun2() {
    int temp[16];
    /**  do something with temp */
}

fun1 will be called very often. In this situation, which is better?

Does Case 2 have some influence on performance?

rustyhu
  • 1,912
  • 19
  • 28
my zhu
  • 21
  • 2
  • 1
    Check the generated assembly code. Although I have doubts that passing it in as an argument to the function would be more efficient – UnholySheep Dec 21 '21 at 15:16
  • I don't think either version will change performance by a significant amount in release mode. If anything I expect case #1 will be slightly slower when optimizations are turned on and not using debug mode. – drescherjm Dec 21 '21 at 15:16
  • 4
    If it really matters, don't guess, measure it. If not, then you're wasting your time, pick whichever makes more sense from a functional perspective and move on. – spectras Dec 21 '21 at 15:21
  • Now my above comment relates to `int temp[16];`. If you had `myClass temp[16];` my answer would be different and the behavior of the 2 code versions would also be different. – drescherjm Dec 21 '21 at 15:26
  • 4
    Reusing variables for multiple purposes is a suprisingly reliable way to introduce bugs. Declare as close to use as possible, rethink if it turns out to be a performance problem. (It may surprise you, but the first version actually does more work than the second.) – molbdnilo Dec 21 '21 at 15:29
  • `int[]& temp` looks wrong. If you intend to pass an array by reference it should be `void fun2(int (& temp)[16])`. Or just `fun2(int[] temp)`, which is equal to `fun2(int *temp)` which will pass a pointer to the first element. – Lukas-T Dec 21 '21 at 15:38
  • @OP -- The code you write is only a description of what you want to do. The compiler is then free to make any optimizations to your code, and most times, the optimized code looks nothing like your original source code (which is why it is difficult to debug optimized programs). The only result you care about is that the optimized code produces the results your program is supposed to generate. Thus two almost identical code snippets will more than likely not have any difference in performance. – PaulMcKenzie Dec 21 '21 at 15:48
  • I agree with everyone that the optimizer will do almost all the leg work. However, eyeballing my prediction would be Case 1 > Case 2. This is because the stack will be allocating and de-allocating in Case 2. Whereas in Case 1 the performance cost will be passing it. Question is: passing speed vs allocate and de-allocate speed. Also I agree alot with moldbnilo. Try and use function scope to limit bug introduction. Case 1 would have a high chance at creating bugs/unexpected behaviour. Measure and decide if it is worth it! – Frebreeze Dec 21 '21 at 15:54
  • Does this answer your question? [Declaring variables inside loops, good practice or bad practice?](https://stackoverflow.com/questions/7959573/declaring-variables-inside-loops-good-practice-or-bad-practice) – DanielTuzes Dec 21 '21 at 16:22
  • If fun1 do not need temp, why it should be created and passed? Do you expect, creating a heap var takes time? As third version you can use a static var if it is guaranteed that you have no race conditions. Passing a reference is not a big deal and will be optimized. The rest is: measure! – Klaus Dec 21 '21 at 17:03

2 Answers2

1

If you look for an answer to the general case, the answer is, "it depends." If you want an answer to your specific example, the answer is that the second version will be more efficient.

Ask yourself:

  1. Is there a cost to construction / destruction / reuse?

In your example, there is none (except adjusting the stack pointer, which is extremely cheap). But if it was an array of objects, or if you had to initialize the array to a specific value, that changes.

  1. How does the cost of parameterization factor in?

This is very minor but in your first case, you pass a pointer to the function. If the function is not inlined, this means that the array can only be accessed through that pointer. This takes up one register which could be used otherwise. In the second example, the array can be accessed through the stack pointer, which is basically free.

It also affects alias and escape analysis negatively which can lead to less efficient code. Basically, the compiler has to write values to memory instead of keeping them in registers if it cannot prove that a following memory read may not refer to the same value.

  1. Which version is more robust?

The second version ensures that the array is always properly sized. On the other hand, if you pass an object whose constructor may throw an exception, constructing outside the function may allow you to throw the exception at a more convenient location. This could be significant for exception safety guarantees.

  1. Is there a benefit in deallocating early?

Yes, allocation and deallocation are costly, but early destruction may allow some reuse. I've had cases where deallocating objects early allowed reuse of the memory in other parts of the code which improved use of the CPU cache.

Homer512
  • 9,144
  • 2
  • 8
  • 25
0

depends on what you want to achieve..in this case, i'm assuming you are looking for performance which case 2 would be the better option as the function would create the variable on the fly instead of trying to get the variable globally then its value.

GreyKvng
  • 1
  • 1