Tiempo de sueño óptimo en modelos de múltiples productores / consumidores individuales

StackOverflow https://stackoverflow.com/questions/1400605

  •  05-07-2019
  •  | 
  •  

Pregunta

Estoy escribiendo una aplicación que tiene un productor múltiple, un modelo de consumidor único (varios hilos envían mensajes a un solo hilo de escritor de archivos).

Cada subproceso de productor contiene dos colas, una para escribir y otra para que un consumidor lea. Cada ciclo del hilo del consumidor, itera a través de cada productor y bloquea el mutex de ese productor, intercambia las colas, desbloquea y escribe desde la cola que el productor ya no usa.

En el bucle del subproceso del consumidor, duerme durante un período de tiempo designado después de procesar todos los subprocesos del productor. Una cosa que noté de inmediato fue que el tiempo promedio para que un productor escriba algo en la cola y regrese aumentó drásticamente (en 5x) cuando pasé de 1 hilo productor a 2. A medida que se agregan más hilos, este tiempo promedio disminuye hasta el final fuera: no hay mucha diferencia entre el tiempo empleado con 10 productores frente a 15 productores. Esto es presumiblemente porque con más productores para procesar, hay menos contención para el mutex del hilo productor.

Desafortunadamente, tener < 5 productores es un escenario bastante común para la aplicación y me gustaría optimizar el tiempo de sueño para obtener un rendimiento razonable independientemente de cuántos productores existan. Me di cuenta de que al aumentar el tiempo de sueño, puedo obtener un mejor rendimiento para conteos de productores bajos, pero un rendimiento peor para conteos de productores grandes.

¿Alguien más ha encontrado esto, y si es así, cuál fue su solución? He intentado escalar el tiempo de suspensión con el número de subprocesos, pero parece algo específico de la máquina y bastante prueba y error.

¿Fue útil?

Solución

Puede elegir el tiempo de sueño en función del número de productores o incluso hacer que el tiempo de sueño se adapte según algún esquema dinámico. Si el consumidor se despierta y no tiene trabajo, duplique el tiempo de sueño, de lo contrario, reduzca a la mitad. Pero limite el tiempo de sueño a un mínimo y máximo.

De cualquier manera, estás empapelando un tema más fundamental. Dormir y sondear es fácil de acertar y, a veces, es el único enfoque disponible, pero tiene muchos inconvenientes y no es el & "; Correcto &"; manera.

Puede dirigirse en la dirección correcta agregando un semáforo que se incrementa cada vez que un productor agrega un artículo a una cola y disminuye cuando el consumidor procesa un artículo en una cola. El consumidor solo se despertará cuando haya elementos para procesar y lo hará de inmediato.

Sin embargo, sondear las colas puede ser un problema. Puede agregar una nueva cola que se refiera a cualquier cola que tenga elementos. Pero más bien plantea la pregunta de por qué no tiene una sola cola que procesa el consumidor en lugar de una cola por productor. Todo lo demás es igual que suena como el mejor enfoque.

Otros consejos

En lugar de dormir, recomendaría que su consumidor bloquee una condición indicada por los productores. En un sistema compatible con posix, puede hacer que funcione con pthread_cond. Cree una matriz de pthread_cond_t, una para cada productor, luego cree una adicional que se comparta entre ellos. Los productores primero señalan su variable de condición individual y luego la compartida. El consumidor espera en la condición compartida y luego itera sobre los elementos de la matriz, realizando un pthread_cond_timed_wait() en cada elemento de la matriz (use pthread_get_expiration_np() para obtener el tiempo absoluto para & Quot; ahora & Quot; ) Si la espera devuelve 0, entonces ese productor ha escrito datos. El consumidor debe reinicializar las variables de condición antes de esperar nuevamente.

Al usar esperas de bloqueo, minimizará la cantidad de tiempo que el consumidor bloquea innecesariamente a los productores. También podría hacer que esto funcione con semáforos, como se indicó en una respuesta anterior. Los semáforos han simplificado la semántica en comparación con las condiciones, en mi opinión, pero debe tener cuidado de disminuir el semáforo compartido una vez para cada productor que se procesó en cada paso a través del ciclo del consumidor. Las variables de condición tienen la ventaja de que básicamente puede usarlas como semáforos booleanos si las reinicializa después de que se señalen.

Intente encontrar una implementación de una Cola de bloqueo en el lenguaje que utiliza para programar. No más de una cola será suficiente para cualquier número de productores y un consumidor.

Para mí, parece que accidentalmente está introduciendo algo de búfer al hacer que el hilo del consumidor esté ocupado en otro lugar, ya sea durmiendo o haciendo un trabajo real. (la cola actúa como el búfer) Quizás hacer un búfer simple en el lado del productor reducirá su contención.

Parece que su sistema es altamente sensible a la contención de bloqueo entre el productor y el consumidor, pero estoy desconcertado de por qué una operación de intercambio tan simple ocuparía suficiente tiempo de CPU para aparecer en sus estadísticas de ejecución.

¿Puedes mostrar algún código?

editar: ¿tal vez está bloqueando e intercambiando colas incluso cuando no hay trabajo que hacer?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top