2012-05-04 11 views
8

Estoy programando en C++, pero solo estoy usando pthread.h, no boost o C++ 11 threads.¿Cómo debería implementarse un grupo de subprocesos en C?

Así que estoy tratando de usar subprocesos pero basado en una de mis preguntas anteriores (link), esto no parece factible ya que los hilos terminan justo después de la finalización de su tarea, y una de las razones más frecuentes para usar un hilo la implementación de grupo es reducir la sobrecarga de creación de subprocesos reutilizando estos subprocesos para múltiples tareas.

¿Es la única otra forma de implementar esto en C para usar fork() y crear una tubería desde los procesos principales a secundarios? ¿O hay una forma de configurar un conducto entre los hilos y sus padres que no conozco?

¡Muchas gracias de antemano!

+0

la creación del hilo de ocultación y tener una cola de trabajos (función + objeto) con un poco de eventos de encendido debe hacerlo . ¿Estás buscando un comportamiento específico? –

+2

Decide si quieres soluciones en C o C++. Si la biblioteca subyacente es pthreads (es decir, solo C) es mucho menos importante que el idioma para el que desea proporcionar el grupo de subprocesos. –

+0

.. y luego elija C++ –

Respuesta

6

Sí, puede crear un thread-safe queue entre los hilos. Luego, los hilos en el conjunto se colocarán en un bucle recuperando un elemento de la cola, ejecutando lo que sea necesario, luego retrocediendo y obteniendo otro.

Eso es generalmente un poco más fácil/simple en C++ porque es un poco más fácil ponerse de acuerdo en algunas de las interfaces (por ejemplo, sobrecargar operator() para ejecutar el código de una tarea), pero en un nivel fundamental puedes hacer lo mismo cosas en C (por ejemplo, cada estructura task que ponga en la cola contendrá un puntero a una función para llevar a cabo el trabajo para esa tarea).

En su caso, ya que está usando C++, probablemente sea más fácil usar una sobrecarga de operator() para hacer el trabajo. El resto de la estructura task (o lo que sea que elija para llamarlo) contendrá los datos necesarios, etc.

+0

Por lo tanto, idealmente, la cola debería ser segura para subprocesos y usar un semáforo con un valor máximo del número máximo de los hilos que voy a engendrar, ¿verdad? Esta implementación parece un poco sucia ... nunca me siento bien configurando los datos/contenedores "a la vista", no encapsulados por una clase. Es por eso que pregunté sobre una implementación de tubería maestra-hijo_tread –

+0

¿Vale la pena tener una tubería parent-child_PROCESS que valga la encapsulación de datos? –

+0

@ K-RAN: El que he vinculado (desplácese hacia abajo hasta el "código final") * está * encapsulado en una clase. –

3

Desde el POSIX standard:

int pthread_create(pthread_t *restrict thread, 
    const pthread_attr_t *restrict attr, 
    void *(*start_routine)(void*), void *restrict arg); 

(...) El hilo se crea ejecutando con start_routinearg como su único argumento.

Por lo tanto, se debe crear un haz de hilos con esta función, y tener a todos ellos ejecutan una función que es algo como

void *consumer(void *arg) 
{ 
    WorkQueue *queue = static_cast<WorkQueue *>(arg); 

    for (task in queue) { 
     if (task == STOP_WORKING) 
      break; 
     do work; 
    } 
    return WHATEVER; 
} 

(Al final de la entrada, empujar nSTOP_WORKING artículos a la cola, donde n es el número de hilos.)

eso sí, pthreads es una API de nivel muy bajo que ofrece muy poca seguridad de tipos (todos los datos se pasa como p void ointers). Si intentas paralelizar tareas que consumen mucha CPU, te recomendamos que consultes OpenMP.

2

'no parece factible ya que los hilos terminan justo después de la finalización de su tarea' ¿qué?

for(;;){ 
    Task *myTask=theCommonProducerConsumerQueue->pop(); 
    myTask->run(); 
} 

.. nunca devuelven nada, de hecho, nunca regresan.

+0

Nunca pensé en eso antes de esta publicación, ni sabía acerca de los métodos pthread sleep; mi comprensión de los hilos anteriores a esto fue que son cosas únicas. –

-1

http://people.clarkson.edu/~jmatthew/cs644.archive/cs644.fa2001/proj/locksmith/code/ExampleTest/threadpool.c

que utilizó Google hace un par de meses, usted debe probarlo.

Editar: parece que tal vez quieras un grupo en su lugar. Pude crear uno con alguna alteración menor de la anterior para que el trabajador no realizara el trabajo, sino que simplemente se uniera a los hilos.

+0

¿Tiene alguna idea de cómo integrar este threadpool a la biblioteca de eventos como libevent? Parece tener un bucle infinito propio que espera una tarea para el hilo. –

2

Puede que le resulte útil mirar the source code for libdispatch, que es la base del Grand Central Dispatch de Apple y utiliza grupos de subprocesos.

+1

Whoa, interesante. ¡Gracias! –

1

Sugeriría usar Threaded Building Blocks de Intel para realizar tareas como cola de trabajos/subprocesos. Un ejemplo bastante artificial usando TBB 3.0:

class PoorExampleTask : public tbb::task { 
    PoorExampleTask(int foo, tbb::concurrent_queue<float>& results) 
    : _bar(foo), _results(results) 
    { } 

    tbb::task* execute() { 
     _results.push(pow(2.0, foo)); 
     return NULL; 
    } 

private: 
    int _bar; 
    tbb::concurrent_queue<float>& _results; 
} 

utilizado más adelante en este modo:

tbb::concurrent_queue<float> powers; 
for (int ww = 0; ww < LotsOfWork; ++ww) { 
    PoorExampleTask* tt 
     = new (tbb::task::allocate_root()) PoorExampleTask(ww, powers); 
    tbb::task::enqueue(*tt); 
} 
Cuestiones relacionadas