2011-06-15 18 views
10

Tengo algunas preguntas sobre la función sched_yield porque veo que no está funcionando como estaba previsto en mi código. Muchas veces veo que el mismo hilo se ejecuta una y otra vez, incluso en presencia de otros hilos, cuando trato de ceder llamando al sched_yield.Comportamiento de sched_yield

También si tengo multinúcleos, será sched_yield rendimiento para hilos que se ejecutan en todos los núcleos, o solo un núcleo. Digamos, por ejemplo, que los hilos 1, 2 y 3 se ejecutan en el núcleo 1 y los hilos 4, 5 y 6 en el núcleo 2 y si se llama al sched_yield desde el hilo 2, será reemplazado solo por el hilo 1 y 3 o 1, 3. 4, 5 y 6 son todos posibles? Lo estoy preguntando porque en .Net Thread.Yield solo cede a los hilos que se ejecutan en el mismo núcleo/procesador.

+3

¿Cómo piensas que funcione? TBH, realmente no entiendo por qué esta llamada es útil, ya sea en POSIX/*** X, Windows o cualquier multitarea preventiva. Si cede su hilo, no tiene garantía de que el SO no lo cargue nuevamente de inmediato, quizás en el mismo núcleo si los otros hilos no están listos en ese momento. Si la versión de .NET tiene una afinidad con el procesador (y sí, busqué en Google y parece que sí), eso es aún más extraño. ¿Supongo que podría mejorar el rendimiento con las fibras? –

+2

@MartinJames es una llamada útil cuando tienes más procesos/subprocesos ejecutables que núcleos y quieres dar a los otros subprocesos/procesos la posibilidad de progresar (p. Ej., Un subproceso acaba de otorgar otro subproceso y el costo del el primer hilo que se va a dormir para esperar al finalizar es más que el costo de (el segundo hilo hace el "algo" + el primer hilo comprobando que se ha realizado). – jhfrontz

Respuesta

3

http://www.kernel.org/doc/man-pages/online/pages/man2/sched_yield.2.html

sched_yield() hace que el subproceso de llamada a renunciar a la CPU. El hilo es movido al final de la cola para su prioridad estática y un nuevo hilo obtiene ejecutar .

Si el subproceso de llamada es el único subproceso en la lista de prioridad más alta en ese momento , continuará ejecutándose después de una llamada a sched_yield().

El sched_yield no es una llamada .Net y el modelo de subprocesamiento/proceso es diferente a. El programador de Windows/.NET no es lo mismo que el programador de Linux. Linux incluso tiene varios posibles planificadores.

Por lo tanto, sus expectativas sobre sched_yield son incorrectas.

Si desea controlar cómo se ejecutan los subprocesos, puede vincular cada subproceso a la CPU. Entonces, los hilos se ejecutarán solo en la CPU enlazada. Si va a tener varios hilos, vinculados a la misma CPU, el uso de sched_yield MAY cambia a otro hilo que está enlazado a la CPU actual y está listo para ejecutarse.

También puede ser una mala idea usar varios subprocesos por CPU si cada subproceso desea hacer un montón de trabajo intensivo de CPU.

Si desea obtener un control total, cómo se ejecutan los subprocesos, puede utilizar subprocesos RealTime. http://www.linuxjournal.com/magazine/real-time-linux-kernel-scheduler - Políticas de SCHED_FIFO y SCHED_RR RT.

-2

¿Por qué querría renunciar a la CPU? Bueno ...

Estoy solucionando un problema en el código del cliente. Básicamente, tienen una estructura común que contiene información:

  1. cuántas monedas en custodia - devolverlos
  2. cuántas cuentas en custodia - uno vuelva

Los anteriores son en el proceso de la A. el resto del código está en proceso B. El proceso B envía mensajes al proceso A para calcular y devolver el dinero en custodia (esta es una máquina expendedora).Sin entrar en la historia de qué el código está escrito de esta manera, la secuencia de código original es:

(Proceso B) enviar mensaje RETURN_ESCROWED_BILLS para procesar un mensaje envío MONEDAS RETURN_ESCROWED para procesar una cero fuera de lo común estructura

Esta es ejecutado como:

(Procedimiento B): enviar los mensajes; ponga a cero la estructura;

(más tarde .. Proceso A): obtener los mensajes; todos los campos en la estructura común son 0; nada que hacer;

oops ... el dinero aún está en custodia, pero el proceso Un código ha perdido ese conocimiento. Lo que realmente se necesita (que no sea una reestructuración masivadel código) es:

(Procedimiento B): enviar los mensajes; ceden la CPU;

(Proceso A): determinar el dinero depositado y la devolución; ceden la CPU; (podría simplemente ir al final del intervalo de tiempo, no es necesario ningún método especial)

(Proceso B): poner a cero la estructura común;

Cada vez que tenga mensajes IPC y los procesos que envían/​​reciben los mensajes son estrechamente acoplados. la mejor forma de es tener un apretón de manos bidireccional. Sin embargo, hay casos (generalmente como resultado de un diseño pobre o inexistente) en los que debe acoplar estrechamente procesos que realmente se supone que están estrechamente relacionados. Normalmente el rendimiento de la CPU es un truco porque no tiene otra opción. La adición de CPU multinúcleo es una fuente de dolor, especialmente cuando se transfiere de un solo núcleo a un núcleo múltiple.

+1

Esta respuesta es incorrecta. sched_yield() no está destinado a la comunicación entre procesos , ni lo llamará para garantizar que se ejecute otro hilo. Como describió osgx, la idea es ayudar al sistema operativo a programar de manera eficiente. – uli

+0

sí, sched_yield() no es explícito para la comunicación entre procesos, sino que: el hilo de envío debe abandonar el CPU de una manera predecible para permitir que el hilo de recepción realmente tenga la oportunidad de obtener la CPU. Además, ambos procesos están en el mismo nivel de prioridad, y el receptor recibe ead está bloqueando, esperando el mensaje. De lo contrario, hubo una carrera entre cuando la tarea de envío perdió la CPU y la tarea de recepción obtuvo la CPU. Este método era predecible (Ubunto 8) – user2913342