Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Al igual que con Direct3D 12, la aplicación DirectML debe (para evitar comportamientos indefinidos) administrar correctamente la duración de los objetos y la sincronización entre la CPU y la GPU. DirectML sigue un modelo de duración de recursos idéntico al de Direct3D 12.
- DirectML mantiene las dependencias de duración entre dos objetos de CPU mediante recuentos de referencias seguros. La aplicación no necesita administrar manualmente las dependencias de la duración de la CPU. Por ejemplo, cada dispositivo secundario tiene una referencia segura a su dispositivo principal.
- Las dependencias de duración entre objetos de GPU, o las dependencias que abarcan la CPU y la GPU, no se administran automáticamente. Es responsabilidad de la aplicación asegurarse de que los recursos de GPU permanezcan activos al menos hasta que todo el trabajo con ese recurso haya completado la ejecución en la GPU.
Dispositivos DirectML
El dispositivo DirectML es un objeto de fábrica sin estado seguro para subprocesos. Cada dispositivo secundario (consulte IDMLDeviceChild) tiene una referencia segura a su dispositivo DirectML primario (consulte IDMLDevice). Eso significa que siempre puede recuperar la interfaz del dispositivo principal desde cualquier interfaz del dispositivo secundario.
A su vez, un dispositivo DirectML tiene una referencia segura al dispositivo Direct3D 12 que se usó para crearlo (consulte ID3D12Device e interfaces derivadas).
Dado que el dispositivo DirectML no tiene estado, es implícitamente seguro para subprocesos. Puede llamar a métodos en el dispositivo DirectML desde varios subprocesos simultáneamente sin necesidad de sincronización externa.
Sin embargo, a diferencia del dispositivo Direct3D 12, el dispositivo DirectML no es un objeto singleton. Eres libre de crear tantos dispositivos DirectML como desees. Sin embargo, no puede mezclar y combinar dispositivos secundarios que pertenezcan a diferentes dispositivos. Por ejemplo, IDMLBindingTable e IDMLCompiledOperator son dos tipos de dispositivos secundarios (ambas interfaces derivan directa o indirectamente de IDMLDeviceChild). Y no puede usar una tabla de enlace (IDMLBindingTable) para enlazar un operador (IDMLCompiledOperator) si el operador y la tabla de enlace pertenecen a instancias de dispositivo DirectML diferentes.
Dado que el dispositivo DirectML no es un singleton, la eliminación del dispositivo se produce por dispositivo, en lugar de ser un evento de todo el proceso como lo es para un dispositivo Direct3D 12. Para obtener más información, consulta Control de errores y eliminación de dispositivos en DirectML.
Requisitos de duración de los recursos de GPU
Al igual que Direct3D 12, DirectML no se sincroniza automáticamente entre la CPU y la GPU; tampoco mantiene automáticamente los recursos vivos mientras la GPU los utiliza. En cambio, estas son responsabilidades de su aplicación.
Al ejecutar una lista de comandos que contiene envíos de DirectML, la aplicación debe asegurarse de que los recursos de GPU se mantengan activos hasta que todo el trabajo con esos recursos haya completado la ejecución en la GPU.
En el caso de IDMLCommandRecorder::RecordDispatch para un operador de DirectML, incluye los siguientes objetos.
- IDMLCompiledOperator que se está ejecutando (o IDMLOperatorInitializer en su lugar, si se realiza la inicialización del operador).
- IDMLCompiledOperator que respalda la tabla de enlace que se usa para enlazar al operador.
- Los objetos ID3D12Resource enlazados como entradas/salidas del operador.
- Los objetos ID3D12Resource enlazados como recursos persistentes y temporales, si procede.
- ID3D12CommandAllocator que respalda la propia lista de comandos.
No todas las interfaces de DirectML representan recursos de GPU. Por ejemplo, no es necesario mantener activa una tabla de enlace hasta que todos los envíos que la utilizan hayan completado su ejecución en la GPU. Esto se debe a que la propia tabla de enlace no posee ningún recurso de GPU. Más bien, el montón de descriptores lo hace. Por lo tanto, el montón de descriptores subyacente es el objeto que se debe mantener activo hasta que se complete la ejecución, y no la tabla de enlace en sí.
Existe un concepto similar en Direct3D 12. Un asignador de comandos debe mantenerse activo hasta que se hayan completado todas las ejecuciones que lo utilicen en la GPU; ya que posee la memoria de la GPU. Sin embargo, una lista de comandos no posee memoria de GPU, por lo que se puede restablecer o liberar tan pronto como se haya enviado para su ejecución.
En DirectML, los operadores compilados (IDMLCompiledOperator) y los inicializadores de operador (IDMLOperatorInitializer) poseen recursos de GPU directamente, por lo que deben mantenerse activos hasta que todos los envíos que los usan hayan completado la ejecución en la GPU. Además, cualquier recurso de Direct3D 12 que se use (asignadores de comandos, montones de descriptores, búferes, por ejemplo) debe mantenerse activo de forma similar en la aplicación.
Si libera prematuramente un objeto mientras la GPU todavía lo está utilizando, el resultado es un comportamiento indefinido, que puede provocar la eliminación del dispositivo u otros errores.
Sincronización de CPU y GPU
DirectML no envía ningún trabajo para su ejecución en la GPU. En su lugar, el método IDMLCommandRecorder::RecordDispatchregistra el envío de ese trabajo en una lista de comandos para su posterior ejecución. A continuación, la aplicación debe cerrarse y enviar su lista de comandos para su ejecución llamando a ID3D12CommandQueue::ExecuteCommandLists, como con cualquier lista de comandos de Direct3D 12.
Dado que DirectML no envía ningún trabajo para su ejecución en la GPU, tampoco crea ningún límite ni realiza ninguna forma de sincronización de CPU y GPU en su nombre. Es responsabilidad de la aplicación usar las primitivas de Direct3D 12 adecuadas para esperar a que el trabajo enviado se complete la ejecución en la GPU, si es necesario. Para obtener más información, consulta ID3D12Fence e ID3D12CommandQueue::Signal.