2010-01-19 80 views
4

我在C中有一个小的数值模拟(我不得不在C中与我的顾问共享它),但我想使用“haskell脚本”模拟。该程序接受一些命令行参数,并吐出一些输出,我想重定向到一个文件,所以我做了这样的事情:Haskell - 关于System.Process和多线程的一些问题

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)我刚才扔在同一时间执行1000个进程???我怎样才能以合理的顺序执行它们 - 一次或连续执行几个进程。

2)我在一个四核心运行这个,它会很好用这个对我有利。有没有一种方法,我可以编译这与-threaded标志,并获得进程并发执行,但有组织的方式?

回答

3

首先,您应该检查顶部或任务管理器,看看您是否确实快速连续创建1000个进程,然后根据该进程寻找解决方案。

减缓流程创建的简单方法是在创建下一个流程之前等待每个流程完成。因此,您不应将runCommand映射到您的commands上,您应该映射您自己的函数,该函数首先调用runCommand,然后在返回的ProcessHandle上调用waitForProcess,即每次调用辅助函数都会阻塞,直到生成的过程结束。

上述解决方案的缺点是,它只会使用您的四个核心之一。因此,如何利用所有四个核心将partitioncommands划分为四个(或者您希望使用的核心数量)列表,然后为每个子列表产生四个工作线程,分别为map,该子列表将在该子列表上运行map

Btw。mapM_ f == sequence_ . map f

+0

感谢您指向'forkIO'。我设法使用您的建议同时运行。非常好!我的第一个多核计划!哈哈哈... – 2010-01-19 17:10:12

+0

顺便说一句,这页提供帮助:http://haskell.org/haskellwiki/Haskell_for_multicores – 2010-01-19 17:10:44

+0

你最后一边不打字; mapM_ =(。)sequence_。地图“会更准确。 – ephemient 2010-01-20 17:20:10

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

这里有一个快速和肮脏的“同时运行几个”,如果它可以帮助:

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)使用列表作为一个简单的队列,运行多个命令,你告诉然后等待队列前面的队列,然后完成添加新命令。请注意,如果混入几个长时间运行的命令,这不会起到理想的作用,但对您而言可能已足够。尽管如此,请不要认为这完全是一种“正确”的方式。