Duración y sincronización de los recursos

Al igual que con Direct3D 12, la aplicación DirectML debe administrar correctamente la duración y sincronización de objetos entre la CPU y la GPU (para que no se genere un comportamiento inesperado). 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 referencia seguros. La aplicación no necesita administrar manualmente las dependencias de duración de la CPU. Por ejemplo, cada elemento secundario del dispositivo contiene una referencia segura a su dispositivo primario.
  • Las dependencias de duración entre objetos de GPU (o dependencias que abarcan CPU y GPU) no se administran automáticamente. Es responsabilidad de la aplicación asegurarse de que los recursos de GPU residen 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 elemento secundario del dispositivo (consulte IDMLDeviceChild) contiene una referencia segura a su dispositivo DirectML primario (consulte IDMLDevice). Esto significa que siempre puede recuperar la interfaz de dispositivo primaria de cualquier interfaz secundaria del dispositivo.

A su vez, un dispositivo DirectML contiene una referencia segura al dispositivo Direct3D 12 que se usó para crearlo (consulte ID3D12Device y las interfaces derivadas).

Dado que el dispositivo DirectML no tiene estado, es implícitamente seguro para subprocesos. Puede llamar a métodos en el dispositivo DirectM 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. Puede crear tantos dispositivos DirectML como desee. Sin embargo, es posible que no pueda combinar elementos secundarios de distintos dispositivos. Por ejemplo, IDMLBindingTable e IDMLCompiledOperator son dos tipos de elementos secundarios de dispositivo (ambas interfaces derivan directa o indirectamente de IDMLDeviceChild). Es posible que no use una tabla de enlace (IDMLBindingTable) para enlazar un operador (IDMLCompiledOperator) si el operador y la tabla de enlace pertenecen a diferentes instancias de dispositivos DirectML.

Dado que el dispositivo DirectML no es un singleton, la eliminación de dispositivos tiene lugar por dispositivo, es decir, no es un evento de todo el proceso, ya que es para un dispositivo Direct3D 12. Para obtener más información, consulte 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 activos automáticamente los recursos mientras están en uso por la GPU. En su lugar, estas son responsabilidades de la 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 mantienen 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 DirectML, esto incluye los siguientes objetos.

  • Se ejecuta IDMLCompiledOperator (o IDMLOperatorInitializer si se está realizando una inicialización de algún operador).
  • IdMLCompiledOperator que respalda la tabla de enlace que se usa para enlazar el operador.
  • Los objetos ID3D12Resource enlazados como entradas y salidas del operador.
  • Los objetos ID3D12Resource enlazados como recursos persistentes y temporales, si procede.
  • ID3D12CommandAllocator, que respalda la lista de comandos.

No todas las interfaces de DirectML representan recursos de GPU. Por ejemplo, una tabla de enlace no necesita mantenerse activa hasta que todas las distribuciones que la usen 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. Pero el montón descriptor sí. Por lo tanto, el montón descriptor subyacente es el objeto que se debe mantener activo hasta que se complete la ejecución y no la propia tabla de enlace.

Existe un concepto similar en Direct3D 12. Un asignador de comandos debe mantenerse activo hasta que todas las ejecuciones que lo usen se hayan completado en la GPU, ya que posee memoria de 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 operadores (IDMLOperatorInitializer) poseen directamente recursos de GPU, por lo que deben mantenerse activos hasta que todos los envíos que los usen hayan completado su ejecución en la GPU. Además, cualquier recurso de Direct3D 12 que se use (asignadores de comandos, montones descriptores, búferes, por ejemplo) debe mantenerse activo de forma similar desde la aplicación.

Si libera prematuramente un objeto mientras sigue en uso por la GPU, el resultado es un comportamiento indefinido, lo que puede provocar la eliminación de dispositivos 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 ejecución posterior. A continuación, la aplicación debe cerrar y enviar la 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 ninguna barrera ni realiza ninguna forma de sincronización entre CPU y GPU por usted. Es responsabilidad de la aplicación usar los primitivos de Direct3D 12 adecuados para esperar a que el trabajo enviado complete su ejecución en la GPU, si es necesario. Para obtener más información, consulte ID3D12Fence e ID3D12CommandQueue::Signal.

Consulte también