在#haskell問了一個關於這個代碼的一個版本的問題,我試了一些其他的例子,並想知道發生了什麼。在我的機器上,「快速」代碼需要大約1秒,而「慢」代碼需要大約1.3-1.5(所有內容均編譯爲ghc -O2
)。爲什麼`logBase 10 x`比'log x/log 10`慢,哪怕是專門的?
import Data.List
log10 :: Double -> Double
--log10 x = log x/log 10 -- fast
--log10 = logBase 10 -- slow
--log10 = barLogBase 10 -- fast
--log10 = bazLogBase 10 -- fast
log10 = fooLogBase 10 -- see below
class Foo a where
fooLogBase :: a -> a -> a
instance Foo Double where
--fooLogBase x y = log y/log x -- slow
fooLogBase x = let lx = log x in \y -> log y/lx -- fast
barLogBase :: Double -> Double -> Double
barLogBase x y = log y/log x
bazLogBase :: Double -> Double -> Double
bazLogBase x = let lx = log x in \y -> log y/lx
main :: IO()
main = print . foldl' (+) 0 . map log10 $ [1..1e7]
I'd've希望GHC將能夠專門何時打開logBase x y
成一模一樣的東西log y/log x
。這裏發生了什麼,以及使用logBase
的推薦方式是什麼?
ghc在某些情況下可能會不斷傳播'log 10'。嘗試使用可變基數進行測量。 –
n.b. Double的'Floating'實例定義了'logBase'等同於上面'fooLogBase'的註釋掉的定義。 – dave4420
當您使用LLVM後端進行編譯時,它們同樣快速。 – leftaroundabout