Veo que la pregunta se ha reactivado con una recompensa, ahora preguntando cuáles son los usos prácticos yield
. Daré un ejemplo de mi experiencia.
Como sabemos, yield
obliga al subproceso que realiza la llamada a abandonar el procesador en el que se está ejecutando para que se pueda programar la ejecución de otro subproceso. Esto es útil cuando el hilo actual ha terminado su trabajo por ahora pero quiere volver rápidamente al frente de la cola y verificar si alguna condición ha cambiado. ¿En qué se diferencia de una variable de condición? yield
permite que el hilo vuelva mucho más rápido a un estado de ejecución. Cuando se espera una variable de condición, el subproceso se suspende y debe esperar a que un subproceso diferente indique que debe continuar.yield
básicamente dice "permitir que se ejecute un hilo diferente, pero permitirme volver al trabajo muy pronto, ya que espero que algo cambie en mi estado muy, muy rápidamente". Esto sugiere un giro ocupado, donde una condición puede cambiar rápidamente pero suspender el hilo incurriría en un gran impacto en el rendimiento.
Pero basta de balbucear, aquí hay un ejemplo concreto: el patrón paralelo de frente de onda. Un ejemplo básico de este problema es calcular las "islas" individuales de 1 en una matriz bidimensional llena de 0 y 1. Una "isla" es un grupo de celdas adyacentes entre sí, ya sea vertical u horizontalmente:
1 0 0 0
1 1 0 0
0 0 0 1
0 0 1 1
0 0 1 1
Aquí tenemos dos islas de 1: arriba a la izquierda y abajo a la derecha.
Una solución simple es hacer una primera pasada sobre toda la matriz y reemplazar los valores de 1 con un contador incremental de modo que al final cada 1 se reemplaza con su número de secuencia en el orden principal de la fila:
1 0 0 0
2 3 0 0
0 0 0 4
0 0 5 6
0 0 7 8
En el siguiente paso, cada valor se reemplaza por el mínimo entre él y los valores de sus vecinos:
1 0 0 0
1 1 0 0
0 0 0 4
0 0 4 4
0 0 4 4
Ahora podemos determinar fácilmente que tenemos dos islas.
La parte que queremos ejecutar en paralelo es el paso donde calculamos los mínimos. Sin entrar en demasiados detalles, cada hilo obtiene filas de manera intercalada y se basa en los valores calculados por el hilo que procesa la fila anterior. Por lo tanto, cada hilo debe retrasarse ligeramente con respecto al hilo que procesa la línea anterior, pero también debe mantenerse al día dentro de un tiempo razonable. En este documento, presento más detalles y una implementación . Tenga en cuenta el uso de sleep(0)
que es más o menos el equivalente en C de yield
.
En este caso yield
se utilizó para forzar a cada hilo a hacer una pausa, pero dado que el proceso del hilo de la fila adyacente avanzaría muy rápidamente mientras tanto, una variable de condición resultaría una elección desastrosa.
Como puede ver, yield
es una optimización bastante fina. Usarlo en el lugar incorrecto, por ejemplo, esperar en una condición que rara vez cambia, causará un uso excesivo de la CPU.
Perdón por el largo parloteo, espero haberme aclarado.