[GHC] #2269: Word type to Double or Float conversions are slower
than Int conversions
GHC
trac at galois.com
Wed May 7 19:17:37 EDT 2008
#2269: Word type to Double or Float conversions are slower than Int conversions
-------------------------------------------+--------------------------------
Reporter: dons | Owner: dons at galois.com
Type: feature request | Status: new
Priority: normal | Component: Compiler
Version: 6.8.2 | Severity: normal
Keywords: rules, performance, double | Testcase:
Architecture: Unknown | Os: Unknown
-------------------------------------------+--------------------------------
We have int2Double# and int2Float# primitives, but not equivalent ones for
Word
types. We may need word2Double# too, for Words* to be fully first-class
performance-wise.
This means we have to do extra tests in the Num instances for Word types
to implement 'fromIntegral':
{{{
toInteger (W# x#)
| i# >=# 0# = smallInteger i#
| otherwise = wordToInteger x#
where i# = word2Int# x#
}}}
Now, for some types, we work around this:
{{{
"fromIntegral/Int->Word" fromIntegral = \(I# x#) -> W# (int2Word# x#)
"fromIntegral/Word->Int" fromIntegral = \(W# x#) -> I# (word2Int# x#)
"fromIntegral/Word->Word" fromIntegral = id :: Word -> Word
}}}
and so on for other Word/Int types. And all is fine.
The problem comes up for Float and Double. For Int, we can write:
{{{
"fromIntegral/Int->Float" fromIntegral = int2Float
"fromIntegral/Int->Double" fromIntegral = int2Double
int2Float :: Int -> Float
int2Float (I# x) = F# (int2Float# x)
int2Double :: Int -> Double
int2Double (I# x) = D# (int2Double# x)
}}}
But we can't write these rules for Word types.
The result is a slow down on Word conversions, consider this
program:
{{{
main = print . sumU
. mapU (fromIntegral::Int->Double)
$ enumFromToU 0 100000000
}}}
When in lhs is Int, we get this nice code:
{{{
$wfold :: Double# -> Int# -> Double#
$wfold =
\ (ww_s18k :: Double#) (ww1_s18o :: Int#) ->
case ># ww1_s18o 100000000 of wild_a14T {
False ->
$wfold
(+## ww_s18k (int2Double# ww1_s18o)) (+# ww1_s18o 1);
True -> ww_s18k
}}}
But for Word types, we get:
{{{
$wfold :: Double# -> Word# -> Double#
$wfold =
\ (ww_s1gN :: Double#) (ww1_s1gR :: Word#) ->
case gtWord# ww1_s1gR __word 100000000 of wild_a1do {
False ->
case case >=# (word2Int# ww1_s1gR) 0 of wild1_a1cS {
False ->
case word2Integer# ww1_s1gR of wild11_a1d9 { (# s_a1db,
d_a1dc #) ->
case {__ccall __encodeDouble Int#
-> ByteArray#
-> Int#
-> State# RealWorld
-> (# State# RealWorld, Double# #)}_a1bT
s_a1db d_a1dc 0 realWorld#
of wild12_a1bX { (# ds1_a1bZ, ds2_a1c0 #) ->
ds2_a1c0
}
};
True -> int2Double# (word2Int# ww1_s1gR)
}
of wild1_a1bM { __DEFAULT ->
$wfold
(+## ww_s1gN wild1_a1bM) (plusWord# ww1_s1gR __word 1)
};
True -> ww_s1gN
}
}}}
Which is to be expected, and the running time goes from:
{{{
$ time ./henning
5.00000000067109e17
./henning 1.53s user 0.00s system 99% cpu 1.534 total
}}}
To:
{{{
$ time ./henning
5.00000000067109e17
./henning 4.57s user 0.00s system 99% cpu 4.571 total
}}}
So not too bad, but still, principle of least surprise says Word and Int
should behave the same.
Should we have a word2Double# primop?
--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/2269>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the Glasgow-haskell-bugs
mailing list