c++ - microsoft - visual studio installer
¿Por qué debería usar std:: async? (4)
Estoy tratando de explorar todas las opciones del nuevo estándar C ++ 11 en profundidad, mientras uso std :: async y leyendo su definición, noté 2 cosas, al menos en Linux con gcc 4.8.1:
- se llama asíncrono , pero tiene un "comportamiento secuencial" realmente, básicamente en la fila donde se llama el futuro asociado con su función asíncrona foo , el programa bloquea hasta que se completa la ejecución de foo .
- depende de la misma biblioteca externa que otros, y mejores soluciones sin bloqueo, lo que significa
pthread
, si desea usarstd::async
necesita pthread.
En este punto, es natural para mí preguntar por qué elegir std :: async incluso con un simple conjunto de funtores. Es una solución que ni siquiera se escala, mientras más futuro llame, menos receptivo será su programa.
Me estoy perdiendo de algo ? ¿Puedes mostrar un ejemplo que se concede para ser ejecutado de forma asíncrona, sin bloqueo?
- se llama asincrónico, pero obtuvo un "comportamiento secuencial" realmente
No, si usa la política std::launch::async
, se ejecutará de forma asíncrona en un nuevo hilo. Si no especifica una política, podría ejecutarse en un nuevo hilo.
Básicamente en la fila donde llamas al futuro asociado con tu función asíncrona foo, el programa bloquea hasta que se completa la ejecución de foo.
Solo bloquea si foo no se ha completado, pero si se ejecutó de forma asíncrona (por ejemplo, porque usa la política std::launch::async
), es posible que se haya completado antes de que lo necesite.
- depende de la misma biblioteca externa que otros, y mejores soluciones sin bloqueo, lo que significa pthread, si desea usar std :: async necesita pthread.
Incorrecto, no tiene que implementarse usando Pthreads (y en Windows no lo es, usa las funciones de ConcRT).
En este punto, es natural para mí preguntar por qué elegir std :: async incluso con un simple conjunto de funtores.
Porque garantiza seguridad de subprocesos y propaga excepciones entre subprocesos. ¿Puedes hacer eso con un simple conjunto de funtores?
Es una solución que ni siquiera se escala, mientras más futuro llame, menos receptivo será su programa.
No necesariamente. Si no especifica la política de lanzamiento, una implementación inteligente puede decidir si comienza un nuevo hilo, o devuelve una función diferida, o devuelve algo que decida más adelante, cuando haya más recursos disponibles.
Ahora bien, es cierto que con la implementación de GCC, si no se proporciona una política de lanzamiento, con las versiones actuales nunca se ejecutará en un nuevo hilo (hay un informe bugzilla para eso), pero esa es una propiedad de esa implementación, no de std::async
en general. No debe confundir la especificación en el estándar con una implementación particular. Leer la implementación de una biblioteca estándar es una forma pobre de aprender sobre C ++ 11.
¿Puedes mostrar un ejemplo que se concede para ser ejecutado de forma asíncrona, sin bloqueo?
Esto no debería bloquear:
auto fut = std::async(std::launch::async, doSomethingThatTakesTenSeconds);
auto result1 = doSomethingThatTakesTwentySeconds();
auto result2 = fut.get();
Al especificar la política de lanzamiento, fuerza la ejecución asincrónica, y si realiza otro trabajo mientras se está ejecutando, el resultado estará listo cuando lo necesite.
Creo que tu problema es con std::future
diciendo que bloquea en get
. Solo bloquea si el resultado no está listo .
Si puede hacer los arreglos para que el resultado ya esté listo, esto no es un problema.
Hay muchas formas de saber que el resultado ya está listo. Puede sondear el future
y preguntar (relativamente simple), podría usar bloqueos o datos atómicos para transmitir el hecho de que está listo, podría construir un marco para entregar artículos future
"terminados" en una cola con la que los consumidores puedan interactuar. , podrías usar señales de algún tipo (que es solo bloquear en varias cosas a la vez, o sondear).
O bien, puede terminar todo el trabajo que puede hacer localmente y luego bloquear el trabajo remoto.
Como ejemplo, imagine un tipo de combinación recursiva paralela. Divide la matriz en dos trozos, luego realiza una ordenación async
en un trozo mientras ordena el otro trozo. Una vez que haya terminado de ordenar su mitad, el hilo de origen no podrá avanzar hasta que la segunda tarea haya finalizado. Entonces hace un .get()
y bloques. Una vez que ambas mitades han sido ordenadas, puede hacer una fusión (en teoría, la fusión se puede hacer al menos parcialmente en paralelo también).
Esta tarea se comporta como una tarea lineal para aquellos que interactúan con ella en el exterior: cuando se hace, la matriz se ordena.
A continuación, podemos ajustar esto en una tarea std::async
y tener una matriz ordenada en el future
. Si queremos, podríamos agregar un procedimiento de señalización para hacernos saber que el future
está terminado, pero eso solo tiene sentido si tenemos un hilo esperando las señales.
Si se establece el indicador asíncrono (es decir, policy & std :: launch :: async! = 0), entonces async ejecuta la función f en un hilo de ejecución separado como si generada por std :: thread (f, args ...) , excepto que si la función f devuelve un valor o arroja una excepción, se almacena en el estado compartido al que se accede a través de std :: future que async regresa a la persona que llama .
Es una buena propiedad mantener un registro de las excepciones lanzadas.
Si necesita el resultado de una operación asincrónica, debe bloquear, sin importar qué biblioteca use. La idea es que elijas cuándo bloquear y, con suerte, cuando lo hagas, bloqueas por un tiempo insignificante porque todo el trabajo ya se ha realizado.
Tenga en cuenta también que std::async
se puede iniciar con las políticas std::launch::async
o std::launch::deferred
. Si no lo especifica, la implementación puede elegir, y podría elegir utilizar la evaluación diferida, lo que daría como resultado todo el trabajo que se realizará cuando intente obtener el resultado del futuro, lo que resultará en un bloqueo más largo. . Por lo tanto, si quiere asegurarse de que el trabajo se realice de forma asincrónica, use std::launch::async
.