[Haskell-cafe] ANN: ieee version 0.7
Daniel Fischer
daniel.is.fischer at web.de
Tue Sep 21 15:08:11 EDT 2010
On Tuesday 21 September 2010 19:46:02, John Millikin wrote:
> On Tue, Sep 21, 2010 at 07:10, Daniel Fischer <daniel.is.fischer at web.de>
wrote:
> > And I'd expect it to be a heck of a lot faster than the previous
> > implementation. Have you done any benchmarks?
>
> Only very rough ones -- a few basic Criterion checks, but nothing
> extensive.
Certainly good enough for an indication.
> Numbers for put/get of 64-bit big-endian:
>
> getWord getFloat putWord putFloat
> Bitfields (0.4.1) 59 ns 8385 ns 1840 ns 11448 ns
> poke/peek (0.4.2) 59 ns 305 ns 1840 ns 744 ns
Yaw. That's a huge difference. I don't think there's much room for doubt
that it's much faster (the exact ratios will vary of course).
> unsafeCoerce 59 ns 61 ns 1840 ns 642 ns
Odd that unsafeCoerce gains 244 ns for get, but only 102 for put.
>
> Note: I don't know why the cast-based versions can put a Double faster
> than a Word64;
Strange. putFloat does a putWord and a transformation, how can that be
faster than only the putWord?
> Float is (as expected) slower than Word32. Some
> special-case GHC optimization?
>
> > One problem I see with both, unsafeCoerce and poke/peek is endianness.
> > Will the bit-pattern of a double be interpreted as the same uint64_t
> > on little-endian and on big-endian machines? In other words, is the
> > byte order for doubles endianness-dependent too?
> > If yes, that's fine, if no, it would break between machines of
> > different endianness.
>
> Endianness only matters when marshaling bytes into a single value --
> Data.Binary.Get/Put handles that. Once the data is encoded as a Word,
> endianness is no longer relevant.
I mean, take e.g. 2^62 :: Word64. If you poke that to memory, on a big-
endian machine, you'd get the byte sequence
40 00 00 00 00 00 00 00
while on a little-endian, you'd get
00 00 00 00 00 00 00 40
, right?
If both bit-patterns are interpreted the same as doubles, sign-bit = 0,
exponent-bits = 0x400 = 1024, mantissa = 0 , thus yielding
1.0*2^(1024 - 1023) = 2.0, fine. But if on a little-endian machine, the
floating point handling is not little-endian and the number is interpreted
as sign-bit = 0, exponent-bits = 0, mantissa = 0x40, hence
(1 + 2^(-46))*2^(-1023), havoc.
I simply didn't know whether that could happen. According to
http://en.wikipedia.org/wiki/Endianness#Floating-point_and_endianness it
could.
On the other hand, "no standard for transferring floating point values has
been made. This means that floating point data written on one machine may
not be readable on another", so if it breaks on weird machines, it's at
least a general problem (and not Haskell's).
More information about the Haskell-Cafe
mailing list