Which is more CPU intensive?

04 Apr 2011

Hello,

I'm wanting to try and cut down on possible memory error / fragmentation issues in my program. I was wondering which is harder on the CPU? * BTW: The math is meaningless... I'm trying to undersand the difference in how these vailables are declared... Imagine a huge program running all sorts of calcs very fast...

--- Example1: ---

int counter = 0; int a = 0; int b = 0;

int main() {

while (1) {

counter++; a = counter; b = (a + counter); if(counter >= 1000){counter = 0;}

}

}

--- Example2: ---

int counter = 0;

int main() {

while (1) {

counter++; int a = counter; int b = (a + counter); if(counter >= 1000){counter = 0;}

}

}

04 Apr 2011

Hi Tim,

I'd expect there to be no difference. All the variables will be allocated in registers for the duration of the loop, so it doesn't really matter.

But example 2 is preferred for general code as it does not rely on the compiler having to determine the scope/use of the variables a and b beyond the while loop (in example 1, they are global), so is easier to know that you'll get the best results. In particular, it is obvious the lifetime of the variables in example 2, whereas it is less obvious in example 1; the compiler can often work this out fine, but someone reading the code may not spot it so easily.

Three examples, from largest to smallest in terms of scoping for a basic loop:

int i;
int main() {
    for(i=0; i<n; i++) { ... }
}

int main() {
    int i;
    for(i=0; i<n; i++) { ... }
}

int main() {
    for(int i=0; i<n; i++) { ... }
}

In general, it is best to keep the scope of variables as small as possible to get the most optimal results and to keep code clean. It'll also help the compiler make the best use of registers and simplify allocation, often avoiding the need to spill to the stack or redundantly save back to memory. Global variables really should only be used where they are required.

Simon

04 Apr 2011

However, when considering the overall performance picture, realize that Simon's second and third examples add uncertainty to your program, both in execution speed and stack usage. When running hard realtime, you may actually want to use global variables instead of having a wildly variable stack.

The bottom line is that you have to understand the ramifications of doing it each of the three suggested ways. Memory leaks, errors, and fragmentation can't happen if you declare everything global and don't use stack or heap allocations. You can, however, mess up if you don't pay careful attention to variable names and where you use each variable.

I have seen a lot of folks with realtime software that hangs or does unexpected things simply because they think that the second and third methods are preferred. They can't even debug their programs properly because of stack overflows, etc. If you are looking for consistent performance, particularly with a lot of variables and a throughput requirement, I would use number one above, but be very careful about naming and using the globals.

And by the way, none of the methods are "harder" on the CPU. It simply does exactly what you tell it to do.

Regards,

- Gary

04 Apr 2011

Hmm, I think the second one might be faster. Since a and b are local to the loop, and are never used, the compiler can optimize them away. It could do so in the first example, but it might be harder to do. IMHO a loop variable (Simons third example) should never ever be placed on a stack by the compiler, so it shouldn't add uncertainty to the runtime behavior.

05 Apr 2011

The use of local variable is often faster when optimization is turned on. With optimization, local var could be allocated on registers instead of memory so access is always faster than from memory. Local var could also use stack when it cannot be allocated on registers, then there would be no difference. In that case, as Gary stated, you must be careful with stack size. Usually when stack overflow happens the program crashes immediately upon the function returns.

05 Apr 2011

Thanks Guys. I really appreciate the feedback. I'm not at all smart about how these PICs actually work... In my mind I think if the variable is global it has persestence... This comment from Gary is what I was thinking too... << Memory leaks, errors, and fragmentation can't happen if you declare everything global and don't use stack or heap allocations >>

My thought was that if you were not declaring and destroying variables over and over again that it would be less stress on the CPU bcause it does not have to process it in the stack? Or whatever method it uses to determine what memory space is to be used for that brief moment the variable is declared and used...

I'm a real stickler for good naming practices... IMHO Anyway.. I tend to use global variables and structures in my app... But there are places where I just declare it on the fly and I was curious to know what added load that put's on the prcessor...

Thanks again for the great feedback! :-)

--

05 Apr 2011

Ideally, you would want the stack size to be consistent. If your application calls many different subroutines/subfunctions, make sure that the stack size returns to its original size after calling a subroutine. This is particularly important if you want your program to run infinitely without crashing (the stack will never overflow if you are careful with designing your application and its usage with variables).