2010-01-06 15 views
7

Estoy haciendo una gran cantidad de búsqueda de archivos basado en un criterio en múltiples iteraciones de mi script de Perl y parece tomar el 100% del tiempo de la CPU. ¿Hay alguna forma de controlar la utilización de la CPU de mi script? Leí en alguna parte sobre poner ciclos de sueño vacíos en mi script. Pero no estoy seguro de cómo hacer esto.¿Controla la utilización de la CPU de una secuencia de comandos perl?

+0

Esto depende de la plataforma. ¿En qué SO se está ejecutando? –

+1

@bish Si no hay otros procesos que necesiten la CPU, ¿por qué debería permitirlo desperdiciar buenos ciclos cuando se pueden aprovechar? – Eli

+0

Estoy ejecutando mis scripts en Windows. Sí, hay otros procesos que también se están ejecutando. Tenía que ser menos molesto con mis guiones. –

Respuesta

10

se podría reducir el proceso de prioridad (de Perl), que le sean asignadas por el sistema operativo: windows o linux

ejemplo para la prioridad más baja:

ventanas

start /LOW perl <myscript> 

Linux

nice +19 perl <myscript> 
+0

Parece la solución más simple. Probaré esto antes que los demás e informaré. –

+0

Esta es una solución fácil pero requiere el conocimiento de los usuarios o crear un script de inicio o un alias. Sin embargo, si usa setpriority(), el código siempre renizará/cambiará la prioridad según lo previsto. El tipo de aplicación y uso debería decidir qué solución elegir. –

3

simplemente dormir:

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

o un poco más de fantasía, hacer N operaciones por ciclo de sueño:

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. 
    } 
} 
+0

Ok. Entiendo la idea Así que tendré que dividir mis tareas en grupos que puedan repetirse. –

5

usted podría utilizar sleep or usleep. Otra cosa que puede hacer es disminuir la prioridad del proceso.

Actualización: Ver setpriority()

+0

La función 'setpriority' de Perl es simplemente un envoltorio alrededor de la llamada al sistema con el mismo nombre. Como tal, es un error fatal llamarlo a plataformas que no lo implementan (por ejemplo, Windows). –

+0

Acabo de confirmar esto. 'setpriority()' no está implementado en Windows. –

7

Una gran manera de mejorar la utilización de la CPU es el uso de mejores algoritmos. No adivine dónde está gastando su código todo el tiempo: use un generador de perfiles. Devel::NYTProf es una herramienta fantástica para esto.

Asegúrese de tener en cuenta Amdahl's law. Por ejemplo, supongamos que parte de su programa utiliza un algoritmo cuadrático y con cierto esfuerzo podría reemplazarlo por uno lineal. ¡Hurra! Pero si el código en cuestión representa solo el 5% del tiempo de ejecución total, su esfuerzo más heroico no puede ser mejor que una pequeña mejora del cinco por ciento. Utilice un generador de perfiles para determinar si hay oportunidades para una mayor aceleración en otros lugares.

No nos diga lo que está buscando, e incluso los algoritmos más conocidos pueden requerir un uso intensivo de la CPU. Tenga en cuenta que el planificador de su sistema operativo se ha escrito, ajustado a mano, probado y reescrito para utilizar los recursos del sistema de manera eficiente. Sí, algunas tareas requieren programadores especializados, pero estos casos son raros, incluso menos si se usa Perl.

No lo tome como una mala señal de que su código está consumiendo CPU. Puede que se sorprenda al saber que uno de los desafíos más difíciles en los sistemas en tiempo real, donde el rendimiento es crucial, es mantener la CPU ocupada en lugar de inactiva.

+0

Mi secuencia de comandos pasa mucho tiempo haciendo tareas menores, como buscar texto en archivos, ejecutar programas externos, capturar y analizar su resultado, en lugar de cualquier algoritmo especializado. En general, estoy de acuerdo con tu opinión. No estoy particularmente preocupado de que mi script esté consumiendo la CPU. Pero más con el hecho de que el uso de esta CPU afecta a otros programas y servicios que se ejecutan en el mismo servidor de Windows. Eso es todo. Una simple prioridad de proceso bajo parece cumplir mi propósito en este momento. Sí, la creación de perfiles es buena a largo plazo. –

+0

Parece una elección inteligente. –

+0

¡Gracias por el consejo en NYTProf! Nota para mí: el único tipo de guía con pasos que pude encontrar hasta ahora es [perlmonks: mod_perl application profiling - Problem] (http://www.perlmonks.org/?node_id=833194) .. ¡Saludos! – sdaau

2

sleep + time + times puede hacer esto.

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; 
} 

(No probado ...) Espolvorear suficientes relax llamadas a través de su código y esto debe ser en promedio a cerca o debajo de tiempo de CPU del 50%.


BSD::Resource puede hacer esto de forma menos invasiva, y es posible que así agarrar Time::HiRes para una mayor precisión.

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); 

(también sin probar ...) En un sistema que soporta, esto debería pedir al sistema operativo para señalar que cada $interval segundos de tiempo de CPU, momento en que se restableció el contador y el sueño. Esto no debería requerir ningún cambio en el resto de tu código.

+0

Tiene que ser probado. Pero parece una solución interesante para controlar generalmente el uso de CPU con números. –

2

¿Su script realmente está haciendo cosas todo el tiempo? Por ejemplo, si calcula un conjunto mandelbrot, tendrá bucles que consumen CPU, pero están procesando activamente datos todo el tiempo.

O tienes bucles en el que están a la espera de más datos de proceso:

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

En el primer caso, el establecimiento de prioridades es probablemente la mejor solución. Se ralentizará el cálculo, pero solo tanto como sea necesario para dar servicio a cualquier otro proceso en el sistema.

En el segundo caso, puede mejorar drásticamente la utilización de la CPU durmiendo durante solo una fracción de segundo.

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

Si usted está tirando de los datos de una fuente que select puede operar en, tanto mejor. Puede organizar que su ciclo se bloquee hasta que los datos estén listos.

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

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

Seleccione trabajos en sockets y manejadores de archivos en sistemas * NIX. En los sistemas Windows, solo puede seleccionar en contra de los sockets.

Cuestiones relacionadas