Как я могу улучшить производительность этой реализации minmax?
Вот мой текущий код. Это наивная реализация.
import System.Environment (getArgs)
minmax [] = Nothing
minmax [x] = Just (x, x)
minmax (a:b:xs) = Just $ minmax' xs $ sort a b
where minmax' [] lohi = lohi
minmax' [x] lohi@(lo, hi)
| x < lo = (x, hi)
| x > hi = (lo, x)
| otherwise = lohi
minmax' (x:y:xs) (lo, hi) = minmax' xs $ newlo `seq` newhi `seq` (newlo, newhi)
where (lo', hi') = sort x y
newlo = if lo' < lo then lo' else lo
newhi = if hi' > hi then hi' else hi
sort x y = if x < y then (x, y) else (y, x)
main = do
args <- getArgs
let [from, till] = map read args :: [Int]
print $ minmax [from..till]
Я хочу увидеть, как далеко я могу пойти с haskell по сравнению с C++ rust
и, возможно, используя три подхода на всех языках. Наивный, наивный параллель и использование матриц (repa
для Хаскелла и eigen
для C++)
Из этого отчета профилировщика я вижу, что Haskell выделяет много памяти.
minmax +RTS -p -RTS 1 10000000
total time = 0.13 secs (132 ticks @ 1000 us, 1 processor)
total alloc = 800,062,584 bytes (excludes profiling overheads)
Я собрал с ghc -O2 -fllvm
(GHC 8.2.1). С моей точки зрения, наивная реализация не должна выделять много памяти, потому что она должна просто повторять список парами. Как этого добиться, могу ли я сделать что-нибудь еще для улучшения производительности?
Я хотел попробовать stream-fusion
пакет, но он не поддерживает base 4.10
, Есть ли обходной путь для этого? Не могу найти ничего об этой проблеме.
1 ответ
Нахождение минимума и максимума может быть сделано в линейном времени и постоянном пространстве следующим образом:
sort :: (Int, Int) -> Int -> (Int, Int)
sort (min, max) val
| val < min = (val, max)
| val > max = (min, val)
| otherwise = (min, max)
minmax :: [Int] -> Maybe (Int, Int)
minmax [] = Nothing
minmax (x:xs) = Just $ foldl sort (x, x) xs
Анализатор строгости Haskell должен выяснить, что этот код должен быть строгим, и оптимизировать его.