Like Tree2Likes
  • 2 Post By JohnGraham

Using a global var into a local one

This is a discussion on Using a global var into a local one within the C Programming forums, part of the General Programming Boards category; Hello. Is the same this two ways of use n: Code: t_mytype * restrict n; // Global n void myfunc() ...

  1. #1
    Registered User
    Join Date
    Feb 2008
    Posts
    145

    Using a global var into a local one

    Hello.
    Is the same this two ways of use n:

    Code:
    t_mytype * restrict n; // Global n
    
    void myfunc() {
    	n->result = n->var1 + n->var2 + n->var3;
    }
    or this one:

    Code:
    t_mytype * restrict n; // Global n
    
    void myfunc() {
    	t_mytype * restrict p = n;
    	p->result = p->var1 + p->var2 + p->var3;
    }
    I read it is a good policy that when using a global var, prefer to copy it into a local one, but a quick speed test say to me 2 example is worse. As I dont absolutely sure what I do is correct, could you please explain me what system is better in order to use n (in terms of speed)

    thanks.

  2. #2
    Registered User
    Join Date
    Sep 2008
    Posts
    200
    Quote Originally Posted by Kempelen View Post
    I read it is a good policy that when using a global var, prefer to copy it into a local one, but a quick speed test say to me 2 example is worse.
    It is a very bad policy to prematurely optimize, which is exactly what you're doing. Just do whatever is easiest and simplest for you as a programmer (in this case, the first example) and do such optimisations if and only if you can demonstrate (i) that it's a performance bottleneck and (ii) that your optimisation actually makes things faster.


    Quote Originally Posted by Kempelen View Post
    As I dont absolutely sure what I do is correct, could you please explain me what system is better in order to use n (in terms of speed)
    In terms of speed, any decent compiler will do the above optimisation for you, so you just do what is easiest and let it handle it.

    Also, since you've declared `n' with the `restrict' keyword (why?) the second version is not only more work than you need, but is actually incorrect - you should not use another pointer to alias one declared `restrict'.
    Last edited by JohnGraham; 05-12-2011 at 04:15 AM.
    Salem and Bayint Naung like this.

  3. #3
    Registered User
    Join Date
    Feb 2008
    Posts
    145
    Quote Originally Posted by JohnGraham View Post
    It is a very bad policy to prematurely optimize, which is exactly what you're doing. Just do whatever is easiest and simplest for you as a programmer (in this case, the first example) and do such optimisations if and only if you can demonstrate (i) that it's a performance bottleneck and (ii) that your optimisation actually makes things faster.
    You are wrong. I am not prematurely optimizing. My program is now five years old, and I have done lots of optimization based on algorithms, recode and thinks like that. I am in the way of improve it, and what I posted is to understand a few issues about my code and if possible to optimeze it, and more important, to make things in a good way.

    Quote Originally Posted by JohnGraham View Post
    In terms of speed, any decent compiler will do the above optimisation for you, so you just do what is easiest and let it handle it.

    Also, since you've declared `n' with the `restrict' keyword (why?) the second version is not only more work than you need, but is actually incorrect - you should not use another pointer to alias one declared `restrict'.
    Maybe here I am wrong, but I declare restrict because I want the compiler to know I am not going to modify the content of the destination throught any pointer different than that, so it is able to done a few optimization based on that promise.

    The question comes to me because I have read than in the next example test2 is preferable to test1, and I wanted to know if it is the same for pointers and what they point. I repeat my main concert is not to make think like this, but first understand and see if I can make things better.
    Code:
        int f(void);
        int g(void);
        int errs;
    
        void test1(void)
        {
          errs += f();
          errs += g();
        }
    
        void test2(void)
        {
          int localerrs = errs;
          localerrs += f();
          localerrs += g();
          errs = localerrs;
        }

  4. #4
    Registered User
    Join Date
    Sep 2008
    Posts
    200
    Quote Originally Posted by Kempelen View Post
    You are wrong. I am not prematurely optimizing. My program is now five years old, and I have done lots of optimization based on algorithms, recode and thinks like that. I am in the way of improve it, and what I posted is to understand a few issues about my code and if possible to optimeze it, and more important, to make things in a good way.
    Fair enough, that was kind of an assumption on my part - but my original assertion was about whether it is (as your original post states) a good policy to do this for reasons of speed, and that's certainly not the case (in my humble opinion). As you also stated in your original post, this modification seems to have made your code slower, so you have your answer.


    Quote Originally Posted by Kempelen View Post
    I declare restrict because I want the compiler to know I am not going to modify the content of the destination throught any pointer different than that, so it is able to done a few optimization based on that promise.
    Sounds to me like you want to use `const' instead of `restrict'. `restrict' tells the compiler that the writes through that pointer won't change the value of any reads through any other pointers at all. In the case of your second example, a write through `n' would affect a read through `p' (and vice-versa, since they're both declared to be `restrict') so it should not be declared `restrict'. To be fair, I can't see how this would affect your example in practice, but I might be missing something and it's something that might affect the code around it.


    Quote Originally Posted by Kempelen View Post
    The question comes to me because I have read than in the next example test2 is preferable to test1...
    As I said, you have your answer because you've tested the alternate version.
    Last edited by JohnGraham; 05-12-2011 at 05:21 AM.

  5. #5
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Kempelen View Post
    Hello.
    Is the same this two ways of use n:

    I read it is a good policy that when using a global var, prefer to copy it into a local one, but a quick speed test say to me 2 example is worse.
    Where did you hear this? I have no heard this particular one before -- that you should keep the variable global, but then copy it onto the stack inside a function. Are you sure that's what is meant?

    The caveat against globals means you should avoid using them at all.

    You are right that this can seemingly involve performance compromises. "Seemingly", because in fact they are not all that significant. Generally, you are passing around pointers, meaning the bulk of your data is still on the heap (like a global); so the only extra work involved is the copying of the pointer value.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  6. #6
    Registered User
    Join Date
    Feb 2008
    Posts
    145
    Quote Originally Posted by MK27 View Post
    Where did you hear this? I have no heard this particular one before -- that you should keep the variable global, but then copy it onto the stack inside a function. Are you sure that's what is meant?
    I read it here: Writing Efficient C and C Code Optimization - CodeProject
    I copy the text

    Code:
    Global variables
    
    Global variables are never allocated to registers. Global variables can be changed by assigning them indirectly using a pointer, or by a function call. Hence, the compiler cannot cache the value of a global variable in a register, resulting in extra (often unnecessary) loads and stores when globals are used. We should therefore not use global variables inside critical loops.
    
    If a function uses global variables heavily, it is beneficial to copy those global variables into local variables so that they can be assigned to registers. This is possible only if those global variables are not used by any of the functions which are called.
    
    For example:
    Collapse
    
        int f(void);
        int g(void);
        int errs;
        void test1(void)
        {
          errs += f();
          errs += g();
        }
    
        void test2(void)
        {
          int localerrs = errs;
          localerrs += f();
          localerrs += g();
          errs = localerrs;
        }
    
    Note that test1 must load and store the global errs value each time it is incremented, whereas test2 stores localerrs in a register and needs only a single instruction.
    Quote Originally Posted by MK27 View Post
    The caveat against globals means you should avoid using them at all.
    That is an ideal world, I know, and i try it, but I use a vector of struct that is so long that can declare it local, but global, and accesed by pointers. That is the reason I ask my original question, it there are ways to optimize the use of that pointers.

  7. #7
    Registered User
    Join Date
    Sep 2008
    Posts
    200
    I got a 503 on your link, so I can't take a look at the whole page, but this section is just plain incorrect:

    Quote Originally Posted by Kempelen View Post
    Code:
    Global variables are never allocated to registers. ...Hence, the compiler cannot cache the value of a global variable in a register, resulting in extra (often unnecessary) loads and stores when globals are used.
    It may be correct for a particular compiler, but not in general. With the exception of variables declared `volatile', there is absolutely nothing in any C standard to say anything about whether or not a compiler may cache the value of a global. And anyway, you generally can't cache variables over function calls, as you have to assume the register may be clobbered - though there are exceptions in at least one ABI I've seen, there's absolutely nothing to say that applies only to local variables.

    And anyway, this is all moot - you've already stated that the second version of your original two examples is faster, so go with that one and try and find another way to get out of your bottleneck.
    Last edited by JohnGraham; 05-12-2011 at 06:29 AM.

  8. #8
    Registered User
    Join Date
    May 2010
    Location
    Naypyidaw
    Posts
    1,314
    Why don't you measure it? and see any improvement.

  9. #9
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    That page seems to have a lot of good ideas in it, but, presuming John's criticism is correct, I would stick to the ones that make obvious logical sense vs. ones like this, which depend upon compiler tricks not part of the C standard. I think the same is true of things that have to do with "some processors" (eg, "Some processors can handle unsigned integer arithmetic considerably faster than signed") -- don't bother with that.*

    It does sound strange to me that "the compiler cannot cache the value of a global variable in a register, resulting in extra (often unnecessary) loads and stores when globals are used." Perhaps may not instead of cannot would be more accurate? It also sounds like the kind of issue that might be determined by the use of a compiler switch/optimization level.

    * on the other hand, the caveat that the processor deals with int sized data faster than shorts or single chars is I think universally true. I guess you will have to take stuff with a grain of salt. If you ask here, someone(s) will probably have some idea about what's worth bothering about.
    Last edited by MK27; 05-12-2011 at 07:31 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  10. #10
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by Kempelen View Post
    If a function uses global variables heavily, it is beneficial to copy those global variables into local variables so that they can be assigned to registers. This is possible only if those global variables are not used by any of the functions which are called.
    Read that again... copy the globals, but don't use them?

    Of course that also forgets the time wasted initially copying the variables to the stack... If you're going to be in that function for a long time and only need 2 or 3 ints from global sources it may catch up to itself, but one should reasonably think the time lost making copies of anything sizeable would outweigh the minor benefit of having them loaded into registers for 2 or 3 quicky operations.

    That is an ideal world, I know, and i try it, but I use a vector of struct that is so long that can declare it local, but global, and accesed by pointers. That is the reason I ask my original question, it there are ways to optimize the use of that pointers.
    About the only optimization from your original code sample would be to pass in a pointer directly to the answer and the values needed in the calculation...

    Assuming int....

    Code:
    t_mytype *n; // Global n
    
    void myfunc(int *result, int v1, int v2, int v3 ) {
    	*result = v1 + v2 +v3;
    }
    
    //called as...
    myfunc(&n->result,n->var1,n->var2,n->var3);
    That would effectively copy the variables to the stack (through the PUSH activity when entering the function) and it would place the result directly in your vector for you. Not only does this let the compiler do register optimization for you, it's a much better programming practice, even with global variables.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. From global to local variable
    By urban1990 in forum C Programming
    Replies: 11
    Last Post: 10-12-2010, 11:24 PM
  2. Local vs Global Variables
    By BENCHMARKMAN in forum C++ Programming
    Replies: 5
    Last Post: 07-03-2007, 05:17 AM
  3. Global Vs Local Variables
    By Waldo2k2 in forum C++ Programming
    Replies: 17
    Last Post: 11-11-2002, 06:51 PM
  4. global or local
    By Unregistered in forum C Programming
    Replies: 5
    Last Post: 06-06-2002, 11:11 AM
  5. global and local variables
    By Unregistered in forum C++ Programming
    Replies: 2
    Last Post: 10-02-2001, 01:17 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21