Memory access optimization

R

rodneys

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
 
T

Thomas Maier-Komor

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
 
M

mlimber

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
 
R

rodneys

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
 
D

David Harmon

On 11 Jan 2006 06:00:59 -0800 in comp.lang.c++, (e-mail address removed)
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.
 
D

Dave Townsend

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.
 
B

Bo Persson

Dave Townsend said:
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
 
R

rodneys

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
 
R

rodneys

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
 
B

Bo Persson

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
 
B

Bo Persson

Bo Persson said:
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).
 
M

mlimber

Bo said:
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
 
R

rodneys

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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top