Preguntas relevantes :
Sobre C ++ 11:
- C ++ 11: std :: hilo agrupado?
- ¿Async (launch :: async) en C ++ 11 hará que los grupos de subprocesos sean obsoletos para evitar la creación de subprocesos costosos?
Sobre Boost:
¿Cómo consigo un grupo de subprocesos para enviar tareas , sin crearlas y eliminarlas una y otra vez? Esto significa hilos persistentes para resincronizar sin unirse.
Tengo un código que se ve así:
namespace {
std::vector<std::thread> workers;
int total = 4;
int arr[4] = {0};
void each_thread_does(int i) {
arr[i] += 2;
}
}
int main(int argc, char *argv[]) {
for (int i = 0; i < 8; ++i) { // for 8 iterations,
for (int j = 0; j < 4; ++j) {
workers.push_back(std::thread(each_thread_does, j));
}
for (std::thread &t: workers) {
if (t.joinable()) {
t.join();
}
}
arr[4] = std::min_element(arr, arr+4);
}
return 0;
}
En lugar de crear y unir subprocesos en cada iteración, preferiría enviar tareas a mis subprocesos de trabajo en cada iteración y solo crearlas una vez.
c++
multithreading
c++11
threadpool
stdthread
Yktula
fuente
fuente
Respuestas:
Puede usar la biblioteca de grupos de subprocesos de C ++, https://github.com/vit-vit/ctpl .
Luego, el código que escribió puede reemplazarse con el siguiente
Obtendrá el número deseado de hilos y no los creará y eliminará una y otra vez en las iteraciones.
fuente
results[j] = p.push([&arr, j](int){ arr[j] +=2; });
Esto se copia de mi respuesta a otra publicación muy similar, espero que pueda ayudar:
1) Comience con el número máximo de subprocesos que un sistema puede admitir:
2) Para una implementación eficiente de conjunto de subprocesos, una vez que los subprocesos se crean de acuerdo con Num_Threads, es mejor no crear nuevos o destruir los antiguos (uniéndose). Habrá una penalización de rendimiento, incluso podría hacer que su aplicación vaya más lenta que la versión en serie.
Cada subproceso de C ++ 11 debe ejecutarse en su función con un bucle infinito, esperando constantemente que se lleven a cabo nuevas tareas.
Aquí se explica cómo adjuntar dicha función al grupo de subprocesos:
3) La función de bucle infinito
Este es un ciclo "while (verdadero)" que espera la cola de tareas
4) Haga una función para agregar trabajo a su cola
5) Vincula una función arbitraria a tu Cola
Una vez que integre estos ingredientes, tiene su propio grupo dinámico de subprocesos. Estos subprocesos siempre se ejecutan, esperando el trabajo que hacer.
Pido disculpas si hay algunos errores de sintaxis, escribí este código y tengo mala memoria. Lamento no poder proporcionarle el código completo del grupo de subprocesos, eso violaría la integridad de mi trabajo.
Editar: para terminar el grupo, llame al método shutdown ():
fuente
std::vector
no requiere que sus elementos sean copiables. Puede utilizar vectores con los tipos de movimiento de sólo (unique_ptr
,thread
,future
, etc.).condition.wait
también buscar una variablestop_
y verificarif (stop_ == true) { break;}
?Un grupo de subprocesos significa que todos sus subprocesos se están ejecutando, todo el tiempo; en otras palabras, la función de subproceso nunca regresa. Para dar a los hilos algo significativo que hacer, debe diseñar un sistema de comunicación entre hilos, tanto con el fin de decirle al hilo que hay algo que hacer, como para comunicar los datos de trabajo reales.
Por lo general, esto implicará algún tipo de estructura de datos concurrentes, y cada hilo probablemente duerma en algún tipo de variable de condición, que se notificará cuando haya trabajo por hacer. Al recibir la notificación, uno o varios subprocesos se activan, recuperan una tarea de la estructura de datos concurrente, la procesan y almacenan el resultado de manera análoga.
Luego, el hilo continuará para verificar si hay aún más trabajo por hacer y, si no, volver a dormir.
El resultado es que tiene que diseñar todo esto usted mismo, ya que no existe una noción natural de "trabajo" que sea de aplicación universal. Es bastante trabajo, y hay algunos problemas sutiles que debes resolver. (Puede programar en Go si desea un sistema que se encargue de la gestión de subprocesos detrás de escena).
fuente
Un conjunto de subprocesos es, en esencia, un conjunto de subprocesos todos vinculados a una función que funciona como un bucle de eventos. Estos subprocesos esperarán sin cesar hasta que se ejecute una tarea o su propia terminación.
El trabajo de grupo de subprocesos es proporcionar una interfaz para enviar trabajos, definir (y quizás modificar) la política de ejecución de estos trabajos (reglas de programación, creación de instancias de subprocesos, tamaño del grupo) y supervisar el estado de los subprocesos y recursos relacionados.
Entonces, para un grupo versátil, uno debe comenzar definiendo qué es una tarea, cómo se inicia, se interrumpe, cuál es el resultado (vea la noción de promesa y futuro para esa pregunta), qué tipo de eventos tendrán que responder los hilos. a, cómo los manejarán, cómo estos eventos serán discriminados de los manejados por las tareas. Como puede ver, esto puede volverse bastante complicado e imponer restricciones sobre cómo funcionarán los subprocesos, a medida que la solución se involucra cada vez más.
La herramienta actual para manejar eventos es bastante básica (*): primitivas como mutexes, variables de condición y algunas abstracciones además de eso (bloqueos, barreras). Pero en algunos casos, estas abstracciones pueden resultar no aptas (ver esta pregunta relacionada ), y uno debe volver a usar las primitivas.
Otros problemas también deben ser manejados:
¿Cómo se desarrollarían en tu entorno?
Esta respuesta a una pregunta similar apunta a una implementación existente destinada a boost y stl.
Me ofrecieron una aplicación muy cruda de un conjunto de subprocesos para otra pregunta, que no aborda muchos de los problemas descritos anteriormente. Es posible que desee construir sobre él. También es posible que desee echar un vistazo a los marcos existentes en otros idiomas, para encontrar inspiración.
(*) No lo veo como un problema, sino todo lo contrario. Creo que es el espíritu de C ++ heredado de C.
fuente
fuente
Algo como esto podría ayudar (tomado de una aplicación que funciona).
Puedes usarlo así:
Tenga en cuenta que reinventar un mecanismo de cola asíncrono eficiente no es trivial.
Boost :: asio :: io_service es una implementación muy eficiente, o en realidad es una colección de contenedores específicos de la plataforma (por ejemplo, envuelve los puertos de finalización de E / S en Windows).
fuente
std::thread
suficiente?std
paraboost::thread_group
.boost::thread_group
Es una colección deboost::thread
instancias. Pero, por supuesto, es muy fácil reemplazarloboost::thread_group
con unavector
destd::thread
s.Editar: Esto ahora requiere C ++ 17 y conceptos. (A partir del 12/09/16, solo g ++ 6.0+ es suficiente).
Sin embargo, la deducción de plantillas es mucho más precisa debido a ello, por lo que vale la pena el esfuerzo de obtener un compilador más nuevo. Todavía no he encontrado una función que requiera argumentos de plantilla explícitos.
Ahora también toma cualquier objeto invocable apropiado (¡ y todavía es estáticamente seguro! ).
Ahora también incluye un grupo de subprocesos de prioridad de subprocesamiento verde opcional con la misma API. Sin embargo, esta clase es solo POSIX. Utiliza la
ucontext_t
API para el cambio de tareas del espacio de usuario.Creé una biblioteca simple para esto. Un ejemplo de uso se da a continuación. (Estoy respondiendo esto porque fue una de las cosas que encontré antes de decidir que era necesario escribirlo yo mismo).
Puede pasar
async
cualquier función con cualquier valor de retorno (o nulo) y cualquier argumento (o no) y devolverá un correspondientestd::future
. Para obtener el resultado (o simplemente esperar hasta que una tarea se haya completado), llamaget()
al futuro.Aquí está el github: https://github.com/Tyler-Hardin/thread_pool .
fuente
Esta es otra implementación de grupo de subprocesos que es muy simple, fácil de entender y usar, usa solo la biblioteca estándar de C ++ 11 y se puede ver o modificar para sus usos, debería ser un buen comienzo si desea comenzar a usar el subproceso quinielas:
https://github.com/progschj/ThreadPool
fuente
Puede usar thread_pool de la biblioteca boost:
También puede usar threadpool de la comunidad de código abierto:
fuente
Un conjunto de subprocesos sin dependencias fuera de STL es completamente posible. Recientemente escribí una pequeña biblioteca de subprocesos de solo encabezado para abordar exactamente el mismo problema. Admite el cambio de tamaño dinámico del grupo (cambio del número de trabajadores en tiempo de ejecución), espera, detención, pausa, reanudación, etc. Espero que le sea útil.
fuente