perl6
Помогающий
Offline
|
|
« : 01-09-2010 20:32 » |
|
Привествую всех. Собственно, вот код #!/usr/bin/perl -w
$| = 1;
open(F, "< file.txt"); @f=<F>; chomp(@f); close(F);
$s = scalar @f; $i = 0; $count = 1;
while ($i <= $count) { $j = 0; @pids = ();
while ($j++ <= 2) { $pid = fork();
if ($pid == 0) { sleep 1; $k = 0;
while ($k < $s) { $ip = shift(@f); chomp($ip); print "$ip \n"; $k++; }
exit 0; } else { push @pids, $pid if defined($pid); };
$i++; };
waitpid($_, 0) foreach @pids; };
Содержимое файла file.txt 1 2 3 4 5 6 7 8 9 10 11 12 14 15 16 17 18 19 20
Вот, что выводит перл Microsoft Windows XP [Версия 5.1.2600] (С) Корпорация Майкрософт, 1985-2001.
C:\Documents and Settings\Саша>cd\
C:\>f.pl 1 2 3 4 5 6 7 8 9 10 11 12 14 15 16 17 18 19 20 1 2 3 4 5 6 7 8 1 9 2 10 3 11 4 12 5 14 6 15 7 16 8 17 9 18 10 19 11 20 12 14 15 16 17 18 19 20
C:\>
И сам вопрос, предполагалось, что два процесса должны ПАРАЛЛЕЛЬНО обработать строки из файла, т.е., процесс первый выводит число 1, второй - число 2, первый - число 3, снова второй - число 4, после вывода числа 20 скрипт закрывается... А у меня какая то ерунда, сначала один процесс выводит 20 чисел, потом другой... Подскажите, что не так с кодом, будьте так любезны. Спасибо за любую подсказку...
|
|
« Последнее редактирование: 02-09-2010 05:59 от RXL »
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #1 : 01-09-2010 20:41 » |
|
Проблема в том, что хоть ты и распаралелил. У тебя все равно будет работать один процесс или нитка в данный момент времени. Если конечно у тебя не многопроцессорная система. Процесс отработает свой квант времени, и тогда система переключит на другой процесс, чтоб он отрабатывал свой квант времени.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #2 : 02-09-2010 06:01 » |
|
perl6, опиши, какую задачу должен выполнять этот код.
Код переформатировал. Никто меня не убедит, что он был аккуратный. Кстати, очень нехороший рваный стиль. Многие выражения не читаются. Пусть Перл и гибкий, но старайся писать однотипно и однозначно. Используй use strict.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
perl6
Помогающий
Offline
|
|
« Ответ #3 : 02-09-2010 08:34 » |
|
perl6, опиши, какую задачу должен выполнять этот код.
Код переформатировал. Никто меня не убедит, что он был аккуратный. Кстати, очень нехороший рваный стиль. Многие выражения не читаются. Пусть Перл и гибкий, но старайся писать однотипно и однозначно. Используй use strict.
Этот код должен в многопоточном режиме брать прокси из списка, затем переходить по урлу, используя взятый прокси сервер, так до тех пор, пока не кончатся прокси сервера... Добавлено через 45 секунд:#!/usr/bin/perl -w
use strict;
$| = 1;
open(F,"< file.txt"); my @f=<F>; chomp(@f); close(F);
my $s = scalar @f;
my $i=0; my $count = 1; while ($i<=$count) { my $j = 0; my @pids = (); while ($j++ <= 2) { my $pid = fork(); if ($pid == 0){ sleep 1;
my $k = 0; while ($k < $s) { my $ip = shift(@f); chomp($ip);
print "$ip \n";
$k++; }
exit 0; } else { push my @pids, $pid if defined($pid); }; $i++; }; waitpid($_, 0) foreach @pids; };
|
|
« Последнее редактирование: 02-09-2010 08:35 от perl6 »
|
Записан
|
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #4 : 02-09-2010 09:37 » |
|
perl6, отформатируй код!
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
perl6
Помогающий
Offline
|
|
« Ответ #5 : 02-09-2010 16:20 » |
|
perl6, отформатируй код!
Каким образом???
|
|
|
Записан
|
|
|
|
perl6
Помогающий
Offline
|
|
« Ответ #6 : 02-09-2010 16:22 » |
|
#!/usr/bin/perl -w
use strict;
$| = 1;
open(F,"< file.txt"); my @f=<F>; chomp(@f); close(F);
my $s = scalar @f;
my $i=0; my $count = 1; while ($i<=$count) { my $j = 0; my @pids = (); while ($j++ <= 2) { my $pid = fork(); if ($pid == 0){ sleep 1;
my $k = 0; while ($k < $s) { my $ip = shift(@f); chomp($ip);
print "$ip \n";
$k++; }
exit 0; } else { push my @pids, $pid if defined($pid); }; $i++; }; waitpid($_, 0) foreach @pids; };
Так???
|
|
|
Записан
|
|
|
|
Sla
|
|
« Ответ #7 : 02-09-2010 18:11 » |
|
perl6, посмотри ка отформатирован твой код в первом посте.
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
perl6
Помогающий
Offline
|
|
« Ответ #8 : 02-09-2010 19:01 » |
|
perl6, посмотри ка отформатирован твой код в первом посте.
Посмотрел, нужно сделать также?
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #9 : 02-09-2010 19:03 » |
|
perl6, Ну это примерно как стандарт оформления кода программы. При таком оформлении намного легче читать программу стороннему человеку. Да и тебе где то через месяц будет намного легче вспоминать весь твой ранний дзен. Заведи себе нормальный редактор, для написания программ. Он сам автоматически будет поддерживать такой стиль.
|
|
« Последнее редактирование: 02-09-2010 19:05 от Finch »
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
perl6
Помогающий
Offline
|
|
« Ответ #10 : 02-09-2010 19:14 » |
|
Сейчас исправлю.
|
|
« Последнее редактирование: 02-09-2010 19:21 от perl6 »
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #11 : 02-09-2010 19:23 » |
|
perl6, Редакторы как правило код сами не форматируют. Но поддерживают нужные отступы. И естественно для новых блоков делают другие отступы.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
perl6
Помогающий
Offline
|
|
« Ответ #12 : 02-09-2010 19:28 » |
|
#!/usr/bin/perl -w
use strict;
$| = 1;
open(F, "< file.txt"); my @f=<F>; chomp(@f); close(F);
my $s = scalar @f; my $i = 0; my $count = 1;
while ($i <= $count) { my $j = 0; my @pids = ();
while ($j++ <= 2) { my $pid = fork();
if ($pid == 0) { sleep 1; my $k = 0;
while ($k < $s) { my $ip = shift(@f); chomp($ip); print "$ip \n"; $k++; }
exit 0; } else { push my @pids, $pid if defined($pid); };
$i++; };
waitpid($_, 0) foreach @pids; };
Вот так приемлимо?
|
|
|
Записан
|
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #13 : 02-09-2010 20:44 » |
|
Да, так уже лучше. Когда код ужасно оформлен его и читать то не хочется. По задаче: Сразу после fork() у тебя появляется новый процесс, со собственным адресным пространством и с полной копией всего, что было в родительском процессе. Копия массива @f будет во всех созданных тобой процессах и shift(@f) будет влиять только на копию текущего процесса. Вывод: необходим арбитр, который разделит список по дочкам. Логично, что им должен выступить родительский процесс. Это можно сделать предварительно, перед fork(), создав еще один массив и перенеся туда часть заданий для создаваемого процесса. Плюс решения - простота. Минус - дочки не будут сбалансированы по нагрузке и времени выплнения, т.к. одни прокси могут не пустить и коннект быстро разорвется, другие хосты могут вообще не существовать и коннект будет ждать таймаута. Также очередная дочка может даже не создаться в силу превышения каких-либо лимитов. Иначе, можно создать канал между родительским процессом и дочкой, по которому дочка будет сообщать о готовности к работе, а родитель будет давать задания. Это много сложнее в реализации, но вполне реально. Рекомендую пока попробовать первый вариант - с предварительным делением заданий. По стилю: Посмотри, какие-то функции ты используешь со скобками, а какие-то без. Лучше избегать такого и делать однообразно. И лучше всего - со скобками. Особенно это не однозначно выглядит в этом выражении: push my @pids, $pid if defined($pid); Кстати, а что тут делает "my"? Это вот еще одна рекомендация: объявляй локальные переменные в начале блока, а не где не попадя. А что касается выражения, то лучше тут использовать полную форму: if (defined($pid)) { push(@pids, $pid); }
Обратная запись очевидна и уместна в выражениях типа: Для строковых констант, не нуждающихся в интерполяции, используй одиночные кавычки. Это поможет избежать некоторых ошибок, а еще сокращает работу процессора.
|
|
« Последнее редактирование: 02-09-2010 20:51 от RXL »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
perl6
Помогающий
Offline
|
|
« Ответ #14 : 03-09-2010 09:27 » |
|
Спасибо, а если все это делать, используя threads? УпростиТСя ли задача в этом случае?
|
|
« Последнее редактирование: 03-09-2010 09:46 от Sel »
|
Записан
|
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #15 : 04-09-2010 07:54 » |
|
И да, и нет. С одной стороны, у потоков общее адресное пространство, что облегчает коммуникации, но с другой стороны работа с общими данными обязательно требует использования механизмов синхронизации, иначе будут стабильные и плавающие ошибки.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
perl6
Помогающий
Offline
|
|
« Ответ #16 : 04-09-2010 10:40 » |
|
Понятно. Добавлено через 1 час, 11 минут и 33 секунды:Это можно сделать предварительно, перед fork(), создав еще один массив и перенеся туда часть заданий для создаваемого процесса.
А что вы имели ввиду, под этим? Не подскажите ли кусочком кода глупому лузеру?
|
|
« Последнее редактирование: 04-09-2010 11:52 от perl6 »
|
Записан
|
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #17 : 04-09-2010 12:45 » |
|
Просто вычислить, по скольку заданий придется на каждый рабочий процесс и перед fork() переносить их в специально для этого используемый массив. my @common;
# Считаем, что @common уже заполнен из файла.
my $tasks = 2; # Число рабочих процессов. my $per_task = int(@common / $tasks); # Сколько заданий придется на задачу. По правилам преобразования Perl округление идет к нулю.
for my $task_number (1..$tasks) { my @private;
if ($task_number != $tasks) { @private = splice(@common, 0, $per_task); } else { @private = @common; # Последней задаче отдаем все оставшиеся задания. }
# Здесь можно делать fork() и внутри рабочего процесса использовать @private. }
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
perl6
Помогающий
Offline
|
|
« Ответ #18 : 04-09-2010 13:30 » |
|
#!/usr/bin/perl -w
$| = 1;
use strict;
my @common;
# Считаем, что @common уже заполнен из файла.
my $tasks = 2; # Число рабочих процессов. my $per_task = int(@common / $tasks); # Сколько заданий придется на задачу. По правилам преобразования Perl округление идет к нулю.
for my $task_number (1..$tasks) { my @private;
if ($task_number != $tasks) { @private = splice(@common, 0, $per_task); } else { @private = @common; # Последней задаче отдаем все оставшиеся задания. }
open(F, "< file.txt"); my @private=<F>; chomp(@private); close(F);
my $s = scalar @private; my $i = 0; my $count = 1;
while ($i <= $count) { my $j = 0; my @pids = ();
while ($j++ <= 1) { my $pid = fork();
if ($pid == 0) { sleep 1; my $k = 0;
while ($k < $s) { my $ip = shift(@private); chomp($ip); print "$ip \n"; $k++; }
exit 0; } else { push my @pids, $pid if defined($pid); };
$i++; };
waitpid($_, 0) foreach @pids; }; }
Спасибо, но вроде что то не то, или я напутал?
|
|
« Последнее редактирование: 04-09-2010 14:30 от perl6 »
|
Записан
|
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #19 : 04-09-2010 14:44 » |
|
Конечно не то! Подумай хорошенько, что было и что ты сделал. Честно говоря, не наблюдаю у тебя ни капли понимания. Не программируешь, а копи-пастом занимаешься. На таких условиях нет желания помогать.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #21 : 04-09-2010 20:07 » |
|
perl6, разбирайся, учи и т.п. Будет что показать, что получше поста №20 - посмотрим.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
perl6
Помогающий
Offline
|
|
« Ответ #22 : 05-09-2010 16:15 » |
|
Будет что показать, что получше поста №20 - посмотрим.
|
|
|
Записан
|
|
|
|
|