Re: [ZEND-ENGINE-CVS] cvs: ZendEngine2(PHP_5_3) / Zend.m4 acinclude.m4 zend_float.h zend_operators.c zend_strtod.c /tests float_prec_001.phpt

[email protected] (Dmitry Stogov) Tue, 17 Mar 2009 14:26:45 +0300
Newsgroups php.zend-engine.cvs
Message-ID <[email protected]>

Christian Seiler wrote:
> Hi Dmitry,
> 
> (cc'ing Johannes & Lukas)
> 
>> It looks like I missed this patch.
>> What is the reason for it?
> 
> It was in context of PHP's round() behaviour, I also discovered
> discrepancies of general FP behaviour between platforms.
> 
> Basically, on x86 systems without SSE FP arithmetics don't really use
> IEEE 754 double arithmetic by default but rather a double-extended type
> for internal calculations - which leads to problems since FP behaviour
> is not reproducible on different platforms - compare to for example x86
> with SSE or x86_64 where SSE is nearly always used, or PPC etc. - there
> you get real IEEE 754 double arithmetic. The makes sure PHP changes the
> internal FPU precision of x86 to IEEE 754 double precision in order to
> get the same results for FP calculations on all platforms.
> 
> See:
> http://wiki.php.net/rfc/rounding
> http://www.christian-seiler.de/projekte/fpmath/
> 
>> It makes ~5% slowdown on Zend/bench.php Linux 32-bit.  :( 
> 
> Huh.. Strange. When I presented the patch (nobody except Lukas, Johannes
> & Scott were interested anyway at that time).

Yeah, I didn't look into it careful as I supposed it changes the round() 
  behaviour but not the whole double arithmetic.

> I knew there would be a
> small performance penalty for the engine, but 5%? That is much higher
> than I expected - which was definitely less than 1% (although I didn't
> measure anything). What does zend/bench.php do? An unusual high amount
> of FP arithmetics?

It runs several simple benchmarks and only two of them works with FP. So 
FP arithmetic became even slower.

> Currently, the patch saves the current FPU state, changes it to IEEE 754
> double arithemtic, does the calculation and then restores the previous
> state. This I did in order not to clash with other libraries that may be
> loaded.

I see, but this state manipulation adds 7 assembler instructions for 
each floating point operation.

> What we could do, however, would be to simply store the state in PHP on
> a pre-request basis (i.e. use RINIT / RSHUTDOWN to store/change/restore
> the state) and hope that no other library changes the state again (or,
> if it does, wrap the invocation of that library). That would remove the
> fnstcw/fldcw assembly instructions from around every FP operation -
> which is probably the reason for the slowdown.
> 
> If you want to, I'll write a patch for that for PHP_5_3 and HEAD this
> evening that may be discussed.

I'm not sure if we should alter "default" "double" arithmetic semantics 
as you proposed in last section of RFC.

RINIT/RSHUTDOWN looks better from performance point of view, but in this 
case we can affect external libraries or become affected by them.

Thanks. Dmitry.