2010-01-19 2 views
4

У меня есть небольшое числовое моделирование в C (я должен был сделать это в C, чтобы поделиться им с моим советником), но я хочу использовать «скрипт haskell» как вещь для организации моделирование. Программа принимает некоторые аргументы командной строки и плюет некоторый вывод, я хотел бы перенаправить в файл, так что я сделал что-то вроде этого:Haskell - Некоторые вопросы о System.Process и mutithreading

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, а затем вызывает waitForProcess по возвращенному ProcessHandle, т. Е. Каждый вызов вашей вспомогательной функции будет блокироваться до тех пор, пока процесс порождения не завершится.

Недостатком вышеупомянутого решения является то, что он будет использовать только один из ваших четырех ядер. Итак, что вы можете сделать, чтобы использовать все четыре ядра, - это partitioncommands в четыре (или столько же ядер, сколько вы хотите использовать), а затем создайте четыре рабочих потока с forkIO для каждого подсписок, каждый из которых будет запускать map в этом подсписке ,

КПП.mapM_ f == sequence_ . map f

+0

Спасибо за указание 'forkIO'. Мне удалось запустить его одновременно с использованием вашего предложения. Очень хорошо! Моя первая многоядерная программа! Hahahah ... –

+0

BTW, эта страница помогла: 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

Вот быстрый и грязный «запустить несколько в то время», если это поможет:

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) использует список как простая очередь, работает множество команд, как вы говорите это, а затем ждет на том, что находится впереди очереди, и когда это сделано, добавляется новая команда. Обратите внимание, что это не будет вести себя идеально, если несколько длинных команд будут перемешаны, но вам может быть достаточно. Пожалуйста, не думайте, что это вообще «правильный» способ сделать это.

Смежные вопросы