2009-08-03 11 views
18
#include <stdio.h> 

int main() { 
    while(!DONE) { 
    /* check for stuff */ 
    } 
    return 0; 
} 

La muestra de código anterior usa 100% de CPU hasta que DONE sea verdadero. ¿Cómo puedo implementar un programa que se repite y solo finaliza cuando se HACE, pero que no usa 100% de CPU? Los idiomas modernos usan algo así como App.ProcessMessages o algo así para darle al sistema operativo el control por el momento y luego regresar al ciclo.C Lazo principal sin 100% CPU

Soy nuevo en C, obviamente, ... con lo último en GCC, Linux y Windows (una solución portátil sería genial!)

+8

Debe utilizar un objeto de sincronización, uno que se puede esperar hasta que se convierte en una señal, de esa manera no se consumen CPU en absoluto. –

+2

¿Qué es 'DONE' y qué causará que sea distinto de cero? Presumiblemente, tiene sentido continuar procesando hasta que el 'verificar cosas' evalúe algo que establece que DONE no sea cero. –

+0

Lasse V. Karlsen: Su solución parece tener sentido (probablemente tenga mucho sentido, pero no tengo ese conocimiento). ¿Podrías por favor elaborar? ¿Debo investigar los hilos? (un ejemplo sería bueno) Charles Bailey: DONE debería ser un int (hecho en lugar de DONE) y se establecería en 1 cuando el usuario optó por salir de la aplicación, por ejemplo. Lo siento si no puedo explicarme lo suficientemente bien ... – pwseo

Respuesta

16

Depende de lo que quieras hacer dentro de este ciclo.

Si está esperando dentro del bucle (es decir, si presiona el botón {hacer algo}, su mecanismo desperdiciará los recursos del sistema sin dar nada a cambio. Un procesador más rápido solo hará más bucles. Esto se puede resolver esperando eventos No simplemente duerma, pero preferiblemente es un evento que desencadena que se pueda hacer algo significativo. Por ejemplo, una operación de archivo (stdin también es un archivo) sería un mecanismo portátil. Esto dará paso a otras aplicaciones hasta que los datos estén disponibles. más específica que puede ser necesario para sumergirse en los semáforos o señales que son a menudo depende del sistema operativo. una capa de abstracción puede resolver esto.

Si usted está haciendo algo útil (es decir, el procesamiento de una gran cantidad de datos), entonces el 100% de la carga de la CPU solo significa que el procesador es nosotros ed de la manera más eficiente. Puede confiar en el sistema operativo para dar paso a otras tareas y posiblemente de mayor prioridad.

El uso de una función como sleep reducirá el uso de la CPU, pero su aplicación será más lenta. Requerirá una compensación entre el rendimiento aceptable y la carga de la CPU. La velocidad máxima de ejecución estará definida por su parámetro de suspensión, y no por la velocidad de la CPU. Además, si la potencia es una preocupación (es decir, el tiempo de vida útil de la batería), entonces esto requerirá que la CPU se active (final del período de reposo) sin que haya que trabajar; es decir, un desperdicio diferente de los recursos del sistema.

+0

Supongo que tendré que aprender los semáforos y señales y luego ¿Alguna sugerencia específica sobre eso? :) – pwseo

+2

¿Qué tipo de procesamiento se encuentra dentro del ciclo principal? Mensajes, señales, semáforos están más relacionados con el sistema operativo que el idioma subyacente. Por ejemplo, http://www.ibm.com/developerworks/eserver/library/es-win32linux-sem.html muestra cómo se manejan los semáforos en Windows en comparación con Linux. Si necesita admitir ambos, puede usar POSIX (que es opcional para Windows, es decir, en cygwin) o poner el código en un módulo dependiente de la plataforma que cree para cada sistema operativo. – Adriaan

1

uso

sueño (int milisegundos)

+3

El argumento para dormir es en realidad una cantidad de segundos, no milisegundos. –

+1

Creo que en realidad depende del sistema operativo ... mientras tienes razón en que el parámetro está en Segundos bajo Unix/Linux/* BSD, creo que recuerdo que era milisegundos en Windows ... Han pasado años, así que pude estar equivocado ... – Nicolas

+5

sleep() lleva varios segundos. usleep() (BSD y POSIX) lleva microsegundos. nanosleep() (POSIX también) tarda nanosegundos. – qrdl

3

Lo exactamente ¿estás buscando?

Si usted está comprobando algo volátil que se cambió por el hardware o en otro proceso, simplemente llame sleep en su bucle.

Si está esperando un descriptor de archivo o un descriptor de socket de red, querrá usar select o poll en su ciclo para esperar a que el descriptor tenga los datos listos para el consumo.

0

Uso yield().

+0

Esto no es portátil, ya que no está definido ni por el estándar C ni por POSIX. –

+1

¿Eso no le daría más tiempo a otros procesos, sin dejar de consumir todo el tiempo que otros procesos no consumen? – liori

0

Si estoy adivinar correctamente (no sé sobre él), el equivalente de App.ProcessMessages está haciendo el bloqueo de IO. Y como no conozco ninguna implementación de C en el sistema operativo multitarea que utiliza encuestas, cualquier CIO estándar debería ser seguro.

5

Sus dos opciones serían de votación, y algún tipo de notificación de eventos.

sondeo sería más fácil de programar - básicamente tienes tu sueño hilo por un corto tiempo cada pasada a través del lazo. Esto libera el procesador a otras tareas. La desventaja es que habrá un retraso en el código de "verificación de cosas", por lo que si duerme un segundo, es posible que transcurra un segundo antes de que el código detecte la condición. Su código aquí será fácil de portar.

La otra opción es esperar en un caso POSIX condicional, o Windows, o algo por el estilo. No solo se cambiará este código, sino que las "cosas que está comprobando" necesitarán activar la bandera para indicar que ya está hecho. Este sería un código un poco menos portátil, aunque probablemente haya bibliotecas para abstraer la plataforma. Pero obtendrá resultados inmediatos para el evento, y no perderá tiempo de procesador para buscar cosas que no están allí.

+1

+1 para sugerir el uso de la sincronización POSIX. –

9

usted tiene varias opciones:

  1. Uso del sueño() para forzar el proceso de suspender periódicamente y permitir que otro proceso para utilizar la CPU
  2. Ejecutar a un nivel de prioridad inferior - lo que provocará que el sistema operativo Asigne menos tiempo de CPU
  3. Utilice un mutex u otro objeto de sincronización para detectar cuándo hay trabajo disponible, lo que evitará que el proceso consuma tiempo de CPU a menos que realmente esté trabajando
  4. Si obtiene trabajo más rápido de lo que puede procesarlo - Puede que aún necesites Busque algún tipo de modelo de sueño/prioridad para evitar consumir completamente la CPU.

La opción n. ° 2 puede ser difícil de hacer en una plataforma/sistema operativo neutral. Su mejor apuesta es iniciar el proceso y cambiar su prioridad en el entorno de tiempo de ejecución.

0

En Windows, puede utilizar Sleep (int milisegundos), definido en windows.h.

2

Si entendí bien, dijiste en los comentarios que DONE se puede cambiar desde otros hilos. Si es así, las variables de condición tienen sentido. Con pthreads, uno haría:

En el hilo que espera:

pthread_mutex_lock(&mutex); 
while (!DONE) { 
    pthread_cond_wait(&cond, &mutex); 
} 
pthread_mutex_unlock(&mutex); 

En otros hilos, cuando se hace se cambia:

pthread_mutex_lock(&mutex); 
DONE = 1; 
pthread_cond_signal(&cond); 
pthread_mutex_unlock(&mutex); 
+0

Puedes desbloquear un hilo de otro hilo? – user457015

Cuestiones relacionadas