Я пытаюсь использовать параллелизм в Haskell для конкретной оптимизации, в которой требуется только одно из двух значений, и в зависимости от ситуации, каждый может быть намного быстрее, чем другой.Совместимость Haskell - forkIO действительно недетерминирован?
Я думал, что могу просто запустить 2 потока с forkIO, а затем подождать, пока значение не будет размещено в MVar. Вот простой тест я написал для этого:
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)
Собран с:
ghc --make -threaded Test
Однако только случай с левого сек когда-либо достигнуто, хотя получение премьер должен занять достаточно много времени для makeInt нить для начала (и возврат 2 действительно не должен занимать столько времени). Почему это и как я это исправить?
Как вы запускаете свой код? По умолчанию haskell использует световые потоки, а не реальные потоки ОС. Я не знаю подробностей, но это может изменить много политик планирования. –
Возможно, вам не подходит ваш случай, но вы также можете изучить некоторые из выполненных работ по «спекулятивному параллелизму»: http://hackage.haskell.org/package/speculation – jberryman
FYI, http://hackage.haskell.org/package/monad-par предоставляет довольно красивый, внешне чистый API параллелизма, который тем не менее позволяет явно указывать вилки, объединения и т. д. –