mircea
10-29-2002, 12:09 PM
VC++ service pack 6 gives meaningless answers in 'machar' routine from NR in C book (Method 20.1).
After a bit of investigation turns out that machine code generated for the sequence:
do {
a += a;
temp = a + one;
....
is something like:
; a += a
FLD [a]
FADD [a]
FST [a] ;note that 'a' value remains on FP stack
; temp = a + one
FADD [one]
FSTP [test]
This plays havoc with all assumptions in the code because 'one' is added to the FP's internal representation of 'a' which is normally higer precision than the memory representation of 'a'.
No amount of 'polite' coercing would make the compiler give up on caching the 'a' value: not only that disabling all optimizations doesn't help but even declaring all varaibles as volatile doesn't make a difference. This is in clear violation of C/C++ standards that require any volatile variable to be reloaded at the begining of each instruction.
The only solution that worked was to interspread the code with garbage like:
do {
a += a;
noop ();
temp = a + one;
noop ();
....
where noop is (obviously) defined as:
void noop () {};
This seems to force the compiler to reload the values before any instruction. It still remains to be seen if this works with different levels of optimizations (initial tests suggest so).
On an unrelated topic I'm a new member of this forum and I was mildly shocked to find out from postings in this forum that a book I keep in such high esteem can have bugs. I've always looked at NR as "The Bible" of numerical algortihms and bibles don't have bugs:). Even my post above shows this belief: when faced with an incorect answer I started to look for a bug in the compiler and, sure thing, I found it. Anyway it's a too long rant just to say you guys have come up with a wonderful book.
Thanks for many hours of delightful reading and clever algorithms.
Mircea Neacsu:)
After a bit of investigation turns out that machine code generated for the sequence:
do {
a += a;
temp = a + one;
....
is something like:
; a += a
FLD [a]
FADD [a]
FST [a] ;note that 'a' value remains on FP stack
; temp = a + one
FADD [one]
FSTP [test]
This plays havoc with all assumptions in the code because 'one' is added to the FP's internal representation of 'a' which is normally higer precision than the memory representation of 'a'.
No amount of 'polite' coercing would make the compiler give up on caching the 'a' value: not only that disabling all optimizations doesn't help but even declaring all varaibles as volatile doesn't make a difference. This is in clear violation of C/C++ standards that require any volatile variable to be reloaded at the begining of each instruction.
The only solution that worked was to interspread the code with garbage like:
do {
a += a;
noop ();
temp = a + one;
noop ();
....
where noop is (obviously) defined as:
void noop () {};
This seems to force the compiler to reload the values before any instruction. It still remains to be seen if this works with different levels of optimizations (initial tests suggest so).
On an unrelated topic I'm a new member of this forum and I was mildly shocked to find out from postings in this forum that a book I keep in such high esteem can have bugs. I've always looked at NR as "The Bible" of numerical algortihms and bibles don't have bugs:). Even my post above shows this belief: when faced with an incorect answer I started to look for a bug in the compiler and, sure thing, I found it. Anyway it's a too long rant just to say you guys have come up with a wonderful book.
Thanks for many hours of delightful reading and clever algorithms.
Mircea Neacsu:)