2010-01-17 16 views
8

He escrito una biblioteca C++ que realiza un trabajo de CPU muy pesado (todo cálculos matemáticos y cálculos) y si se deja en sus propios dispositivos, consumirá fácilmente el 100% de todos los recursos de CPU disponibles (también es multiproceso al número de núcleos lógicos disponibles en la máquina).¿La mejor manera de ralentizar un hilo? Está utilizando el modo de suspensión() ¿OK?

Como tal, tengo una llamada de retorno dentro del bucle principal de cálculo que el software usando la biblioteca se supone que llamar:

while(true) 
{ 
    //do math here 
    callback(percent_complete); 
} 

En la devolución de llamada, el cliente llama sueño (x) para reducir la velocidad del hilo.

Originalmente, el código del cliente era una llamada fija de Suspensión (100), pero esto conducía a un mal rendimiento no confiable porque algunas máquinas terminan las operaciones matemáticas más rápido que otras, pero la suspensión es la misma en todas las máquinas. Entonces ahora el cliente verifica la hora del sistema, y ​​si ha pasado más de 1 segundo (lo cual == varias iteraciones), dormirá durante medio segundo.

¿Es esta una forma aceptable de ralentizar un hilo? ¿Debo usar un semáforo/mutex en lugar de Sleep() para maximizar el rendimiento? ¿Está bien dormir x milisegundos por cada 1 segundo de procesamiento o hay algo mal que no estoy notando?

La razón por la que pregunto es que la máquina aún se empantana a pesar de que el técnico de tareas muestra que el proceso ocupa ~ 10% de la CPU. Ya he explorado el disco duro y la contención de la memoria en vano, así que ahora me pregunto si la forma en que estoy ralentizando el hilo está causando este problema.

Gracias!

Respuesta

2

Dormir debería estar bien para estrangular una aplicación, que según sus comentarios es lo que está buscando. Tal vez solo necesites ser más preciso por cuánto tiempo duermes.

El único software en el que utilizo una función como esta es el BOINC client. No sé qué mecanismo utiliza, pero es de código abierto y multiplataforma, así que sírvete.

Tiene una opción de configuración ("límite de uso de CPU a X%"). La forma en que esperaba implementar eso es usar API dependientes de la plataforma como clock() o GetSystemTimes(), y comparar el tiempo del procesador con el tiempo del reloj de pared transcurrido. Haga un poco de trabajo real, compruebe si está por encima o por debajo de la media, y si está por encima del nivel de sueño por un tiempo para volver a estar bajo.

El cliente BOINC juega muy bien con las prioridades, y no causa ningún problema de rendimiento para otras aplicaciones, incluso al 100% de CPU máxima. La razón por la que uso el acelerador es que, de lo contrario, el cliente ejecuta la CPU a toda máquina y aumenta la velocidad y el ruido del ventilador. Así que lo ejecuto en el nivel donde el ventilador se mantiene en silencio. Con un mejor enfriamiento tal vez no lo necesite :-)

+0

En Linux, si ejecuta su proceso con un nivel agradable superior, el sistema operativo mantendrá bajo el reloj de la CPU, suponiendo que su hardware admita la escala de velocidad de la CPU. Esto mantendrá la potencia, el calor y el ruido bajos sin estrangulamiento artificial. – karunski

+0

Dulce. Cambiar a Linux por completo es una opción que considero constantemente y hasta el momento siempre rechazo ... –

23

¿Por qué no utiliza una prioridad más baja para los hilos de cálculo? Esto garantizará que otros hilos estén programados y permita que los hilos de cálculo se ejecuten lo más rápido posible si no es necesario que se ejecuten otros hilos.

+4

En la práctica, eso no es muy confiable en Windows. He portado la biblioteca a OS X y funciona como un sueño con una prioridad más baja, pero en Windows todavía causará problemas. También otra cosa: con fines de marketing/soporte técnico, nos parece una mala idea que el software ocupe más del 20% de la CPU en el administrador de tareas, o si recibe algunas quejas locas y comentarios extravagantes sobre su software matando Rendimiento de PC ¡La gente ve un 50% de uso de la CPU y el pánico! –

+1

No puedo decir por qué su puerto se comportó así. En mi experiencia, la programación funciona bien en Windows. En cualquier caso, dada la pregunta, creo que se resuelve mejor usando prioridades y dejando la programación en el sistema operativo. –

+11

Computer Guru, las prioridades de subprocesos funcionan con bastante fiabilidad en Windows. Sin embargo, si realiza un montón de E/S (no importa si es directo o causado por la búsqueda de memoria), también puede reducir su prioridad de E/S. Ver SetThreadPriority y THREAD_MODE_BACKGROUND_BEGIN. – avakar

0

Eche un vistazo a cpulimit. Envía SIGSTOP y SIGCONT según sea necesario para mantener un proceso por debajo de un porcentaje de uso de CPU determinado.

Aún así, WTF en "quejas locas y comentarios extravagantes sobre su software matando el rendimiento de la PC". Sería más probable que me quejara de que tu software era lento y no aprovechaba al máximo mi hardware, pero no soy tu cliente.

Editar: en Windows, SuspendThread() y ResumeThread() probablemente puede producir un comportamiento similar.

0

Otro método, aunque no tan elaborado, podría ser cronometrar una iteración y dejar que el subproceso duerma durante (x * t) milisegundos antes de la siguiente iteración donde t es el tiempo de milisegundos para una iteración yx es la fracción de tiempo de suspensión elegida (entre 0 y 1).

4

¿Qué hay de malo con la CPU al 100%? Eso es lo que debes esforzarte, no tratar de evitar. Estos cálculos matemáticos son importantes, ¿no? A menos que esté tratando de evitar acaparar algún otro recurso no administrado explícitamente por el sistema operativo (un mutex, el disco, etc.) y utilizado por el hilo principal, generalmente es una mala idea tratar de reducir la velocidad del hilo. ¿Qué pasa con los sistemas multinúcleo (que serán casi todos los sistemas, en adelante)? Estarás ralentizando un hilo sin ninguna razón.

El sistema operativo tiene un concepto de un cuanto de hilo. Se ocupará de garantizar que no se muera de hambre en su sistema. Y, como mencioné anteriormente, en los sistemas multinúcleo conectar un hilo en una CPU no afecta en absoluto el rendimiento de otros hilos en otros núcleos.

También veo en otro comentario que este hilo también está haciendo una gran cantidad de E/S de disco: estas operaciones ya harán que su hilo ceda mientras espera los resultados, por lo que el sueño no hará nada.

En general, si llamas a Sleep (x), hay algo mal/flojo con tu diseño, y si x == 0, te estás abriendo a live locks (el hilo que llama a Sleep (0) en realidad se puede reprogramar de inmediato, convirtiéndolo en un noop).

+0

Quizás un poco de contexto ayude: la matemática es para calcular la diferencia mínima entre dos archivos para un programa de respaldo. Un programa de copia de seguridad "configúrelo y olvídese" no debería tomar 100% de CPU, mientras que un programa de "diff de archivos" de un solo propósito debería hacerlo. Ahí radica la clave de este diseño :) –

+1

Ah, ya veo; esa es exactamente la razón por la que se inventaron las prioridades de procesos e IO. Debería hacer eso y dejar que el programador del sistema operativo se encargue de todo. Sáltate las Duermen. –

+3

Creo que Computer Guru está diciendo que su programa de copia de seguridad no debe tomar 100% de CPU, * incluso si el sistema está completamente inactivo *. karunski dice que Linux logra esto simplemente asignando una prioridad suficientemente baja, pero no es qué prioridad se define en POSIX. Hay una diferencia entre la prioridad relativa entre los procesos ("no lo hagas rápido si se muere de hambre algo importante") y lo que supongo que podrías llamar prioridad absoluta ("no hagas esto rápido, nunca"). –

Cuestiones relacionadas