¿Cómo monitorear la utilización de la CPU usando la función de reloj POSIX () durante el tiempo de ejecución?

¿Existe algún método confiable para que un programa pueda medir la utilización de su CPU durante su tiempo de ejecución?

Probablemente tenga que usar un POSIX reloj() funcionar desde tiempo.h. La idea es primero usar algunos milisegundos para establecer una carga inactiva de la CPU (paso A), luego la carga completa de la CPU (paso B), luego iniciar un programa y llamar a clock () constantemente. Por lo tanto, puedo calcular la utilización de la CPU en relación con un calculado en el paso A y el paso B para monitorear la utilización de la CPU en el porcentaje. Supongo que se ignoran todos los demás procesos en segundo plano.

Sin embargo, no estoy seguro, ¿cómo implementar estos pasos A y B, digamos las funciones idle () y full_load () usando solo C89 y POSIX?

preguntado el 10 de mayo de 11 a las 13:05

¿Está midiendo la utilización de la CPU del proceso en el que se encuentra o un proceso separado? -

@ Spudd86: mi propio proceso -

3 Respuestas

Cuando dice "full_load" y solo necesita una única CPU o núcleo virtual bajo carga, un simple bucle cerrado será suficiente. Por supuesto, no usará todos los transistores en el chip (es decir, no estamos hablando de una prueba de quemado para "carga completa"), pero lo hará, durante el intervalo de tiempo programado que recibe de la CPU. , use todos los ciclos de reloj disponibles sin llamadas al sistema que cederían el control al kernel y posiblemente causarían que el hilo en ejecución se reprogramara para más adelante. También puede utilizar una alarma con un gestor de señales para salir del bucle. Entonces eso le permitiría ejecutar el ciclo durante aproximadamente un segundo de tiempo de ejecución (las alarmas no son exactamente precisas en el tiempo ... están cerca, pero no en el ciclo del reloj).

Además, para la parte de carga "inactiva", puede hacer lo mismo, pero utilizando un sigsuspend() en lugar de un bucle cerrado, esperaría a que se activara la alarma.

Entonces, su código podría tener un aspecto similar al siguiente:

#include <signal.h>
#include <unistd.h>
#include <time.h>
#include <stdio.h>

static sig_atomic_t alarm_flag = 1;

void alarm_handler(int arg)
{
    alarm_flag = 0;
}

clock_t idle()
{
    //setup the alarm flag
    alarm_flag = 1;

    //setup the signal masks
    sigset_t old_signal_set;
    sigset_t new_signal_set;

    sigemptyset(&old_signal_set);
    sigemptyset(&new_signal_set);

    //block the alarm signal
    sigaddset(&new_signal_set, SIGALRM);
    sigprocmask(SIG_BLOCK, &new_signal_set, &old_signal_set);

    //setup the alarm
    alarm(1);

    clock_t time_before = clock();

    //sit idle while we wait for the alarm to go off
    while(alarm_flag)
        sigsuspend(&old_signal_set);

    clock_t time_after = clock();

    //restore the old signal mask
    sigprocmask(SIG_SETMASK, &old_signal_set, NULL);

    return time_after - time_before;
}

clock_t full_load()
{
    //set the alarm signal
    alarm_flag = 1;

    //set the 1-second alarm
    alarm(1);

    clock_t time_before = clock();

    //loop until the alarm goes off
    while(alarm_flag);

    clock_t time_after = clock();

    return time_after - time_before;
}

int main()
{
    //setup the signal handler for the alarm
    sigset(SIGALRM, alarm_handler);

    //call the functions
    clock_t idle_time = idle();
    clock_t load_time = full_load();

    //... do whatever else you need to-do with this info
    printf("Idle Time: %d\n", (int)idle_time);
    printf("Load Time: %d\n", (int)load_time);

    return 0;
}

Tenga en cuenta que de acuerdo con el estándar POSIX, debe haber 1 millón de relojes por segundo como base de tiempo para el clock_t value, por lo que debería ver el número devuelto para "full_load" que está cerca de ese número, ya que vamos a "full-load" durante aproximadamente un segundo. La carga inactiva debe ser muy pequeña (por supuesto). Estos son los números que generé en mi Mac Pro:

Idle Time: 31
Load Time: 1000099

Así que eso parece estar en línea con lo que está buscando en cuanto a saber cuántos ciclos de reloj puede ver que regresan de clock(). Por supuesto, lo ejecutaría varias veces y tomaría un promedio para obtener un mejor indicador de la varianza que podría ver.

contestado el 10 de mayo de 11 a las 18:05

Pensé que esto está cubierto por CLOCK_VIRTUAL (BSD / HP-UX) o CLOCK_PROCESS_CPUTIME_ID en Linux para clock_gettime (2).

contestado el 10 de mayo de 11 a las 21:05

no te refieres CLOCK_PROCESS_CPUTIME_ID - Spudd86

No, me refiero a CLOCK_VIRTUAL. Aparentemente, solo puede contar con CLOCK_REALTIME según SusV2 y estaba mirando BSD y elegí el incorrecto. Linux usa su constante, HP-UX también usa CLOCK_VIRTUAL. Editando respuesta. - miel

No especifica la versión de POSIX, pero si está utilizando C89, debe ser bastante antigua. POSIX.1-2001 también conocido como SUSv3 requiere C99 y también hay POSIX.1-2008.

La calibración parece innecesaria; simplemente compare los valores devueltos al tiempo monótono (mejor, pero puede que no esté disponible) o al tiempo del reloj de pared. Para clock(), utilizar el CLOCKS_PER_SEC define (se garantiza que será un millón si el sistema admite la opción XSI, pero no si es solo POSIX).

Imagine getrusage() en lugar de clock() para mayor precisión y flexibilidad.

La función getrusage() estaba bajo la opción XSI en versiones anteriores de POSIX; el historial de cambios dice que se introdujo en el Issue 4 Versión 2 (SUSv1) y se movió a la base en el Issue 5 (SUSv2), pero todavía hay marcas XSI en él. En cualquier caso, es bastante común ya que es una función 4.2BSD.

Otra opción es la times() función.

contestado el 11 de mayo de 11 a las 01:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.