Pull to refresh

Проще сделать самому, или to fork() or not to fork()

Reading time2 min
Views934
Решая проблему вычисления объемных данных в циклах частенько тянет распараллелить задачку.
Конечно же в perl есть сразу пара моделей: fork или thread, позволюящих использовать «многопоточность». Реализация каждого способа и религиозные предпочтения к материалу данной заметки не относятся.
Говорить будем о подкреплении выбора «делить/не делить» цифрами.

Если говорить коротко, то выделение вычесления в «отдельный поток» кроме плюсов несет еще и жирный минус, связаный с накладными расходами на создание потомка, коммуникации с ним и его обслуживание.
Логично предположить, что зная стоимость накладных расходов «многопоточности» мы сможем аргументированно выбрать ту или иную архитектуру своего приложения. Значит нужно взять и посчитать, например вот так:

use Benchmark qw( timethese cmpthese ) ;

sub forked {
  my $pid = fork;
  $pid ? waitpid($pid, 0) : exit 0;
}

sub empty {
  1;
}

my $r = timethese( -1, {
    a => sub {forked(2)},
    b => sub{empty(2)},
  } );
cmpthese $r;


* This source code was highlighted with Source Code Highlighter.


В результате нехитрого действа получаем что-то вроде:

Benchmark: running a, b for at least 1 CPU seconds...
     a: 7 wallclock secs ( 0.09 usr 0.96 sys + 1.93 cusr 3.45 csys = 6.43 CPU) @ 278.69/s (n=1792)
     b: 2 wallclock secs ( 1.11 usr + 0.01 sys = 1.12 CPU) @ 2730666.07/s (n=3058346)
    Rate    a    b
a   279/s   --  -100%
b 2730666/s 979709%   --

* This source code was highlighted with Source Code Highlighter.


Отлично, значит цикл создания потока и его обслуживание дает нам макимальную производительность 278.69/s. Значит любое вычисление, выполняемое быстрее мы считаем сами, а все более громоздкое — отдаем детям!
Стоит почаще пользоваться бенчмарком там, где цифры позволяют сделать выводы и принять правильное решение.
Tags:
Hubs:
-8
Comments10

Articles

Change theme settings