• C

why do we use local variables in a loop?

Hi all,

Will  code 1 be faster than code 2. why?
THank you.

With Regards
HCK


Code 1:

      for(int n=0; n<N; n++){
             int s = ptr[0] - ptr[1] - ptr[2] + ptr[3];
                                 // other code using s
      }

Code 2:
               int s;
      for(int n=0; n<N; n++){
             s = ptr[0] - ptr[1] - ptr[2] + ptr[3];
                                // other code using s
      }
hengck23Asked:
Who is Participating?
 
brettmjohnsonConnect With a Mentor Commented:
Having implemented compilers, I can tell you that mrwad99 is absolutely incorrect in his
interpretation and grg99 is exactly correct.  In C, the storage space for all local variables
within a function is allocated at function entry (on x86 it looks like: mov bp, sp ; sub bp, ...)

From that perspective, there is little performance difference** between declaring all your
local variables at the beginning  of the function or within scope-limiting blocks.  Indeed,
the primary reason for declaring local variable in a limited scope is for code readability,
maintenance, and encapsulation of valid values.

Indeed, if ptr is never manipulated in the loop, a good optimizing compiler will move this
"loop invariant" code to outside the loop as follows:

    int s = ptr[0] - ptr[1] - ptr[2] + ptr[3];
    for(int n=0; n<N; n++){
         ...
    }


** One place where using limited-scope local variables helps is during the resource allocation
phase of compiler optimization.  Optimizing compilers assign data to resources
(in this case registers and stack memory) and can use the rules of scope to schedule the
availability of those resources. For instance, recursive functions (or any call constructs
with deep call stacks) with significant stack usage can adversely affect performance when
page faults occur to allocate additional stack space.  But consider the following:

int myFunc(...)
{
      {
            char aBuffer[1024];
            ...
      }
      ...
      {
            char anotherBuffer[2048];
            ...
      }
      ...
}

The brain-dead compiler will set aside 3KB of stack space for the two
buffers in the current frame.  An optimizing compiler can apply the rules
of scope to the allocation of stack resources - knowing that aBuffer[] and
anotherBuffer[] are never in scope at the same time, the compiler can
allocate 2KB of stack space and use it for both buffers.  That is an obvious
example, but it is equally applicable to small local variables:

int myFunc(...)
{
      {
            int i;
            ...
      }
      ...
      {
            int k;
            ...
      }
      ...
}

The limited scope helps the resource optimization assign i and k to the
same memory in stack frame, or better still, the same register on the CPU.

0
 
Sjef BosmanConnect With a Mentor Groupware ConsultantCommented:
Did you compare them using the assembly listing? Probably you won' see a difference. You might get faster using
    register int n
but it won't differ that much, and it's processor-dependent.
0
 
a_twixt_in_the_taleConnect With a Mentor Commented:
Use something like the zen timer to check which one works faster?
You might have to run it multiple times though to average out everything.

Here's one link
http://www.programmersheaven.com/zone3/cat487/13855.htm

:)
Don
0
Simple Misconfiguration =Network Vulnerability

In this technical webinar, AlgoSec will present several examples of common misconfigurations; including a basic device change, business application connectivity changes, and data center migrations. Learn best practices to protect your business from attack.

 
mrwad99Connect With a Mentor Commented:
Nobody has mentioned the fact that the integer variable 's' is created and destroyed N times in the first loop: in the second it is only created once and destroyed once.

>> int s = ptr[0] - ptr[1] - ptr[2] + ptr[3];

essentially that is copy construction of an integer, which is followed by the destruction (if you want to call it that) of an integer.

>>  s = ptr[0] - ptr[1] - ptr[2] + ptr[3];

That is merely assignment.  No construction, no destruction.

For that reason I strongly believe the second is faster.

And yeah you could put the register specifier in front of the n in the for loop, but modern compilers would optimize the code and do that anyway.

HTH
0
 
grg99Connect With a Mentor Commented:
Most every compiler will factor out the declaration, as it's MUCH easier to allocate the space ONCE at function entry, rather than allocate it every time the declaration block is entered.  And most compilers will allocate a register for "s" anyway, instead of explicitly allocating it stack space, unless it MUST have an address, such as if it's passed as a reference to another function.  Then again, declaring it in the outer block could confuse the optimizer, if it's a shaky optimizer.

So it could be faster, or could be slower, or could be the same speed.  Pretty dumb question, IYAM.


0
 
hengck23Author Commented:
I read somewhere that says

" Now we put all the pointers, strides and array sizes on
the stack (as local variables), so compiler can safely allocate some
of them on registers (Because the assumption that the current stack frame does
not overlap with heap or data segment is pretty safe :) )
Now compiler may not assume only that storing result to
C_data keeps A_data[...] and B_data[...] the same.
> So this is the next version (that can be further unrolled
and converted to SIMD intrinsics), that requires minimum compiler
intellect:"

>for( ; height--; )
> {
> for( x = 0; x < width; x++ )
> {
> int t0 = A_data[x] + B_data[x];
> int t1 = A_data[x] - B_data[x];
> C_data[x] = (char)t0;
> D_data[x] = (char)t1;
> }
> A_data += A_step;
> B_data += B_step;
> C_data += C_step;
> D_data += D_step;
> }

I was wondering in that case, should be always declared loop variables as local?
(in  this case, i mean int t0 , t1)
0
 
mrwad99Connect With a Mentor Commented:
>> should be always declared loop variables as local?

Well that depends on whether or not  you plan to use the variable outside of the loop at any time.  Most likely the answer to that will be no, so I think that all variables that will be used in a for loop should be local to that loop.

>> for( x = 0; x < width; x++ )

probably better to declare the variable x inside that loop too, i.e.

for(int x=0; ....)

>> (in  this case, i mean int t0 , t1)

well I think that we have given a pretty good description of the pros and cons of local declaration.

It would be interesting to hear *why* you want to know all this...
0
 
Sjef BosmanConnect With a Mentor Groupware ConsultantCommented:
Btw, as far as my compiler goes:
    for(int i=1; ...
isn't C, but C++

I agree with grg99. The the scope (visibility) of a local variable is a compile-time restriction, but during runtime there will be no compiler in/decreasing the stackspace just for the sake of a local var. So look at the assembly-listing of your code, you'll see for yourself that space for all local var's will be reserved at the beginning of the function. Something like a
    sub sp,20
 or so. All other stack movements (push/pop) are for arguments of called functions.
0
 
mrwad99Connect With a Mentor Commented:
>> isn't C, but C++

Yeah that is right, but as the original question goes it was used in there so I followed suit.  Perhaps the questioner should have asked this in the C++ area ?!
0
 
Sjef BosmanConnect With a Mentor Groupware ConsultantCommented:
So did I. The two languages are so much alike... Both my responses were C-based, but what a C++-compiler makes of it in assembly I wouldn't know. I suppose it won't make a big difference.

Somehow I never grew to like C++, it being "only" a C-dialect of the more interesting kind ;)
0
 
PaulCaswellConnect With a Mentor Commented:
My policy is generally to reduce the scope of any variable to its minimum. This has two useful results:

1. As was quite clearly described by brettmjohnson et al, some of the more 'intelligent' compilers can optimise it better.

2. If you ever come to chop the contents of the loop out into a separate function, the variables it uses are already 'close' enough.

Generally speaking, if you are worried about code speed, first optimise your algorithm, then use a different language, then twiddle bits. Bit tgwiddling should only be use as a last resort. Always 'optimise' for the next reader of the code.

Paul
0
 
ssnkumarCommented:
hengck23,

How you do programming, many (or most of the) times depend on what is your ultimate objective!
So, if your objective is readability and maintanance of code, then you will not look into whether it is optimized or not.
If optimization is the intention, then your code may lose on the side of readability!

In the first code that you posted, the intention was readability and easy understanding.

But as others have pointed out very clearly and also in detail, the more-intelligent compilers of modern days optimize your code more than what you can make out! If you are able to get back the source from the machine code, then you will not be in a position to recognize that it was the code written by you!!

-ssnkumar
0
 
aakash_mandharConnect With a Mentor Commented:
Ok.. Simple Answer...

To make programmers life easy..

A variable used inside the loop has the scope limited to the loop and cannot be used outside the loop..
You can have programs like....

int main()
{
int a=25;
{
int a=30;
printf("%d\n",a);
}
printf("%d",a);
}

The output will be:
30
25

This means the scope of the inner a is limited to inner loop and does not affect the value of the a outside the loop... When u have such conflicting variable declarations the value of the outer a is pushed onto the program stack and is popped when you exit the loop...

Another advantage is if you have a limited use of the variable and want to make sure you dont use it anywhere else by mistake limit its scope.... :)

Enjoy programming,,,,,,

Regards
Aakash
0
 
Sjef BosmanConnect With a Mentor Groupware ConsultantCommented:
Just another reason why I prefer C over C++. IMHO, declarations are only there to facilitate proper translation. They should be kept far away from the actual algorithm. I don't envy the poor sod who has to maintain code that's littered with declarations all over the place. That you use it for loop var's I can understand, but nowhere else.
0
 
ageraldnaveenConnect With a Mentor Commented:
From point of view,

both the code snips, will perform equally in speed.. there is no differentiating factor in terms of speed. however, the code 2 snip, would be holding that sizeof(int) bytes allocated for the variable "s" even after the for loop is done. thats all. If the variable "s" is declared inside the loop, there is no loss in performance at all.. there is nothing called as construction and destruction of a primitive data type like "int". All that is done is changes to the ESP stack pointer, which would anyway happen when there is atleast one local variable. So, code 1 is the better one, when the value of "s" is no longer required outside the for loop, and it costs no performance loss.
0
 
Sjef BosmanConnect With a Mentor Groupware ConsultantCommented:
If variables declared inside a loop were also created at that moment, the implementation would make snip 2 last longer, for temp. var's must be created and removed each time the loop starts.
So I cannot imagine the stack moves (please don't quote Galilei... ;)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.