Управлять загрузкой ЦП сценария жемчуга?

Я делаю много файла, ищущего на основе критерии в нескольких повторениях из моего сценария Perl, и это, кажется, поднимает 100% процессорного времени. Существует ли способ управлять моей загрузкой ЦП сценария? Я читал где-нибудь о помещении пустых циклов сна в моем сценарии. Но я не уверен, как сделать это.

7
задан Nilesh C 6 January 2010 в 12:28
поделиться

6 ответов

можно снизить приоритет процесса (Perl's), назначенный операционной системой: windows или linux

пример для самого низкого приоритета:

windows

start /LOW  perl <myscript>

linux

nice +19 perl <myscript>
10
ответ дан 6 December 2019 в 06:14
поделиться

Вы можете использовать для сна или сна . Другое, что вы можете сделать, это снизить приоритет процесса.

Обновить: Смотрите setpripriority()

5
ответ дан 6 December 2019 в 06:14
поделиться

Просто спать:

while ($not_done_yet) {
    do_stuff_here();
    sleep 1; # <-- sleep for 1 second.
}

или чуть больше фантазии, делать N операций за цикл сна:

my $op_count = 0;
while ($not_done_yet) {
    do_stuff_here();

    $op_count ++;
    if ($op_count >= 100) {
        $op_count = 0;
        sleep 1; # <-- sleep for 1 second every 100 loops.
    }
}
3
ответ дан 6 December 2019 в 06:14
поделиться

Отличный способ улучшить использование ЦП - это использовать лучше алгоритмы. Не угадайте, на что ваш код тратит все свое время: используйте профилировщик. Devel :: NYTProf - отличный инструмент для этого.

Обязательно помните закон Амдала . Например, предположим, что часть вашей программы использует квадратичный алгоритм и, приложив некоторые усилия, вы можете заменить его линейным. Ура! Но если на рассматриваемый код приходится только 5% от общего времени выполнения, ваши самые героические усилия могут принести не больше, чем крошечное пятипроцентное улучшение. Используйте профилировщик, чтобы определить, доступны ли где-либо возможности для большего ускорения.

Вы не говорите нам, что ищете, и даже самые известные алгоритмы могут сильно загружать процессор. Учтите, что планировщик вашей операционной системы был написан, настроен, протестирован и переписан для эффективного использования системных ресурсов. Да, для некоторых задач требуются специализированные планировщики, но такие случаи редки - даже менее вероятно, если вы используете Perl.

Не воспринимайте это как плохой знак того, что ваш код поглощает процессор. Вы можете быть удивлены, узнав, что одна из самых сложных задач в системах реального времени, где производительность имеет решающее значение, - это поддерживать загруженность ЦП, а не бездействие.

7
ответ дан 6 December 2019 в 06:14
поделиться

Ваш сценарий на самом деле все время что-то делает? Например, если вы вычислить набор мандельброта, то у вас будут циклы, которые потребляют процессор, но активно обрабатывают данные все время.

Или у вас есть циклы, в которых вы ожидаете обработки большего количества данных:

while(1) { 
    process_data() if data_ready();
}

В первом случае, установка приоритета, вероятно, является лучшим решением. Он замедлит вычисления, но только настолько, насколько это необходимо для обслуживания любых других процессов в системе.

Во втором случае можно значительно повысить загрузку процессора, проспав лишь долю секунды.

while(1) { 
    process_data() if data_ready();
    select( undef, undef, undef, 0.1 );
}

Если вы извлекаете данные из источника, на котором выберите , то тем лучше. Можно организовать блокировку цикла до тех пор, пока данные не будут готовы.

use IO::Select;
my $s = IO::Select->new($handle);

while(1) { 
    process_data() if $s->can_read;
}

Выбор работает на сокетах и файловых дескрипторах на системах *NIX. В системах Windows можно выбирать только против сокетов.

2
ответ дан 6 December 2019 в 06:14
поделиться

сна + время + время может вроде как сделать это.

my $base = time;
my $ratio = 0.5;
my $used = 0;
sub relax {
    my $now = time;
    my ($total) = times;
    return if $now - $base < 10 or $total - $used < 5;  # otherwise too imprecise
    my $over = ($total - $used) - $ratio * ($now - $base);
    $base = $now + ($over > 0 && sleep($over));
    $used = $total;
}

(Непроверенные...) Посыпайте достаточно расслабьтесь вызовов по всему вашему коду, и это должно в среднем составлять около или менее 50% процессорного времени.


BSD::Ресурс может делать это менее инвазивно, и вы можете также захватить Время::HiRes для большей точности.

my $base = clock_gettime(CLOCK_MONOTONIC);
my (undef, $hard) = getrlimit(RLIMIT_CPU);
my $interval = 10;
if ($hard != RLIM_INFINITY && $hard < $interval) {$interval = $hard / 2}
my $ratio = 0.5;
$SIG{XCPU} = sub {
    setrlimit(RLIMIT_CPU, $interval, $hard);
    my $now = clock_gettime(CLOCK_MONOTONIC);
    my $over = $interval - $ratio * ($now - $base);
    $base = $now + ($over > 0 && sleep($over));
};
setrlimit(RLIMIT_CPU, $interval, RLIM_INFINITY);

(Также непроверенный...) На системе, которая его поддерживает, это должно просить операционную систему сигнализировать вам каждые $interval секунд процессорного времени, после чего вы сбрасываете счетчик и спите. Это не должно требовать внесения изменений в остальной код.

2
ответ дан 6 December 2019 в 06:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: