Как использовать потоки для замены цикла подпрограммы в perl / pdl - PullRequest
2 голосов
/ 08 сентября 2010

У меня есть очень хорошая подпрограмма perl, написанная как часть модуля perl. Не вдаваясь в подробности, он принимает строку и короткий список в качестве аргументов (часто берется из терминала) и выдает значение (прямо сейчас, всегда с плавающей запятой, но это не всегда так).

Прямо сейчас, часть списка моего аргумента принимает два значения, скажем (val1, val2). Я сохраняю вывод моей подпрограммы для сотен различных значений для val1 и val2, используя циклы for. Каждая итерация занимает почти секунду, поэтому весь этот процесс занимает часы.

Я недавно читал о мистическом (для меня) вычислительном инструменте, называемом «многопоточность», который, очевидно, может заменить циклы с невероятно быстрым временем выполнения. У меня были проблемы с пониманием, что это такое и что они делают, но я думаю, что они как-то связаны с параллельными вычислениями (и я бы хотел, чтобы мой модуль был максимально оптимизирован для параллельных процессоров.)

Если я сохраню все значения, которые я хотел бы передать в val1 в виде списка, скажем @ val1 и то же самое для val2, как я могу использовать эти «потоки» для выполнения моей подпрограммы для каждой комбинации элементов val1 и val2? Кроме того, было бы полезно узнать, как обобщить эту процедуру для подпрограммы, которая также принимает val3, val4 и т. Д.

1 Ответ

6 голосов
/ 08 сентября 2010

Обновление:

Я не использую PDL, поэтому я не знал, что поток в PDL не соответствует в точности понятию потоков, о котором я говорил. См. Потоки PDL и подписи :

Сначала мы должны объяснить, что мы подразумеваем под многопоточностью в контексте PDL, тем более что термин «многопоточность» уже имеет особое значение в компьютерной науке, что лишь частично согласуется с его использованием в PDL.

Тем не менее, я думаю, что приведенное ниже объяснение все еще полезно для вас, так как нужно было бы знать, что такое потоки в обычном смысле, чтобы понять, как отличаются потоки PDL.

Вот запись Threads в Википедии для фона.

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

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

Что касается возможного повышения производительности, рассмотрим следующую программу:

#!/usr/bin/perl

use strict; use warnings;
use threads;

my ($n) = @ARGV;

my @threads = map { threads->create(\&act_busy) } 1 .. $n;

$_->join for @threads;

sub act_busy {
    for (1 .. 10_000_000) {
        my $x = 2 * 2;
    }
}

На моем двухъядерном ноутбуке под управлением Windows XP:

C:\> timethis t.pl 1
TimeThis :  Elapsed Time :  00:00:02.375
C:\> timethis t.pl 2
TimeThis :  Elapsed Time :  00:00:02.515
C:\> timethis t.pl 3
TimeThis :  Elapsed Time :  00:00:03.734
C:\> timethis t.pl 4
TimeThis :  Elapsed Time :  00:00:04.703
...
C:\> timethis t.pl 10
TimeThis :  Elapsed Time :  00:00:11.703

Теперь сравните это с:

#!/usr/bin/perl

use strict; use warnings;

my ($n) = @ARGV;

act_busy() for 1 .. $n;

sub act_busy {
    for (1 .. 10_000_000) {
        my $x = 2 * 2;
    }
}
C:\> timethis s.pl 10
TimeThis :  Elapsed Time :  00:00:22.312
...