2010-01-19 4 views
4

C로 작은 수치 시뮬레이션을하고 있습니다. (내 고문과 공유하기 위해 C에서 수행해야했습니다.)하지만 "haskell 스크립트"를 사용하여 정리하고 싶습니다. 시뮬레이션. 이 프로그램은 몇 가지 명령 줄 인수를 받아 I 파일로 리디렉션하고 싶은 몇 가지 출력을 내뿜으며, 그래서 나는이 같은 짓 :하스켈 - System.Process 및 mutithreading에 대한 몇 가지 질문

: I 출력 파일의 이름을 생성하는 기능을 가지고

import Control.Monad 
import System.Process 

filename :: Int -> String 
filename n = some stuff here... 

내가 싶어 명령이 실행

command :: Int -> String 
command n = "./mycutesimulation " ++ show n ++ " >" ++ filename n 

을 마지막으로 내가하고 runCommand 그들을에서 실행 싶어 런들의 목록을 생성 :

commands = map command [1,2..1000] 

main = do 
    sequence_ $ map runCommand commands 

이 "스크립트"를 실행하면 컴퓨터가 거의로드가 멈추는 문제가 있습니다. 실행중인 프로그램은 메모리 사용량이 매우 적고 몇 분의 1 초 만에 실행됩니다. 이것은 일어나서는 안됩니다.

그래서, 내 질문은 :

1) 난 그냥 1000 개 프로세스가 동시에 실행되는 던졌다나요 ??? 합리적 순서로 순차적으로 또는 한 번에 몇 개의 프로세스 만 실행할 수있는 방법은 무엇입니까?

2) 저는 이것을 쿼드 코어에서 실행하고 있습니다. 이걸 내 호의에 사용하는 것이 좋을 것 같습니다. 이 -threaded 플래그로 이것을 컴파일하고 동시 적으로 실행되지만 체계적으로 처리 할 수있는 방법이 있습니까?

답변

3

우선 맨 또는 작업 관리자를 확인하여 실제로 1000 개의 프로세스가 빠르게 연속적으로 생성되는지 확인한 다음이를 기반으로 솔루션을 찾아야합니다.

프로세스 생성을 느리게하는 쉬운 방법은 각 프로세스가 완료 될 때까지 기다렸다가 다음 프로세스를 생성하는 것입니다. 따라서 runCommandcommands에 매핑하는 대신 먼저 runCommand을 호출 한 자체 함수를 매핑 한 다음 ProcessHandlewaitForProcess을 호출합니다. 즉, 생성 된 프로세스가 완료 될 때까지 도우미 함수의 각 호출이 차단됩니다.

위의 솔루션의 단점은 네 개의 코어 중 하나만 사용한다는 것입니다. 따라서 네 개의 코어를 모두 사용하기 위해 할 수있는 일은 partitioncommands을 네 개 (또는 원하는만큼 많은 코어) 목록에 넣은 다음 해당 하위 목록에 map을 실행할 각 하위 목록에 대해 forkIO으로 작업자 스레드 4 개를 생성합니다. .

btw.당신이 말할만큼 명령을

import System.Process 

commands = replicate 16 "sleep 2" 

runSome handles cmd = do 
    (h:hs) <- handles 
    waitForProcess h 
    h' <- runCommand cmd 
    return $ hs ++ [h'] 

test n = 
    let initial = mapM runCommand $ take n commands 
    in foldl runSome initial (drop n commands) 

이 단지 (MIS)

간단한 큐으로 목록을 사용하여 실행 : mapM_ f == sequence_ . map f

+0

'forkIO'를 (를) 지정해 주셔서 감사합니다. 나는 그것을 당신의 제안을 사용하여 동시에 실행하도록 만들었다. 아주 좋아! 내 첫번째 멀티 코어 프로그램! 하하 ... –

+0

현재 페이지 도움 : http://haskell.org/haskellwiki/Haskell_for_multicores –

+0

마지막으로 제쳐두고 입력하지 않습니다; 'mapM_ = (.) sequence_. 지도 '가 더 정확할 것입니다. – ephemient

4

waitForProcess =<< runCommand이 필요합니다.

import System.Process 

main = sequence $ map (\x -> runCommand x) commands 
where commands = map (\x -> "echo " ++ show x) [1, 2..1000] 

는 당신과 비슷한 증상을 가지고 있지만,

import System.Process 

main = sequence $ map (\x -> waitForProcess =<< runCommand x) commands 
where commands = map (\x -> "echo " ++ show x) [1, 2..1000] 

작품.

1

여기에 도움이된다면, "한 번에 몇 가지를 실행"신속하고 더러운입니다 그 다음, 대기열 앞에있는 대기열에서 기다리고 완료되면 새로운 명령이 추가됩니다. 장시간 실행되는 몇 가지 명령이 섞여 있지만 충분할 수도 있지만 이상적으로 작동하지 않습니다. 그래도 이것이 "올바른"방법이라고 생각하지 마십시오.