Estoy tratando de usar concurrencia en Haskell para una optimización específica en la que solo se requiere uno de dos valores, y dependiendo de la situación, cualquiera de los dos puede ser mucho más rápido de crear que el otro.concurrencia Haskell - ¿es forkIO realmente no determinista?
Pensé que podría simplemente ejecutar 2 hilos con forkIO, y luego esperar hasta que se coloque un valor en un MVar. He aquí una sencilla prueba que he escrito para esto:
import Control.Concurrent
main = do out <- newEmptyMVar
t1 <- forkIO (makeString out)
t2 <- forkIO (makeInt out)
v <- takeMVar out
killThread t1
killThread t2
case v of
Left s -> putStrLn s
Right i -> putStrLn $ show i
makeString out = do s <- return (show (primes !! 10000))
putMVar out $ Left s
makeInt out = do i <- return 2
putMVar out $ Right i
primes = sieve [2..]
where sieve (x:xs) = x : (sieve $ filter ((/=0).(flip mod x)) xs)
Compilado con:
ghc --make -threaded Test
Sin embargo, sólo es cada vez alcanzó caso la Izquierda s, aunque para conseguir el primer debería tener el tiempo suficiente para la makeInt hilo para comenzar (y return 2 realmente no debería tomar tanto tiempo). ¿Por qué es eso y cómo soluciono esto?
¿Cómo se ejecuta el código? Por defecto, haskell usa hilos ligeros en lugar de hilos del sistema operativo real. No sé los detalles, pero esto puede cambiar muchas políticas de programación. –
Puede que no se ajuste a su caso, pero también puede consultar parte del trabajo sobre el "paralelismo especulativo" que se está realizando: http://hackage.haskell.org/package/speculation – jberryman
FYI, http://hackage.haskell.org/package/monad-par expone una API de paralelismo bastante agradable, externamente pura que, no obstante, te permite indicar explícitamente tenedores, combinaciones, etc. –