He escrito el código para Project Euler's Challenge 14, en ambos Haskell y C++ (enlaces de ideone). Ambos recuerdan cualquier cálculo que hayan hecho previamente en una matriz.Optimización de GHC: Conjetura de Collatz
Usando ghc -O2
y g++ -O3
respectivamente, el C++ funciona 10-15 veces más rápido que la versión de Haskell.
Aunque entiendo que la versión de Haskell puede funcionar más despacio, y que Haskell es un lenguaje más agradable para escribir, sería bueno saber algunos cambios de código que puedo hacer en la versión de Haskell para hacerlo correr más rápido (idealmente dentro de factor de 2 o 3 de la versión de C++)?
código Haskell está aquí:
import Data.Array
import Data.Word
import Data.List
collatz_array =
let
upperbound = 1000000
a = array (1, upperbound) [(i :: Word64, f i :: Int) | i <- [1..upperbound]]
f i = i `seq`
let
check_f i = i `seq` if i <= upperbound then a ! i else f i
in
if (i == 1) then 0 else (check_f ((if (even i) then i else 3 * i + 1) `div` 2)) + 1
in a
main =
putStrLn $ show $
foldl1' (\(x1,x2) (y1,y2) -> if (x2 >= y2) then (x1, x2) else (y1, y2)) $! (assocs collatz_array)
Editar:
que he hecho ahora también una versión utilizando matrices mutables sin embalaje. Todavía es 5 veces más lento que la versión C++, pero una mejora significativa. El código está en ideone here.
Me gustaría saber las mejoras en la versión de matriz mutable que la acerque a la versión de C++.
Solo FYI, la compilación con '-fllvm' mejora el rendimiento en ~ 10% en mi máquina. –
Su 'seq' no hace ninguna diferencia; ambas funciones son estrictas en 'i'. GHC solía ser bastante malo en aritmética de 64 bits en plataformas de 32 bits, pero no sé qué plataforma estás usando. – augustss
No use 'div', use' quot'. – augustss