2012-04-20 3 views
13

두 개의 값 중 하나만 필요하고, 상황에 따라 어느 하나가 다른 것보다 훨씬 빠르게 생성 될 수있는 특정 최적화를 위해 Haskell에서 동시성을 사용하려고합니다.하스켈 병행 성 - 실제로 forkio는 비 결정적입니까?

나는 forkIO로 2 개의 스레드를 실행할 수 있다고 생각하고 값이 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) 

컴파일 : 총리를 얻는 것은 makeInt에 대해 충분히해야하지만

그러나
ghc --make -threaded Test 

만 왼쪽의 경우 이제까지 도달 여기에 내가 이것을 위해 작성한 간단한 테스트입니다 스레드를 시작 (그리고 2 반환 정말 많은 시간이 걸릴해서는 안). 왜 그런가요? 어떻게 수정합니까?

+0

코드를 어떻게 실행합니까? 기본적으로 haskell은 실제 OS 쓰레드보다는 가벼운 쓰레드를 사용합니다. 세부 사항을 모르지만 스케줄링 정책이 많이 바뀔 수 있습니다. –

+0

사례에 맞지 않을 수도 있지만 "투기 적 병렬 처리"에 대한 작업 중 일부를 살펴볼 수도 있습니다. http://hackage.haskell.org/package/speculation – jberryman

+3

FYI, http://hackage.haskell.org/package/monad-par는 그럼에도 불구하고 외부, 순수 병렬 처리 API를 제공합니다. 그럼에도 불구하고 명시 적으로 forks, join 등을 명시 할 수 있습니다. –

답변

20

여기의 문제는 게으름입니다. makeString은 덤프를 삽입하여 show (primes !! 10000)을 계산 한 다음 나중에 주 스레드가 평가합니다. 썽크를 넣는 것은 꽤 빠르기 때문에이 경우에는 경기에서 승리합니다. (이 보장되지 비록)

makeString out = do s <- evaluate $ show (primes !! 10000) 
        putMVar out $ Left s 

이 대부분의 경우에서 경주를 우승 makeInt을 야기한다 :

하는 스레드 내에서 일어날 평가를 강제하려면 returnevaluate에 변경할 수 있습니다.

+1

고마워요! 나는 게으름을 완전히 잊었다. – Cubic

10

예, 스레드는 실제로 (GHC에서) 비 결정적입니다.

특정 코드가 항상 t1이 항상 승리하는 방식으로 구조화되고 최적화됩니다. 보장은 없습니다.

다른 결과를 내기 위해 마사지를 시도하려면 최적화 (-O2)를 켜거나 여러 코어 (+RTS -N)를 사용하십시오.

예. 내 컴퓨터, 연속 2 실점에 : HAMMAR 지적

$ ghc -O2 -threaded --make A.hs -rtsopts -fforce-recomp 
[1 of 1] Compiling Main    (A.hs, A.o) 
Linking A.exe ... 
$ ./A +RTS -N2 
2 
$ ./A +RTS -N2 
104743 

으로, 당신은 또한 스레드에서 자리를 차지할 더 많은 작업을 강제로 코드를 구성 할 수 있습니다 (또는 using strict mvars로 전환).

+0

감사합니다. RTS에 매개 변수를 전달할 수 있는지조차 알지 못했습니다. – Cubic