<div dir="ltr">><span style="font-family:arial,sans-serif;font-size:13px">Ну а если воркеры вычисления делают, т.е. CPU потребляют, будет работать?</span><div><span style="font-family:arial,sans-serif;font-size:13px"><br>
</span></div><div>Отвечу за Антона - будет, медленней точно не станет.</div><div>Оборачиваем "воркер" в async - в цикле эти асинки складываем в массив, Делаем join и радуемся массиву значений.</div><div>Создавать под это процессы это перебор.</div>
</div><div class="gmail_extra"><br><br><div class="gmail_quote">5 июня 2014 г., 22:24 пользователь Victor Efimov <span dir="ltr"><<a href="mailto:victor@vsespb.ru" target="_blank">victor@vsespb.ru</a>></span> написал:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">5 июня 2014 г., 22:12 пользователь Antonio Nikishaev <<a href="mailto:a@lelf.me">a@lelf.me</a>> написал:<br>
<div class="">> Нахрена вам разделяемая память и костыли с трубами?<br>
><br>
> Куча async. В конце всем ->join. Если надо по частям передавать данные то Coro::Channel к каждому<br>
><br>
<br>
</div>Ну а если воркеры вычисления делают, т.е. CPU потребляют, будет работать?<br>
<div class="HOEnZb"><div class="h5"><br>
><br>
><br>
> On 5 Jun 2014, at 19:47, Харпалёв Иван <<a href="mailto:ivan.kharpalev@gmail.com">ivan.kharpalev@gmail.com</a>> wrote:<br>
><br>
>> Спасибо!<br>
>> На  Go выглядит заманчиво, хотя и совершенно не понятно, как происходит распределение входа между воркерами.<br>
>><br>
>> Классный пример с ForkEngine.<br>
>> Вот только в доке IO::Pipe не описаны  функции autoflush и blocking. Зачем они вызываются в ForkEngine?? и зачем делается binmode на дескриптор?<br>
>><br>
>> Передача через Pipe -- подходящее решение (прогон через paip почти не замедляет построчное копирование из файла в файл на Perl).<br>
>><br>
>> А как же быть c получением из воркеров??<br>
>> как-то так?<br>
>> open my $input, "<", $in_file or die "Can not open file for read";<br>
>> open my $output, ">", $out_file or die "Can not open file for write";<br>
>> for (@workers) {<br>
>> ⇥   my $wait_for_input  = AnyEvent->io (<br>
>> ⇥   ⇥   fh => $_->{fromchild},<br>
>> ⇥   ⇥   poll => 'r',<br>
>> ⇥   ⇥   cb => sub {<br>
>> ⇥   ⇥   ⇥   say $output readline ($_->{fromchild});<br>
>> ⇥   ⇥   ⇥   $_->{c}--; #счётчик очереди в worker'е<br>
>> ⇥   ⇥   }<br>
>> ⇥   )<br>
>> }<br>
>> my $number=0;<br>
>> while (<$input>) {<br>
>> ⇥   while(1){<br>
>> ⇥   ⇥   $number = ++$number  % $#workers;<br>
>> ⇥   ⇥   my $worker = $workers[$number];<br>
>> ⇥   ⇥   if ($worker->{c} < 10) {<br>
>> ⇥   ⇥   ⇥   my $to = $worker->{tochild};<br>
>> ⇥   ⇥   ⇥   say $to $_;<br>
>> ⇥   ⇥   ⇥   $worker->{c}++;<br>
>> ⇥   ⇥   }<br>
>> ⇥   }<br>
>> }<br>
>><br>
>> Gearman -- штука крутая, но всё-таки хочется на Perl.<br>
>> А как решить на Coro по-прежнему непонятно(<br>
>> Вроде если есть симафоры, по они должны быть для разделяемых ресурсов и следовательно должно быть возможно изменять оду и ту же переменную из разных потоков...   Возможно ли вообще такое в Perl.  Хотя пайпы вроде норм решение для передачи и главная проблема в неблокирующем ожидании.<br>

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