Memory access optimization

Discussion in 'C++' started by rodneys@gmx.de, Jan 11, 2006.

  1. Guest

    Hi,

    please take a look to this sample code:

    class MyClass {
    private:
    static int length ;
    public:
    static void setLength(int newLength) ;
    void do() ;
    }

    int MyClass::length ;

    void MyClass::setLength(int newLength) {
    length=newLength ;
    }

    void MyClass::do() {
    for(int i=0;i<length;i++) {
    // some simple floating point additions and multiplications ...
    }
    }

    I expected that the compiler (Microsoft EVC 4 for ARM, full
    optimization)
    would optimize the for-loop of the method "do" to
    register int t=length ;
    for(int i=0;i<t;i++) {
    ...
    }
    But this does not happen. Instead, the generated machine code
    refetches "length" in each iteration of the for-loop. Why?
    Does the compiler "fear" that another thread could call "setLength"
    while the for-loop runs? "length" is *not* declared volatile.

    Is there a formal specification how long a compiler is allowed to cache
    non-local variables in registers? For example, can code like
    a = length ;
    b = length ;
    always be expected to be optimized to
    register int t=length ;
    a=t ;
    b=t ;
    ?

    rs
     
    , Jan 11, 2006
    #1
    1. Advertising

  2. wrote:
    > Hi,
    >
    > please take a look to this sample code:
    >
    > class MyClass {
    > private:
    > static int length ;
    > public:
    > static void setLength(int newLength) ;
    > void do() ;
    > }
    >
    > int MyClass::length ;
    >
    > void MyClass::setLength(int newLength) {
    > length=newLength ;
    > }
    >
    > void MyClass::do() {
    > for(int i=0;i<length;i++) {
    > // some simple floating point additions and multiplications ...
    > }
    > }
    >
    > I expected that the compiler (Microsoft EVC 4 for ARM, full
    > optimization)
    > would optimize the for-loop of the method "do" to
    > register int t=length ;
    > for(int i=0;i<t;i++) {
    > ...
    > }
    > But this does not happen. Instead, the generated machine code
    > refetches "length" in each iteration of the for-loop. Why?
    > Does the compiler "fear" that another thread could call "setLength"
    > while the for-loop runs? "length" is *not* declared volatile.
    >
    > Is there a formal specification how long a compiler is allowed to cache
    > non-local variables in registers? For example, can code like
    > a = length ;
    > b = length ;
    > always be expected to be optimized to
    > register int t=length ;
    > a=t ;
    > b=t ;
    > ?
    >
    > rs
    >


    rule of thumb is to cache any global variable in a local variable to
    ease optimization for the compiler. If a register is available, it will
    be allocated for the local variable. If none is available, the local
    varialbe will most likely be allocated on stack and therefore will most
    likely have a better cache behaviour than its global counterpart. The
    compiler might even be capable of eliminating the local variable.

    I cannot say what the reason for missing optimization is your case,
    because you omitted the contents of the for loop. But I recomend to
    allocate a local variable that is the copy of the object attribute.

    HTH,
    Tom
     
    Thomas Maier-Komor, Jan 11, 2006
    #2
    1. Advertising

  3. mlimber Guest

    wrote:
    > Hi,
    >
    > please take a look to this sample code:
    >
    > class MyClass {
    > private:
    > static int length ;
    > public:
    > static void setLength(int newLength) ;
    > void do() ;
    > }
    >
    > int MyClass::length ;
    >
    > void MyClass::setLength(int newLength) {
    > length=newLength ;
    > }
    >
    > void MyClass::do() {
    > for(int i=0;i<length;i++) {
    > // some simple floating point additions and multiplications ...
    > }
    > }
    >
    > I expected that the compiler (Microsoft EVC 4 for ARM, full
    > optimization)
    > would optimize the for-loop of the method "do" to
    > register int t=length ;
    > for(int i=0;i<t;i++) {
    > ...
    > }
    > But this does not happen. Instead, the generated machine code
    > refetches "length" in each iteration of the for-loop. Why?
    > Does the compiler "fear" that another thread could call "setLength"
    > while the for-loop runs? "length" is *not* declared volatile.
    >
    > Is there a formal specification how long a compiler is allowed to cache
    > non-local variables in registers? For example, can code like
    > a = length ;
    > b = length ;
    > always be expected to be optimized to
    > register int t=length ;
    > a=t ;
    > b=t ;
    > ?
    >
    > rs


    There is no formal specification for such optimizations in the
    Standard. You might be better off posting in Microsoft-specific group
    where more of their experts lurk. Several such groups are listed in
    this FAQ:

    http://www.parashift.com/c -faq-lite/how-to-post.html#faq-5.9

    Cheers! --M
     
    mlimber, Jan 11, 2006
    #3
  4. Guest

    > There is no formal specification for such optimizations in the
    > Standard. You might be better off posting in Microsoft-specific group
    > where more of their experts lurk. Several such groups are listed in
    > [...]


    I know that it may be a MS-specific thing but I wanted to know what
    c.l.c++ thinks about it. Do you agree with me that nothing in the specs
    prevents the compiler from doing the optimization unless the variable
    is declared volatile?

    rs
     
    , Jan 11, 2006
    #4
  5. David Harmon Guest

    On 11 Jan 2006 06:00:59 -0800 in comp.lang.c++,
    wrote,
    >I know that it may be a MS-specific thing but I wanted to know what
    >c.l.c++ thinks about it. Do you agree with me that nothing in the specs
    >prevents the compiler from doing the optimization unless the variable
    >is declared volatile?


    I think you are right.
     
    David Harmon, Jan 11, 2006
    #5
  6. <> wrote in message
    news:...
    > > There is no formal specification for such optimizations in the
    > > Standard. You might be better off posting in Microsoft-specific group
    > > where more of their experts lurk. Several such groups are listed in
    > > [...]

    >
    > I know that it may be a MS-specific thing but I wanted to know what
    > c.l.c++ thinks about it. Do you agree with me that nothing in the specs
    > prevents the compiler from doing the optimization unless the variable
    > is declared volatile?
    >
    > rs
    >


    Why don't you make the length variable a local and see what MSVC does ?
    Although "length" is not declared as voltaile, in typical MS manner, they
    might
    have tried to anticipate that you might be modifying "length" in another
    thread
    and so get the value each iteration of the loop.
     
    Dave Townsend, Jan 11, 2006
    #6
  7. Bo Persson Guest

    "Dave Townsend" <> skrev i meddelandet
    news:...
    >
    > <> wrote in message
    > news:...
    >> > There is no formal specification for such optimizations in the
    >> > Standard. You might be better off posting in Microsoft-specific
    >> > group
    >> > where more of their experts lurk. Several such groups are listed
    >> > in
    >> > [...]

    >>
    >> I know that it may be a MS-specific thing but I wanted to know what
    >> c.l.c++ thinks about it. Do you agree with me that nothing in the
    >> specs
    >> prevents the compiler from doing the optimization unless the
    >> variable
    >> is declared volatile?
    >>
    >> rs
    >>

    >
    > Why don't you make the length variable a local and see what MSVC
    > does ?
    > Although "length" is not declared as voltaile, in typical MS manner,
    > they
    > might
    > have tried to anticipate that you might be modifying "length" in
    > another
    > thread
    > and so get the value each iteration of the loop.


    Yes. The length is globally accessible through the public static
    function setLength. To be able to cache the length, the compiler must
    first prove that no one is ever calling setLenght while the loop runs.

    That's hard to do in the general case, so they have obviously not
    bothered.


    Bo Persson
     
    Bo Persson, Jan 12, 2006
    #7
  8. Guest

    > Yes. The length is globally accessible through the public static
    > function setLength. To be able to cache the length, the compiler must
    > first prove that no one is ever calling setLenght while the loop runs.


    As already discussed above, the specs don't force the compiler
    to prove anything, do they?

    Ramin
     
    , Jan 12, 2006
    #8
  9. Guest

    > Why don't you make the length variable a local and see what MSVC does ?

    First thing I tried. As expected, the local variable is kept in a
    register
    (plenty of free registers in the ARM processor).

    > Although "length" is not declared as voltaile, in typical MS manner, they
    > might have tried to anticipate that you might be modifying "length" in
    > another thread and so get the value each iteration of the loop.


    As an experiment, I removed the setter-method and initialized the
    variable
    via
    static MyClass::length=10 ;
    so that the variable is never write-accessed in the code. No difference
    :-(

    I suppose that optimization on global data is generally very difficult
    in languages like C/C++ where the compiler has to assume that you can
    modify any variable indirectly with some pointer arithmetic+type casts.

    Ramin
     
    , Jan 12, 2006
    #9
  10. Bo Persson Guest

    <> skrev i meddelandet
    news:...
    >> Yes. The length is globally accessible through the public static
    >> function setLength. To be able to cache the length, the compiler
    >> must
    >> first prove that no one is ever calling setLenght while the loop
    >> runs.

    >
    > As already discussed above, the specs don't force the compiler
    > to prove anything, do they?


    Yes, they do. Using volatile prevents the compiler from keeping the
    value in a register. Not using volatile doesn't automatically allow
    caching. The compiler must first make sure that the value is not
    updated any other way. If the variable is global, or accessible
    through a public function, that is hard.

    Consider this code:

    int i;

    void f(int& j)
    {
    for (i = 0; i < 10; i++)
    j = i;
    }

    int main()
    {
    int k;

    f(k);
    f(i);

    }

    What happens for f(k) ?
    What happens for f(i) ?

    Does that affect the optimizations possible for the function f()? It
    sure does!


    Bo Persson
     
    Bo Persson, Jan 12, 2006
    #10
  11. Bo Persson Guest

    "Bo Persson" <> skrev i meddelandet
    news:...
    >
    > <> skrev i meddelandet
    > news:...
    >>> Yes. The length is globally accessible through the public static
    >>> function setLength. To be able to cache the length, the compiler
    >>> must
    >>> first prove that no one is ever calling setLenght while the loop
    >>> runs.

    >>
    >> As already discussed above, the specs don't force the compiler
    >> to prove anything, do they?

    >
    > Yes, they do. Using volatile prevents the compiler from keeping the
    > value in a register. Not using volatile doesn't automatically allow
    > caching. The compiler must first make sure that the value is not
    > updated any other way. If the variable is global, or accessible
    > through a public function, that is hard.
    >
    > Consider this code:
    >
    > int i;
    >
    > void f(int& j)
    > {
    > for (i = 0; i < 10; i++)
    > j = i;
    > }


    Ok, this was a bad example. Change the line to j = 1; to show the
    problem with f(i).

    >
    > int main()
    > {
    > int k;
    >
    > f(k);
    > f(i);
    >
    > }
    >
    > What happens for f(k) ?
    > What happens for f(i) ?
    >
    > Does that affect the optimizations possible for the function f()? It
    > sure does!
    >
    >
    > Bo Persson
    >
     
    Bo Persson, Jan 12, 2006
    #11
  12. mlimber Guest

    Bo Persson wrote:
    > <> skrev i meddelandet
    > news:...
    > >> Yes. The length is globally accessible through the public static
    > >> function setLength. To be able to cache the length, the compiler
    > >> must
    > >> first prove that no one is ever calling setLenght while the loop
    > >> runs.

    > >
    > > As already discussed above, the specs don't force the compiler
    > > to prove anything, do they?

    >
    > Yes, they do. Using volatile prevents the compiler from keeping the
    > value in a register.


    [snip]

    Actually, the meaning of volatile is compiler-specific, but in general
    it means that the compiler should not do any fancy optimizations to the
    data at hand. That could mean not caching a variable in a register even
    though the code doesn't appear to change it. By using volatile, the
    programmer is indicating that the value could change due to something
    outside the program (e.g. another thread or process or a hardware
    device). See TC++PL A.7.1.

    Cheers! --M
     
    mlimber, Jan 12, 2006
    #12
  13. Guest

    > Ok, this was a bad example. Change the line to j = 1; to show the
    > problem with f(i).


    Thank you! I have eventually understood why the optimization did
    not happen.
    The for-loop contains code like

    for(int i=0;i<length;i++) {
    data= ...some floating point math...
    }

    As in your example, it is possible (at least from the compiler's point
    of view) that the assignment to "data" overwrites "length". One
    would need a very potent data flow analysis to prove the opposite.
    /*
    Please insert here some C/C++ bashing.
    Topic: Why does C/C++ constantly forces me to do things that
    are done by the compiler in other language?
    */

    Ramin
     
    , Jan 13, 2006
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. BCC

    c++ memory optimization

    BCC, Nov 4, 2003, in forum: C++
    Replies:
    11
    Views:
    3,113
    Jerry Coffin
    Nov 6, 2003
  2. Evangelista Sami

    memory optimization

    Evangelista Sami, Jun 14, 2004, in forum: C Programming
    Replies:
    4
    Views:
    353
    Eric Sosman
    Jun 15, 2004
  3. Ravikiran

    Zero Optimization and Sign Optimization???

    Ravikiran, Nov 17, 2008, in forum: C Programming
    Replies:
    22
    Views:
    894
    Thad Smith
    Nov 24, 2008
  4. Good Guy
    Replies:
    4
    Views:
    317
    Good Guy
    Oct 19, 2010
  5. Andrew
    Replies:
    13
    Views:
    268
    Ilya Zakharevich
    Mar 20, 2006
Loading...

Share This Page