solrize
trong #haskell đã hỏi một câu hỏi về một phiên bản của mã này và tôi đã thử một số trường hợp khác và đã tự hỏi điều gì đang diễn ra. Trên máy của tôi, mã "nhanh" mất ~ 1 giây và mã "chậm" mất ~ 1.3-1.5 (mọi thứ được biên dịch với ghc -O2
).Tại sao `logBase 10 x` chậm hơn` log x/log 10`, ngay cả khi chuyên biệt?
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 hy vọng rằng GHC sẽ có thể biến logBase x y
vào chính xác những điều tương tự như log y/log x
, khi chuyên. Điều gì đang xảy ra ở đây và cách nào được khuyến nghị sử dụng logBase
?
Ghc có thể thực hiện tuyên truyền liên tục 'log 10' trong một số trường hợp. Hãy thử đo với một cơ sở biến. –
n.b. Ví dụ 'Floating' cho' Double' định nghĩa 'logBase' tương đương với định nghĩa nhận xét của' fooLogBase' ở trên. – dave4420
Chúng đều đều nhanh chóng khi bạn biên dịch với chương trình phụ trợ LLVM. – leftaroundabout