c++ - ¿Cuál es el problema con std:: async?
multithreading c++11 (2)
Hay varias cuestiones:
std::async
sin una política de inicio permite a la biblioteca de tiempo de ejecución elegir si iniciar un nuevo hilo o ejecutar la tarea en el hilo que se llamaget()
owait()
en el futuro. Como dice Herb, este es el caso que probablemente quieras usar. El problema es que esto lo deja abierto a la QoI de la biblioteca de tiempo de ejecución para obtener el número correcto de subprocesos, y no se sabe si la tarea tendrá un subproceso en sí misma, por lo que el uso de variables de subprocesos locales puede ser problemático. Esto es lo que preocupa a Scott, tal como lo entiendo.El uso de una política de
std::launch::deferred
no ejecuta la tarea hasta que se llama explícitamente aget()
o sewait()
. Esto casi nunca es lo que quieres, así que no hagas eso.Usando una política de
std::launch::async
comienza un nuevo hilo. Si no realiza un seguimiento de la cantidad de subprocesos que tiene, esto puede hacer que se ejecuten demasiados subprocesos.A Herb le preocupa el comportamiento de
std::future
destructor, que se supone que debe esperar a que se complete la tarea, aunque MSVC2012 tiene un error que no espera.
Para un desarrollador junior, sugeriría:
- Use
std::async
con la política de inicio predeterminada. - Asegúrate de esperar explícitamente todos tus futuros.
- No utilice el almacenamiento local de subprocesos en las tareas asíncronas.
Cerca del comienzo de este clip de C ++ And Beyond, escuché algo sobre problemas con std::async
. Tengo dos preguntas:
Para un desarrollador junior, ¿hay un conjunto de reglas sobre qué hacer y qué evitar al usar
std::async
?¿Cuáles son los problemas presentados en este video? ¿Están relacionados con este artículo ?
No podría estar en desacuerdo sobre el consejo de usar la política predeterminada.
Si se esfuerza por diseñar unidades de cómputo independientes, probablemente no espere que se ejecuten de forma secuencial mientras media docena de CPU hacen girar sus pulgares, lo que puede suceder "legalmente" según el compilador que elija .
La suposición implícita del comportamiento predeterminado es que algún mecanismo sofisticado de agrupación de subprocesos optimizará la colocación de tareas (posiblemente permitiendo que algunos se ejecuten secuencialmente en la CPU del llamador), pero eso es pura fantasía, ya que nada especifica lo que debe hacer el tiempo de ejecución de C ++ (que iría bien más allá del alcance de un tiempo de ejecución del compilador de todos modos).
Esto se parece más a un comportamiento indefinido por diseño para mí.
Una clase llamada "async" debería lanzar unidades de ejecución asíncronas, a menos que algún parámetro de comportamiento explícito y determinista indique lo contrario.
Francamente, a excepción del propósito de la depuración, no puedo ver un uso para el launch::deferred
, a menos que planee escribir su propio pseudo-programador, en cuyo caso será mejor que use hilos simples.
Así que mi consejo sería especificar launch::async
cuando uses async
, (diciendo al compilador algo como "hey, quiero una tarea async, pero realmente async, ¿vale?") Y no usar async
en absoluto si solo quieres para ejecutar tareas de forma secuencial.
Si tiene problemas con sus tareas asíncronas, puede ser conveniente volver a la política deferred
para depurarlas más fácilmente, pero eso es todo.