Запилил за 10 минут. Такие задачки на Go решаются элементарно. А если учесть, что каждая горутина может выполняться на своём CPU и никаких GIL, то становится ням-ням как вкусно.
5 июня 2014 г., 15:10 пользователь Eugene Toropov <[email protected]> написал: > Интересно, это уже готовое было или запилил за полчаса? > > Евгений > > On Jun 5, 2014, at 5:03 PM, Alexander Lourier <[email protected]> wrote: > > Минутка рекламы. Вот решение задачи на Go. Оно длинное, потому что я его > обильно снабдил комментариями. Если лишнее убрать, всё будет выглядеть > очень компактно и работать производительно. > > > package main > import ( > "fmt" > "math/rand" > "time" > ) > const ( > numWorkers = 10 > ) > // task - это задание для воркера.type task struct { > value int > output chan result > } > // result - это результат обработки задания воркером.type result struct { > value int > worker int > } > // worker берёт данные из канала input, обрабатывает их (умножает на 100) и > кладёт в канал ответа,// который прислан вместе с заданием.func > worker(workerNumber int, input chan task) { > // Пока входной канал не закроют, читаем из него задание. > for task := range input { > // Работаем в поте лица. > time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond) > task.output <- result{task.value * 100, workerNumber} > } > } > // prepareInput готовит входные задания и кладёт их в два канала: в одну > очередь// задания для воркеров, в другую - каналы ответа.func > prepareInput(input chan task, output chan chan result) { > for i := 0; i < 100; i++ { > // Канал ответа буферизованный, чтобы воркер не ждал, когда его > ответ считают, > // а сразу брался за следующее задание. > outputChan := make(chan result, 1) > // Тот факт, что задания кладутся в input и output в одном и > том же порядке, > // гарантирует, что ответы будут упорядочены в том же порядке. > input <- task{i, outputChan} > output <- outputChan > } > close(input) > close(output) > } > func main() { > // Каналы обязательно буферизованные (длина буфера = числу воркеров). > input := make(chan task, numWorkers) > output := make(chan chan result, numWorkers) > > // Запускаем готовилку входных данных. > go prepareInput(input, output) > > // Запускаем воркеры. > for i := 0; i < numWorkers; i++ { > go worker(i, input) > } > > // Читаем ответы в порядке, в каком нам нужно. > for res := range output { > fmt.Printf("%+v\n", <-res) > } > } > > > > 5 июня 2014 г., 13:46 пользователь Харпалёв Иван <[email protected] > > написал: > >> Добрый день, могучий MoscowPM >> >> Опять про параллельную обработку. >> >> Хочется написать вот такую схему обработки ввода: >> master создаёт work'ов, >> читает порции из файла, раздаёт порции worker'ам >> ждёт, пока worker обработает, получает ответ worker'a >> пишет результат в файл. >> Так же мастер буфереизует вывод, чтобы выход писался в правильном порядке. >> >> Самое туманное: >> Как передавать данные от мастера к worker'у и Обратно?!!!! >> Как ждать готовности?!!! >> Должна ли такая схема (работа с диском из одного места) дать ускорение по >> сравнению с чтением/записью файла в каждом worker'е? >> >> смотрел на Coro, увидел Coro::Simaphore, Coro::Signal ... но не пойму: >> как сделать разделяемую память, (как быстро передавать данные между >> мастером и worker'ом внутри Perl)? >> как сделать неблокирующее ожидание готовности одного из worker'ов (при >> котором можно заниматься вводом-выводом)? >> >> Подскажите, на чём и как такое писать!! >> Спасибо! >> >> Уважение >> Иван Харпалев >> >> >> >> -- >> Moscow.pm mailing list >> [email protected] | http://moscow.pm.org >> >> > -- > Moscow.pm mailing list > [email protected] | http://moscow.pm.org > > > > -- > Moscow.pm mailing list > [email protected] | http://moscow.pm.org > >
-- Moscow.pm mailing list [email protected] | http://moscow.pm.org
