Bifferboard FPU tests

18 views
Skip to first unread message

Rilhas

unread,
Jun 16, 2012, 9:02:57 PM6/16/12
to Bifferboard
I did some tests with the Bifferboard's FPU, especially with 3
trigonometric functions (sin, cos, and tan) and one basic math
function (fmod), and compared the results with those of my Ubuntu VM.
I placed the graphs in:

http://www.rilhas.com/Bifferboard/Math/index.html

I added some workarounds at the end of the page that may be helpful to
those that need to avoid such troubles. Also available are the
executables used for testing and the corresponding C source code.

Andrew Scheller

unread,
Jun 17, 2012, 7:54:49 AM6/17/12
to biffe...@googlegroups.com
> I did some tests with the Bifferboard's FPU, especially with 3
> trigonometric functions (sin, cos, and tan) and one basic math
> function (fmod), and compared the results with those of my Ubuntu VM.
> I placed the graphs in:
>
> http://www.rilhas.com/Bifferboard/Math/index.html

Definitely something weird going on! I tried replicating this on
Slackware 13.0 (from the bifferboard wiki) using native (on the
BifferBoard) compilation, and it also produces incorrect results
outside the range -PI/2 -> +PI/2
Interestingly, even though the fmod results are incorrect outside the
-360 -> +360 range, the "incorrect" fmod results from a
native-compiled program always come out at integer values. And yet if
I try either of your Ubuntu-compiled programs on my Slackware
bifferboard, the incorrect fmod results come out as floating point
values. I've uploaded my BifferBoard-Slackware-compiled programs to
http://www.loowis.durge.org/mathtest_slack and
http://www.loowis.durge.org/mathtest_slack_debug if you want to
experiment further.

IMHO your test program will be much more useful to "Linux types" if
you make the following tweaks:

--- main.c 2012-05-01 02:53:37.000000000 +0100
+++ mathtest.c 2012-05-01 03:12:22.000000000 +0100
@@ -8,19 +8,19 @@
const double PI=3.14159265;
// open the file
#ifdef _DEBUG
- file=fopen("test_data_debug.xls", "wt");
+ file=fopen("test_data_debug.csv", "wt");
#else
- file=fopen("test_data_release.xls", "wt");
+ file=fopen("test_data_release.csv", "wt");
#endif
// write the header
- fprintf(file,
"AngDeg\tAngRad\tSin(AngRad)\tCos(AngRad)\tTan(AngRad)\tFMod(AngDeg,360.0)\n");
- // test all angles from -270 to +720
+ fprintf(file,
"AngDeg,AngRad,Sin(AngRad),Cos(AngRad),Tan(AngRad),FMod(AngDeg,360.0)\n");
+ // test all angles from -720 to +720
for(ang_deg=-720.0; ang_deg<=720.0; ang_deg+=1.0) {
// convert degrees to radians
ang_rad=ang_deg*PI/180.0;
// write to the file
fprintf(file,
- "%.15g\t%.15g\t%.15g\t%.15g\t%.15g\t%.15g\n",
+ "%.15g,%.15g,%.15g,%.15g,%.15g,%.15g\n",
ang_deg,
ang_rad,
sin(ang_rad),


I also made a super-minimal test program:
#include <stdio.h>
#include <math.h>

int main() {
// This should print 90
printf("%.15g\n",fmod(450.0, 360.0));
return 0;
}

available at http://www.loowis.durge.org/mathtest_slack which prints
out 152 instead of the expected 90.

Lurch

Andrew Scheller

unread,
Jun 17, 2012, 9:25:06 AM6/17/12
to biffe...@googlegroups.com
I found http://stackoverflow.com/questions/1018638/using-software-floating-point-on-x86-linux
which looks like it contains some interesting links (including
alternative soft-float implementations), but I'm afraid it's all a bit
over my head.
I tried the "libgcc" steps recommended (again using slackware on the
BB), but it failed with lots of "can't emulate 'TF'" errors.

Lurch

Rilhas

unread,
Jun 17, 2012, 9:39:31 AM6/17/12
to Bifferboard
> Interestingly, even though the fmod results are incorrect outside the
> -360 -> +360 range, the "incorrect" fmod results from a
> native-compiled program always come out at integer values.

When I first realized something was wrong in the Bifferboard's STL
generator I tried replicating the problem in many ways (because they
could be comming from many different places in the whole application)
and I had a hard time narrowing it down because the results seemed to
change as I tweeked the code to observe specific details. So I started
getting the impression that the problem changed everytime I compiled a
new executable, and even many of the 3D shapes produced by the STL
generator looked different in the STL viewer as I changed the code to
try and make the problem source manifest itself.

So I'm not sure but, although on a given executable the weirdness
seems to have some pattern and even be symetrical, it might depend on
memory configuration at the time of the calls, which could depend on
slight compilation changes produced while debugging. If true then it
would also explain you getting different results on different
environments. Also, I was trying to debug the problem on the
Bifferboard using release executables, which seem to lead to more even
variable results comparing to debug builds.

Anyway, to me it makes sense that the problem is all in the fmod and
that other functions are just suffering from it. If, for example, the
FPU emulator works by computing Taylor series expansion of the
trigonometric functions, then it makes sense that they needs to fix
the angles to some range and use fmod for that. For example,
internally it could work like
sin(a)=internal_taylor_series_expansion_of_sin(fmod(a, PI)) or
something like that. So, if fmod doesn't work correctly outside the
central range -modulus -> +modulus then all functions that depend on
it will also not work correctly outside their central range.

... actually when I noticed that sin, cos, and tan would only work
inside the -PI/2->+PI/2 range I fixed the angles by using - you
guessed it - fmod, and since that didn't solve the problem that meant
there had to be a problem with fmod, and I confirmed that by including
fmod in a subsequent test.


> IMHO your test program will be much more useful to "Linux types" if
> you make the following tweaks:

I followed your suggestions and if you don't define symbol XLS you get
a CSV file. I also changed the name of the file to "test_fpu.c", it is
a more convenient name for me than "mathtest.c", and it is definitly
better than the Code::Blocks-baptized "main.c".

Rilhas

unread,
Jun 17, 2012, 10:14:17 AM6/17/12
to Bifferboard


On Jun 17, 2:25 pm, Andrew Scheller <ya...@loowis.durge.org> wrote:
> I foundhttp://stackoverflow.com/questions/1018638/using-software-floating-po...
> which looks like it contains some interesting links (including
> alternative soft-float implementations), but I'm afraid it's all a bit
> over my head.
> I tried the "libgcc" steps recommended (again using slackware on the
> BB), but it failed with lots of "can't emulate 'TF'" errors.
>

My preferred solution would be one where the code runs optimally when
an FPU is available. To me the biggest advantage of the Bifferboard is
to be able to run code that also runs on a PC, without me having to
build a specific binary for it.

In that sense I prefer to avoid specific software solutions (because
they will be slower on a desktop), unless I could determine at run
time if a hardware FPU is available (in which case I would call native
functions) or if one is not available (in which case I would prefer
solutions like the one you point out, which will always have the
benefit of less overhead by avoiding kernel traps). Since I don't know
how to determine the availability of an FPU in Linux I'll leave that
solution to the distant future (since the STL generator can do a 20K
triangle helical spring in about 1 minute I don't feel the need to
rush it just yet).

Of course this could be solved easily, adding a #define to build for
the Bifferboard with software emulation, or native functions when not
for the Bifferboard, but the workarounds I mention of the webpage seem
to be the best solution so far. On a PC (my main target for the
application) it has a negligeable effect (a complex object with 1M
triangles takes 7 seconds without the workarounds and 7.2 with
workarounds), and on the Bifferboard there isn't a big advantage in
going to great lengths to provide an STL public service which is slow
instead of very slow (hence the usage of the expression "public
service" :-) ).

Anyway, if in the future I endup needing fast math in the Bifferboard
it makes sense to use a specific math software library rather than the
kernel's emulation (to avoid the overhead, as mentioned).

Andrew Scheller

unread,
Jun 17, 2012, 10:42:27 AM6/17/12
to biffe...@googlegroups.com
>> which looks like it contains some interesting links (including
>> alternative soft-float implementations), but I'm afraid it's all a bit
>> over my head.
> My preferred solution would be one where the code runs optimally when
> an FPU is available. To me the biggest advantage of the Bifferboard is
> to be able to run code that also runs on a PC, without me having to
> build a specific binary for it.

Yup. To me it "feels" like there's a small bug somewhere (kernel?
libm? compiler/linker settings? something else?) on the Bifferboard
software, and that if that bug could be fixed, everything would just
get back to working properly, no matter what the function inputs.
I tried running:
python -c 'import math;print math.fmod(450, 360)'
on the BB-slackware and it also prints out an incorrect 152.05468
value (I think you might be right about the randomness of the
incorrect values), which definitely suggests a "system level" problem.

> In that sense I prefer to avoid specific software solutions (because
> they will be slower on a desktop), unless I could determine at run
> time if a hardware FPU is available (in which case I would call native

"cat /proc/cpuinfo" might be a good way of checking?

One of the other devices on my network is a NSLU2 (ARM CPU and also
FPU-less) and that compiles and produces correct results for your
fpu_test program and any Python math tests.
So part of the reason for suggesting the other softfloat
implementations was to maybe help track down exactly where the problem
is. But like I already said this is a bit over my head.

I guess if Biff's able to find any spare time to look at this, he's
the person most likely to be able to find a fix (or at least point in
the right direction!)...

Lurch
Reply all
Reply to author
Forward
0 new messages