Vince Weaver
2007-03-22 21:46:49 UTC
Hello,
I know in general I shouldn't expect floating point to be _exact_, but
I've found a problem where valgrind is just slightly off and it majorly
effects results.
I've made a valgrind plugin that calculates Basic Block Vectors for use
with the Simpoint analysis tool. It gets an instruction count using
methods simiar to cachegrind and I've validated it with performance
counters on a P3 system (one special case has to be added; with the
"rep" prefix and string instructions an actual machine counts up to 4096
reps as one instruction retired, not as 4096 separate ones)
In any case I've run this on the spec2k benchmarks, and all of them are
close except for art. The art benchmark finishes in half the number of
instructions than it should.
It turns out that art is using the "==" operator to compare two floating
point numbers. And valgrind returns values that have the LSB wrong
on 64-bit fmul and fadd instructions. This is enough to make the program
finish early.
Looking through the valgrind code, I am guessing maybe this is a problem
with the rounding mode, but I haven't been able to track down a good fix.
I've attached code after this that shows the problem.
On a native system I get
xr=0.426335 qr=0.505253
3fdb4914520a783a
3fe02b07a0efb19b
v=5.478862 4015ea5ace4c4585
Under valgrind with --tool=none I get
xr=0.426335 qr=0.505253
3fdb4914520a783a
3fe02b07a0efb19b
v=5.478862 4015ea5ace4c4586
Notice that only the very last bit of the result is off, which is why I
think it might be rounding related.
Any help with this problem would be appreciated... I am using
valgrind 3.2.3
Thanks,
Vince
#include <stdio.h>
void print_hex(double value) {
long long *blah;
blah=(long long *)&value;
printf("%llx\n",*(blah));
}
int main(int argc, char **argv) {
unsigned long long xr_l=0x3fdb4914520a783aULL;
unsigned long long qr_l=0x3fe02b07a0efb19bULL;
double xr,qr,v;
long long *int_ptr;
unsigned short cw;
int_ptr=(unsigned long long *)&xr;
*int_ptr=xr_l;
int_ptr=(unsigned long long *)&qr;
*int_ptr=qr_l;
printf("xr=%lg qr=%lg\n",xr,qr);
print_hex(xr); print_hex(qr);
// asm ("fstcw %0":"=m"(cw)::"memory");
// printf("cw=%x, rounding=%d\n",cw,(cw>>9)&3);
v=xr+10.0*qr;
printf(" v=%lf ",v);
print_hex(v);
return 0;
}
I know in general I shouldn't expect floating point to be _exact_, but
I've found a problem where valgrind is just slightly off and it majorly
effects results.
I've made a valgrind plugin that calculates Basic Block Vectors for use
with the Simpoint analysis tool. It gets an instruction count using
methods simiar to cachegrind and I've validated it with performance
counters on a P3 system (one special case has to be added; with the
"rep" prefix and string instructions an actual machine counts up to 4096
reps as one instruction retired, not as 4096 separate ones)
In any case I've run this on the spec2k benchmarks, and all of them are
close except for art. The art benchmark finishes in half the number of
instructions than it should.
It turns out that art is using the "==" operator to compare two floating
point numbers. And valgrind returns values that have the LSB wrong
on 64-bit fmul and fadd instructions. This is enough to make the program
finish early.
Looking through the valgrind code, I am guessing maybe this is a problem
with the rounding mode, but I haven't been able to track down a good fix.
I've attached code after this that shows the problem.
On a native system I get
xr=0.426335 qr=0.505253
3fdb4914520a783a
3fe02b07a0efb19b
v=5.478862 4015ea5ace4c4585
Under valgrind with --tool=none I get
xr=0.426335 qr=0.505253
3fdb4914520a783a
3fe02b07a0efb19b
v=5.478862 4015ea5ace4c4586
Notice that only the very last bit of the result is off, which is why I
think it might be rounding related.
Any help with this problem would be appreciated... I am using
valgrind 3.2.3
Thanks,
Vince
#include <stdio.h>
void print_hex(double value) {
long long *blah;
blah=(long long *)&value;
printf("%llx\n",*(blah));
}
int main(int argc, char **argv) {
unsigned long long xr_l=0x3fdb4914520a783aULL;
unsigned long long qr_l=0x3fe02b07a0efb19bULL;
double xr,qr,v;
long long *int_ptr;
unsigned short cw;
int_ptr=(unsigned long long *)&xr;
*int_ptr=xr_l;
int_ptr=(unsigned long long *)&qr;
*int_ptr=qr_l;
printf("xr=%lg qr=%lg\n",xr,qr);
print_hex(xr); print_hex(qr);
// asm ("fstcw %0":"=m"(cw)::"memory");
// printf("cw=%x, rounding=%d\n",cw,(cw>>9)&3);
v=xr+10.0*qr;
printf(" v=%lf ",v);
print_hex(v);
return 0;
}