#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

Reply via email to