2010-06-08 7 views
9

Parece que Linux no implementa pthread_suspend y continúa, pero realmente lo necesito.linux pthread_suspend

He intentado cond_wait, pero es demasiado lento. El trabajo que se enhebra se ejecuta principalmente en 50us pero ocasionalmente ejecuta más de 500ms. El problema con cond_wait es doble. El bloqueo de exclusión mutua está tomando tiempos comparables a las ejecuciones de micro segundos y no necesito bloqueo. En segundo lugar, tengo muchos hilos de trabajo y realmente no quiero hacer N variables de condición cuando deben ser despertados.

Sé exactamente qué hilo está esperando para qué trabajo y podría simplemente pthread_continue ese hilo. Un hilo sabe cuándo no hay más trabajo y puede pthread_suspend fácilmente. Esto no usaría bloqueo, evitaría la estampida y sería más rápido. El problema es ... no pthread_suspend o _continue.

¿Alguna idea?

+0

¿Distribuir grandes trozos de trabajo a los hilos, de modo que el costo de bloqueo se convierta en un menor% de sobrecarga? (¿Los hilos pasan más tiempo trabajando y menos tiempo delegando el trabajo?) – Thanatos

+0

El trabajo es grande ... a veces. No se puede decir hasta que lo intentes. Y despaché el trabajo de una manera que no necesita bloqueo en absoluto ... excepto que no he descubierto la forma óptima de bajo costo para suspender y activar los hilos sin bloquear ... cond_wait bloquea un mutex para cada hilo que se despierta Tampoco te permite despertar solo un hilo. Bueno, podría hacer una condición para cada hilo ... argh ... Debe haber una mejor manera. cond_wait parece adecuado para un hilo gui de usuario, pero no para transacciones de alta velocidad. – johnnycrash

+0

Voy a ver el código fuente mañana para cond_wait, así como probar la señal y los métodos de tubería vs cond wait. – johnnycrash

Respuesta

7

Haga que el subproceso espere una señal específica.

Utilice pthread_sigmask y sigwait.

+0

+1 por una respuesta prometedora . Voy a probar esto esta noche y te daré la respuesta si funciona. ¡Gracias! – johnnycrash

+0

Se olvidó de mencionar que DEBE usar 'pthread_kill' para señalar un hilo específico, de lo contrario no puede predecir qué hilo se va a reanudar. – jweyrich

+3

Realizamos pruebas con este método y resulta que pudimos dormir y despertar hilos 40 veces más rápido que utilizando un pthread_cond_wait. – johnnycrash

0

Me parece que una solución así (es decir, usar "pthread_suspend" y "pthread_continue") es inevitablemente atrevido.

Puede transcurrir un tiempo arbitrario entre el trabajo de finalización del subproceso de trabajo y la decisión de suspenderse, y la suspensión realmente se produce. Si el hilo principal decide durante ese tiempo que el subproceso de trabajo debe volver a funcionar, el "continuar" no tendrá ningún efecto y el subproceso de trabajo se suspenderá independientemente.

(Tenga en cuenta que esto no se aplica a los métodos de suspensión que permiten el "continuar" en cola, como los métodos sigwait() y read() mencionados en otras respuestas).

+0

Tenga en cuenta que las señales están en cola (al menos en NPTL). – jweyrich

+2

@jweyrich: Sí, puedes hacerlo con señales, ya que 'sigwait()' efectivamente hace un desbloqueo-espera-bloque atómico. – caf

+0

Cuando el despachador agrega trabajo a la cola de trabajo circular, comprobará la cola suspendida circular correspondiente. Un hilo suspendido en el mismo índice que el trabajo se despertará. El hilo de vigilia borra su bandera suspendida. El despachador escaneará de vez en cuando la cola suspendida buscando hilos que no se hayan despertado (la carrera) y los señalice nuevamente. Al final del procesamiento, es necesario repetir el escaneo suspendido (quizás con un descanso de 1 ms) hasta que todos los hilos se activen y completen. Como la condición de carrera es rara, estimo que 1/100 transacciones necesitarán el escaneo adicional al final. – johnnycrash

2

Haga que los hilos bloqueen en una lectura de tubería. Luego envíe los datos a través de la tubería. Los hilos se despertarán como resultado de la llegada de los datos que necesitan procesar. Si los datos son muy grandes, solo envíe un puntero a través de la tubería.

Si necesita datos específicos para hilos específicos, necesita una tubería por hilo. Si cualquier subproceso puede procesar cualquier información, todos los subprocesos pueden bloquearse en el mismo conducto y despertarán la operación por turnos.

0

Puede ser una opción de tratar pthread_cancel pero tenga cuidado si los bloqueos a ser liberados, Lea la página de manual para identificar cancelar estado

0

¿Por qué te importa por cuál de ellos hace el trabajo? Parece que se diseñó en una esquina y ahora necesita un truco para salir de ella. Si permites que el hilo que ya se estaba ejecutando haga el trabajo, no necesitarías este truco, y necesitarías menos interruptores de contexto también.

+0

Hay un grupo de hilos. También hay una lista de subprocesos que están esperando que finalice el trabajo o están inactivos. Si el nuevo elemento de trabajo resulta ser una dependencia para un hilo en espera, lo despierto; de lo contrario, me despierto un hilo inactivo. La señal me permite dirigirme a un hilo que duerme en particular, o al primer hilo inactivo. Lancé mi propia cola de trabajo que usaba átomos en lugar de mutexes y variables de condición. Esto mantuvo la sobrecarga lo suficientemente baja como para mantener el rendimiento incluso si los elementos de trabajo tomaron microsegundos. Solo necesitaba poder dormir un hilo ocasionalmente como un mutex o cv. – johnnycrash

+0

@johnnycrash Esto suena como un mal diseño. ¿Por qué tener un hilo específico esperando algo específico? Puede esperar que ocurra X antes de hacer Y sin tener un hilo en espera. Cuando sucede X, entonces arregla para que * cualquier * hilo pueda hacer Y. Tu diseño te obliga a resolver el problema de despertar hilos específicos y luego fuerza cambios de contexto adicionales y penalizaciones del programador/caché porque ese hilo puede ser ineficiente para ejecutarse en ese momento . –