Missing conversion rules for realToFrac causing slowdowns in Int->Double conversions
GHC.Real and GHC.Float currently have:
-- | general coercion from integral types
fromIntegral :: (Integral a, Num b) => a -> b
fromIntegral = fromInteger . toInteger
{-# RULES
"fromIntegral/Int->Int" fromIntegral = id :: Int -> Int
#-}
-- | general coercion to fractional types
realToFrac :: (Real a, Fractional b) => a -> b
realToFrac = fromRational . toRational
{-# RULES
"realToFrac/Int->Int" realToFrac = id :: Int -> Int
#-}
But these avoid some primops that can make these conversions more efficient.
{-# RULES
"realToFrac/Int->Double" realToFrac = i2d :: Int -> Double
#-}
int2Double :: Int -> Double
int2Double (I# x) = D# (int2Double# x)
A rule to use the in2Double# primop over realToFrac directly, improves the running time of this program:
import Data.Array.Parallel.Unlifted
main = do
let c = replicateU n (2::Double)
a = mapU realToFrac (enumFromToU 0 (n-1) ) :: UArr Double
print (sumU (zipWithU (*) c a))
From 113 seconds, to 0.194s! A massive speedup.
We should fill out the rules here with at least those for which GHC has primitives:
{-# RULES
"realToFrac/Int->Double" realToFrac = int2Double :: Int -> Double
"realToFrac/Int->Float" realToFrac = int2Float :: Int -> Float
#-}
to the realToFrac and fromIntegral rules in GHC.Float
Trac metadata
Trac field | Value |
---|---|
Version | 6.8.2 |
Type | Bug |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Runtime System |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | dons@galois.com |
Operating system | Unknown |
Architecture | Unknown |