Pregunta Esperando múltiples futuros?


Me gustaría ejecutar tareas (hilos de trabajo) del mismo tipo, pero no más de un cierto número de tareas a la vez. Cuando una tarea finaliza, su resultado es una entrada para una nueva tarea que, luego, puede iniciarse.

¿Hay alguna forma de implementar esto con el paradigma async / future en C ++ 11?

A primera vista, parece sencillo, solo genera múltiples tareas con:

std::future<T> result = std::async(...);

y, luego, correr result.get() para obtener un resultado asíncrono de una tarea.

Sin embargo, el problema aquí es que los objetos futuros deben almacenarse en una especie de cola y esperar uno por uno. Sin embargo, es posible iterar sobre los objetos futuros una y otra vez comprobando si alguno de ellos está listo, pero no es deseable debido a una carga de CPU innecesaria.

¿Es posible de alguna manera esperar por alguna futuro de un conjunto dado para estar listo y obtener su resultado?

La única opción que puedo pensar hasta ahora es un enfoque de la vieja escuela sin asincronía / futuro. Específicamente, al generar múltiples subprocesos de trabajo y al final de cada subproceso, se envía su resultado a una cola protegida por mutex que notifica al subproceso de espera a través de una variable de condición que la cola se ha actualizado con más resultados.

¿Hay alguna otra mejor solución con async / future posible?


35
2017-10-07 12:48


origen


Respuestas:


El soporte de subprocesos en C ++ 11 fue solo un primer paso, y mientras std::future rocas, no es compatible con espera múltiple todavía.

Sin embargo, puedes fingir de manera relativamente ineficiente. Terminas creando un hilo de ayuda para cada std::future (ouch, muy caro), luego reuniendo su "este future está listo "en una cola de mensajes de un solo consumidor sincronizada de muchos productores, y luego configura una tarea de consumo que distribuye el hecho de que un determinado std::future está listo.

los std::future en este sistema no agrega mucha funcionalidad, y tener tareas que indiquen directamente que están listas y pegue su resultado en la cola anterior sería más eficiente. Si sigue esta ruta, puede escribir un contenedor que coincida con el patrón de std::async o std::thready devuelve un std::future como objeto que representa un mensaje de cola. Esto básicamente implica volver a implementar un fragmento de la biblioteca de concurrencia.

Si quieres quedarte con std::future, podrías crear shared_futures, y que cada tarea dependiente dependa del conjunto de shared_futures: es decir, hazlo sin un planificador central. Esto no permite cosas como mensajes de aborto / apagado, que considero esenciales para un sistema robusto de tareas múltiples.

Finalmente, puedes esperar C ++ 2x, o siempre que la concurrencia TS esté plegada en el estándar, para resolver el problema por usted.


17
2017-10-07 15:42



Podrías crear todos los futuros de "generación 1", y darle todos esos futuros a su generación 2 tareas, que luego esperarán su aportación ellos mismos.


4
2017-10-07 12:54