solrize
#haskellでこのコードの1つのバージョンについて質問があり、他のいくつかのケースを試してみて、何が起こっているのか不思議に思っていました。私のマシンでは、「高速」コードは約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は特殊なlog y/log x
、とまったく同じものにlogBase x y
を回すことができるであろうことを期待。ここで何が起こっているのですか?logBase
を使用する際の推奨方法は何ですか?
ghcは、場合によっては「log 10」の一定の伝播を行っている可能性があります。可変ベースで測定してみてください。 –
n.b. 'Double'の' Floating'インスタンスは、上の 'fooLogBase'のコメントアウトされた定義と同じように' logBase'を定義します。 – dave4420
LLVMバックエンドを使用してコンパイルすると、すべて同じ速さになります。 – leftaroundabout