Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Параллельная обработка строк из файла  (Прочитано 23693 раз)
0 Пользователей и 1 Гость смотрят эту тему.
perl6
Помогающий

ru
Offline 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
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #1 : 01-09-2010 20:41 » 

Проблема в том, что хоть ты и распаралелил. У тебя все равно будет работать один процесс или нитка в данный момент времени. Если конечно у тебя не многопроцессорная система. Процесс отработает свой квант времени, и тогда система переключит на другой процесс, чтоб он отрабатывал свой квант времени.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #2 : 02-09-2010 06:01 » 

perl6, опиши, какую задачу должен выполнять этот код.

Код переформатировал. Никто меня не убедит, что он был аккуратный.
Кстати, очень нехороший рваный стиль. Многие выражения не читаются. Пусть Перл и гибкий, но старайся писать однотипно и однозначно. Используй use strict.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
perl6
Помогающий

ru
Offline 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
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #4 : 02-09-2010 09:37 » 

perl6, отформатируй код!
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
perl6
Помогающий

ru
Offline Offline

« Ответ #5 : 02-09-2010 16:20 » 

perl6, отформатируй код!
Каким образом???
Записан
perl6
Помогающий

ru
Offline 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
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #7 : 02-09-2010 18:11 » 

perl6, посмотри ка отформатирован твой код в первом посте.
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
perl6
Помогающий

ru
Offline Offline

« Ответ #8 : 02-09-2010 19:01 » new

perl6, посмотри ка отформатирован твой код в первом посте.
Посмотрел, нужно сделать также?
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #9 : 02-09-2010 19:03 » 

perl6, Ну это примерно как стандарт оформления кода программы. При таком оформлении намного легче читать программу стороннему человеку. Да и тебе где то через месяц будет намного легче вспоминать весь твой ранний дзен. Заведи себе нормальный редактор, для написания программ. Он сам автоматически будет поддерживать такой стиль.
« Последнее редактирование: 02-09-2010 19:05 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
perl6
Помогающий

ru
Offline Offline

« Ответ #10 : 02-09-2010 19:14 » 

Сейчас исправлю.
« Последнее редактирование: 02-09-2010 19:21 от perl6 » Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #11 : 02-09-2010 19:23 » 

perl6, Редакторы как правило код сами не форматируют. Но поддерживают нужные отступы. И естественно для новых блоков делают другие отступы.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
perl6
Помогающий

ru
Offline 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
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #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);
}

Обратная запись очевидна и уместна в выражениях типа:

Код:
next if ...;

Для строковых констант, не нуждающихся в интерполяции, используй одиночные кавычки. Это поможет избежать некоторых ошибок, а еще сокращает работу процессора.
« Последнее редактирование: 02-09-2010 20:51 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
perl6
Помогающий

ru
Offline Offline

« Ответ #14 : 03-09-2010 09:27 » 

Спасибо, а если все это делать, используя threads? УпростиТСя ли задача в этом случае?
« Последнее редактирование: 03-09-2010 09:46 от Sel » Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #15 : 04-09-2010 07:54 » 

И да, и нет. С одной стороны, у потоков общее адресное пространство, что облегчает коммуникации, но с другой стороны работа с общими данными обязательно требует использования механизмов синхронизации, иначе будут стабильные и плавающие ошибки.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
perl6
Помогающий

ru
Offline Offline

« Ответ #16 : 04-09-2010 10:40 » 

Понятно.

Добавлено через 1 час, 11 минут и 33 секунды:
Цитата
Это можно сделать предварительно, перед fork(), создав еще один массив и перенеся туда часть заданий для создаваемого процесса.
А что вы имели ввиду, под этим? Не подскажите ли кусочком кода глупому лузеру? Жаль
« Последнее редактирование: 04-09-2010 11:52 от perl6 » Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #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
Помогающий

ru
Offline 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
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #19 : 04-09-2010 14:44 » 

Конечно не то! Подумай хорошенько, что было и что ты сделал.

Честно говоря, не наблюдаю у тебя ни капли понимания.  Жаль
Не программируешь, а копи-пастом занимаешься. На таких условиях нет желания помогать.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
perl6
Помогающий

ru
Offline Offline

« Ответ #20 : 04-09-2010 19:44 » 

Тонкий намек на толстое обстоятельство ясен. Да-да
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #21 : 04-09-2010 20:07 » 

perl6, разбирайся, учи и т.п. Будет что показать, что получше поста №20 - посмотрим.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
perl6
Помогающий

ru
Offline Offline

« Ответ #22 : 05-09-2010 16:15 » 

Цитата
Будет что показать, что получше поста №20 - посмотрим.
Улыбаюсь
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines