#2271: floor, ceiling, round :: Double -> Int are awesomely slow
------------------------------------------+---------------------------------
Reporter: dons | Owner: [EMAIL PROTECTED]
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 6.8.2
Severity: normal | Resolution:
Keywords: performance, math, double | Testcase:
Architecture: Unknown | Os: Unknown
------------------------------------------+---------------------------------
Comment (by dons):
An old complaint:
http://article.gmane.org/gmane.comp.lang.haskell.cafe/21757/
Was due to this issue.
The original poster was complaining about:
quant8 :: Double -> Word8
quant8 x = floor $ x * 0xFF
being too slow.
Of course, it turns into a properFraction call,
{{{
quant8_rha :: Double -> Word8
quant8_rha =
\ (x_ahf :: Double) ->
case properFraction5
@ Word8
$f32
(case x_ahf of wild_aVL { D# x1_aVN ->
D# (*## x1_aVN 255.0)
})
of wild_aUN { (n_aUP, r_aUQ) ->
case r_aUQ of wild1_aVn { D# x1_aVp ->
case <## x1_aVp 0.0 of wild11_aUS {
False -> n_aUP;
True ->
case n_aUP of wild2_aVx { W8# x#_aVz ->
W8# (narrow8Word# (minusWord# x#_aVz __word 1))
}
}
}}}
Rather than an expected unboxed double floor(). The properFraction call
there is going to kill things. We'd need a C floor call to get something
like:
{{{
$wccall_r182 :: Double#
-> State# RealWorld
-> (# State# RealWorld, Double# #)
$wccall_r182 =
{__ccall floor Double#
-> State# RealWorld
-> (# State# RealWorld, Double# #)}_dRy
quant8_rha :: Double -> Word8
quant8_rha =
\ (x_ahf :: Double) ->
case x_ahf of wild_aUI { D# x1_aUK ->
case $wccall_r182 (*## x1_aUK 255.0) realWorld#
of wild1_XB { (# ds_dRx, ds1_dRw #) ->
W8#
(narrow8Word# (int2Word# (double2Int# ds1_dRw)))
}
}}}
With the result we can turn this program:
{{{
import Data.Word
import Data.Array.Vector
main = print . sumU
. mapU (quant8 :: Double -> Word8)
$ enumFromToFracU 0 100000000
}}}
From running in 1 minute, 14 seconds, to one that runs in 4.1 seconds.
But note, with the pure Haskell quant, we get a fold of this form:
{{{
$wfold :: Word# -> Double# -> Word#
}}}
While with the FFI, we get:
{{{
$wfold :: Word# -> Double# -> Word8
}}}
Is this related to Neil's issue with FFI and unboxing results?
So, anyway, more support that the Double floor/ceiling functions need to
be turned into ccalls if we're going to use them for anything with
meaningful performance.
The full program
{{{
{-# LANGUAGE ForeignFunctionInterface #-}
import Data.Word
import Data.Array.Vector
main = print . sumU
. mapU (quant8 :: Double -> Word8)
$ enumFromToFracU 0 100000000
quant8 :: Double -> Word8
quant8 x = floor' $ x * 0xFF
floor' :: Double -> Word8
floor' x = (fromIntegral . (truncate :: Double -> Int)) $ c_floor x
foreign import ccall unsafe "math.h floor"
c_floor :: Double -> Double
}}}
--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/2271#comment:1>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
_______________________________________________
Glasgow-haskell-bugs mailing list
Glasgow-haskell-bugs@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs