Neon-ized Math.h Like Library


This is pretty surprising. I compiled my library on a X86 C2D 2.0Ghz XP machine and some of my *_c functions are significantly outperforming the inbuilt ones. Maybe there's some other platforms that this library will be useful for. Here's the results:

Code:
Function	Range		Number	Max Error	Rate
-------------------------------------------------------------------------
sinf       	[-3.14, 3.14]	500000	5.94e-006%	100.00%
sinf_c     	[-3.14, 3.14]	500000	8.35e-003%	193.75%
cosf       	[-3.14, 3.14]	500000	5.92e-006%	100.00%
cosf_c     	[-3.14, 3.14]	500000	1.59e-002%	93.75%
tanf       	[-0.79, 0.79]	500000	5.95e-006%	100.00%
tanf_c     	[-0.79, 0.79]	500000	7.75e-004%	151.61%
asinf      	[-1.00, 1.00]	500000	5.95e-006%	100.00%
asinf_c    	[-1.00, 1.00]	500000	1.06e-002%	131.91%
acosf      	[-1.00, 1.00]	500000	5.95e-006%	100.00%
acosf_c    	[-1.00, 1.00]	500000	5.98e-003%	136.96%
atanf      	[-1.00, 1.00]	500000	5.93e-006%	100.00%
atanf_c    	[-1.00, 1.00]	500000	2.12e-002%	193.75%
sinhf       	[-3.14, 3.14]	500000	0.00e+000%	100.00%
sinhf_c     	[-3.14, 3.14]	500000	3.49e-003%	200.00%
coshf       	[-3.14, 3.14]	500000	0.00e+000%	100.00%
coshf_c     	[-3.14, 3.14]	500000	1.19e-005%	200.00%
tanhf       	[-3.14, 3.14]	500000	0.00e+000%	100.00%
tanhf_c     	[-3.14, 3.14]	500000	3.62e-003%	290.63%
expf       	[0.00, 50.00]	500000	0.00e+000%	100.00%
expf_c     	[0.00, 50.00]	500000	2.38e-005%	196.88%
logf       	[1.00, 1000.00]	5000000	5.96e-006%	100.00%
logf_c     	[1.00, 1000.00]	5000000	5.00e-003%	182.98%
log10f       	[1.00, 1000.00]	5000000	5.95e-006%	100.00%
log10f_c     	[1.00, 1000.00]	5000000	6.56e-003%	202.15%
floorf     	[1.00, 1000.00]	5000000	0.00e+000%	100.00%
floorf_c   	[1.00, 1000.00]	5000000	0.00e+000%	178.48%
ceilf     	[1.00, 1000.00]	5000000	0.00e+000%	100.00%
ceilf_c   	[1.00, 1000.00]	5000000	0.00e+000%	179.49%
fabsf     	[1.00, 1000.00]	5000000	0.00e+000%	100.00%
fabsf_c   	[1.00, 1000.00]	5000000	0.00e+000%	48.39%
sqrtf      	[1.00, 1000.00]	500000	5.96e-006%	100.00%
sqrtf_c    	[1.00, 1000.00]	500000	1.04e-003%	100.00%
atan2f       	[0.10, 10.00]	10000	5.95e-006%	100.00%
atan2f_c     	[0.10, 10.00]	10000	2.23e-002%	83.87%
powf       	[1.00, 10.00]	10000	0.00e+000%	100.00%
powf_c     	[1.00, 10.00]	10000	9.92e-004%	327.42%
fmodf       	[1.00, 10.00]	10000	0.00e+000%	100.00%
fmodf_c     	[1.00, 10.00]	10000	0.00e+000%	34.04%
Once i figure out some NEON bugs, i'll get the full results on the actual pandora. In other news, i've also added 2, 3 & 4 element NEON matrix multiplication and matrix vector multiplication.
 
From what I can tell, it looks like your increased speed comes with decreased accuracy. That's fine for most applications, but some situations will need the added accuracy more than the faster execution.
 
Vorporeal said:
From what I can tell, it looks like your increased speed comes with decreased accuracy. That's fine for most applications, but some situations will need the added accuracy more than the faster execution.

Of course the lacking accuracy can be a problem. I assume that for 99% of the software we will see on the pandora that won't be a problem. It still beats anything I have seen with fixed point :)
 
Last edited by a moderator:
From what I can tell, it looks like your increased speed comes with decreased accuracy. That's fine for most applications, but some situations will need the added accuracy more than the faster execution.
Thats the idea of the library. If you want cmath like accuracy for many functions you need significant branches to subdivide the range, each of which cause a >20 cycle NEON & ARM stall. Also remember that this is simply relative peak error (as a percentage) over the range I've specified, in general it is a very bad characterization of error.

Some of the problems are:
  • For periodic functions the absolute error is a better measure, but if the function is asymptotic the relative error is better.
  • When the result approaches zero your relative error gets more and more meaningless. In the errors above i didn't count any errors caused by results below a certain arbitary threshold, below i'm showing you the raw maximums.
  • The errors are small enough that floating point errors come into play. For instance the errors specified for the cmath functions are just because of floating point inaccuracies, they should all be zero because the cmath functions are exactly what i'm measuring against.
  • I am using an inaccurate function as a base function, so there errors might constructively or deconstructively interfere.
I've changed my benchmark to show the root mean squared, max absolute and max relative error compared to the cmath functions:
Code:
Function	Range		Number	ABS Max Error	REL Max Error	RMS Error	Rate
------------------------------------------------------------------------------------
sinf       	[-3.14, 3.14]	500000	2.98e-008	5.94e-006%	1.45e-008	100.00%
sinf_c     	[-3.14, 3.14]	500000	7.29e-007	1.00e+002%	4.08e-007	213.33%
cosf       	[-3.14, 3.14]	500000	2.98e-008	5.92e-006%	1.46e-008	100.00%
cosf_c     	[-3.14, 3.14]	500000	7.65e-007	1.31e+000%	4.16e-007	193.75%
tanf       	[-0.79, 0.79]	500000	4.37e-008	5.95e-006%	1.21e-008	100.00%
tanf_c     	[-0.79, 0.79]	500000	2.79e-006	7.75e-004%	1.31e-006	100.00%
asinf      	[-1.00, 1.00]	500000	5.96e-008	5.95e-006%	1.77e-008	100.00%
asinf_c    	[-1.00, 1.00]	500000	5.53e-005	1.06e-002%	1.68e-005	193.75%
acosf      	[-1.00, 1.00]	500000	1.19e-007	5.95e-006%	4.47e-008	100.00%
acosf_c    	[-1.00, 1.00]	500000	5.54e-005	5.98e-003%	1.68e-005	134.04%
atanf      	[-1.00, 1.00]	500000	2.98e-008	5.93e-006%	1.26e-008	100.00%
atanf_c    	[-1.00, 1.00]	500000	1.67e-004	2.12e-002%	7.39e-005	100.00%
sinhf       	[-3.14, 3.14]	500000	0.00e+000	0.00e+000%	0.00e+000	100.00%
sinhf_c     	[-3.14, 3.14]	500000	9.54e-007	1.00e+002%	2.18e-007	197.87%
coshf       	[-3.14, 3.14]	500000	0.00e+000	0.00e+000%	0.00e+000	100.00%
coshf_c     	[-3.14, 3.14]	500000	9.54e-007	1.19e-005%	2.21e-007	293.75%
tanhf       	[-3.14, 3.14]	500000	0.00e+000	0.00e+000%	0.00e+000	100.00%
tanhf_c     	[-3.14, 3.14]	500000	1.19e-005	1.00e+002%	5.49e-006	351.61%
expf       	[0.00, 50.00]	500000	0.00e+000	0.00e+000%	0.00e+000	100.00%
expf_c     	[0.00, 50.00]	500000	1.13e+015	2.38e-005%	6.42e+013	520.00%
logf       	[1.00, 1000.00]	5000000	2.38e-007	5.96e-006%	1.35e-007	100.00%
logf_c     	[1.00, 1000.00]	5000000	1.14e-006	1.#Je+000%	4.05e-007	182.98%
log10f       	[1.00, 1000.00]	5000000	1.19e-007	5.95e-006%	6.60e-008	100.00%
log10f_c     	[1.00, 1000.00]	5000000	1.07e-006	1.#Je+000%	2.73e-007	239.74%
floorf     	[1.00, 1000.00]	5000000	0.00e+000	0.00e+000%	0.00e+000	100.00%
floorf_c   	[1.00, 1000.00]	5000000	0.00e+000	0.00e+000%	0.00e+000	177.22%
ceilf     	[1.00, 1000.00]	5000000	0.00e+000	0.00e+000%	0.00e+000	100.00%
ceilf_c   	[1.00, 1000.00]	5000000	0.00e+000	0.00e+000%	0.00e+000	150.54%
fabsf     	[1.00, 1000.00]	5000000	0.00e+000	0.00e+000%	0.00e+000	100.00%
fabsf_c   	[1.00, 1000.00]	5000000	0.00e+000	0.00e+000%	0.00e+000	100.00%
sqrtf      	[1.00, 1000.00]	500000	9.54e-007	5.96e-006%	4.91e-007	100.00%
sqrtf_c    	[1.00, 1000.00]	500000	2.29e-004	1.04e-003%	8.68e-005	100.00%
atan2f       	[0.10, 10.00]	10000	5.96e-008	5.95e-006%	0.00e+000	100.00%
atan2f_c     	[0.10, 10.00]	10000	1.72e-004	2.23e-002%	0.00e+000	82.98%
powf       	[1.00, 10.00]	10000	0.00e+000	0.00e+000%	0.00e+000	100.00%
powf_c     	[1.00, 10.00]	10000	2.66e+004	9.92e-004%	0.00e+000	322.22%
fmodf       	[1.00, 10.00]	10000	0.00e+000	0.00e+000%	0.00e+000	100.00%
fmodf_c     	[1.00, 10.00]	10000	9.97e+000	0.00e+000%	0.00e+000	31.91%
------------------------------------------------------------------------------------

Edit: This is it running on a C2D again, i'll do a proper benchmark when i get home.
 
lulzfish said:
For something like a video game, I wouldn't worry about anything less than gigantic, glaring errors, anyway.
while i'd agree that more often than not videogames give more weight to speed than precision, robust numerical algorithms can be as important to a video game as to any other form of scientific-derived computing. /pseudo-offended
 
Last edited by a moderator:
darkblu said:
lulzfish said:
For something like a video game, I wouldn't worry about anything less than gigantic, glaring errors, anyway.
while i'd agree that more often than not videogames give more weight to speed than precision, robust numerical algorithms can be as important to a video game as to any other form of scientific-derived computing. /pseudo-offended
If you were relying on cmath for a high accuracy, scientific application you would have to be pretty stupid. My algorithms are in general not significantly less precise than cmath. For instance the cmath implementations i've seen of sinf have a peak absolute error of ~3.0e-7, as you can see from the list above my function differs from this by at most ~7e-7 therefore the maximum error in my function relative to an actual sine curve is less than ~1.0e-6.

The functions which have troubles with accuracy in my library (ie tanf) have the same problems in cmath. A polynomial (with positive powers) will never accurately fit a function which approaches infinity... [/rant]
 
Last edited by a moderator:
get off the tree, adventus, i was not even referring to your library in that post you quoted (converesely, in my previous one i said i liked your lib and would likely use it).

ps on that wild conjecture of yours: no need to diss cmath and/or its users - nobody said it was perfect, but in case you've forgotten, it handles double (or even higher, where available) precision - of course it will be used for scientific computations when suitable. also, cmath doesn't start and end with trig and inverse hyperbolic trig functions, where it traditionally takes critique.

pps: if i were you, i'd be spending less time arquing here and more time improving the sqrtf precision ;p
 
Sorry, i didn't mean it to come out that way, i wasn't intending to argue. I was just saying that my functions exhibit the same fallacies as cmath, just a little bit more exaggerated. I have nothing against cmath, its a good, fast general computing library. The fact that it handles doubles is not really relevant, in most cmath functions its not the precision of the datatype that is holding it back, its the number of terms used in the polynomials or the number of range subdivisions. I wont be able to make sqrtf any more accurate without making it slower, maybe i'll just include a few versions of varying accuracy.

BTW by cmath i mean the standard "math.h" stuff, not the extensions for complex numbers etc.
 
Back
Top