Пожалуйста, представьте мультипроцессорную библиотеку на Perl или Ruby - PullRequest
5 голосов
/ 13 мая 2009

В Python мы можем использовать многопроцессорные модули. Если бы в Perl и Ruby была похожая библиотека, вы бы ее научили? Буду признателен, если вы включите краткий образец.

Ответы [ 5 ]

12 голосов
/ 13 мая 2009

Ruby:

Perl:

Кроме того, потоки Perl являются собственными потоками операционной системы, поэтому вы можете просто использовать их для использования преимуществ нескольких ядер.

9 голосов
/ 13 мая 2009

С Perl у вас есть варианты. Одним из вариантов является использование процессов, как показано ниже. Мне нужно посмотреть, как написать аналогичную программу, используя потоки, но http://perldoc.perl.org/perlthrtut.html должно дать вам представление.

#!/usr/bin/perl

use strict;
use warnings;

use Parallel::ForkManager;

my @data = (0 .. 19);

my $pm = Parallel::ForkManager->new(4);

for my $n ( @data ) {
    my $pid = $pm->start and next;
    warn sprintf "%d^3 = %d\n", $n, slow_cube($n);
    $pm->finish;
}

sub slow_cube {
    my ($n) = @_;

    sleep 1;
    return $n * $n * $n;
}

__END__

Следующая версия, использующая потоки, не использует ограничение на количество создаваемых потоков (потому что я не знаю как):

#!/usr/bin/perl

use strict;
use warnings;

use threads;

my @data = (0 .. 19);
my @threads = map { 
    threads->new( {context => 'list' }, \&slow_cube, $_ )
} @data;

for my $thr ( @threads ) {
    my ( $n, $ncubed ) = $thr->join;
    print "$n^3 = $ncubed\n";
}

sub slow_cube {
    my ($n) = @_;

    sleep 1;
    return $n, $n * $n * $n;
}

__END__

Интересно:

TimeThis :  Command Line :  t.pl
TimeThis :  Elapsed Time :  00:00:01.281
3 голосов
/ 13 мая 2009

Проверьте Coro , которые предоставляют сопрограммы для Perl.

Вот выдержка из документации авторов ....

Этот набор модулей управляет продолжениями в целом, чаще всего в форме кооперативных потоков (также называемых coro, или просто "coro" в документации). Они похожи на потоки ядра, но (в общем случае) не работают параллельно одновременно даже на машинах SMP. Особый вид потоков, предлагаемый этим модулем, также гарантирует, что он не будет переключаться между потоками без необходимости в легко идентифицируемых точках вашей программы, поэтому блокировка и параллельный доступ редко становятся проблемой, делая программирование потоков намного безопаснее и проще, чем использование другие модели резьбы.

В отличие от так называемых «потоков Perl» (которые на самом деле не являются реальными потоками, а являются только эмуляцией процессов Windows, портированной на Unix и, таким образом, действуют как процессы), Coro обеспечивает полное общее адресное пространство, которое обеспечивает связь между потоками очень просто. И потоки Coro также быстрые: отключение кода эмуляции процесса Windows в вашем perl и использование Coro могут легко привести к увеличению скорости ваших программ в два-четыре раза. Тест параллельного умножения матриц выполняется в 300 раз быстрее на одном ядре, чем псевдопотоки perl на четырехъядерном процессоре с использованием всех четырех ядер.


Что-то похожее на вышеописанное в Ruby, посмотрите на Fiber , которая поставляется с Ruby 1.9.

Вот две интересные статьи об использовании Fiber:

Существует также волокно для Perl , использующее Coro. Вот несколько статей о Fiber для Perl (на японском):

1 голос
/ 01 февраля 2011

Посмотрите на эту симпатичную сводную страницу для библиотек Perl с параллельной обработкой http://www.openfusion.net/perl/parallel_processing_perl_modules. Мне нравится Parallel :: Forker, это современная и более мощная библиотека, чем старый Parallel :: ForkManager, и имеет больше функций, таких как сигнализация потомков процессы. Я использовал его в нескольких проектах, и он работает точно так, как ожидалось. Вот пример того, как его использовать:

#!/usr/bin/env perl

use strict;
use warnings;
use Parallel::Forker;

my $forker = Parallel::Forker->new(use_sig_child => 1, max_proc => 4);
$SIG{CHLD} = sub {
    Parallel::Forker::sig_child($forker);
};
$SIG{TERM} = sub {
    $forker->kill_tree_all('TERM') if $forker and $forker->in_parent;
    die "Exiting child process...\n";
};
# an example
for (1..10) {
    $forker->schedule(run_on_start => sub {
        # all child process code to run here
    })->ready();
}
# wait for all child processes to finish
$forker->wait_all();

Надеюсь, это поможет вам

0 голосов
/ 09 февраля 2012
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...