Partager via


Durée de vie et synchronisation des ressources

Comme avec Direct3D 12, votre application DirectML doit (afin d’éviter tout comportement non défini) gérer correctement les durées de vie et la synchronisation des objets entre l’UC et le GPU. DirectML suit un modèle de durée de vie de ressource identique à celui de Direct3D 12.

  • Les dépendances de durée de vie entre deux objets de processeur sont gérées par DirectML en utilisant des compteurs de références fortes. Votre application n’a pas besoin de gérer manuellement les dépendances de durée de vie du processeur. Par exemple, chaque enfant d’appareil contient une référence forte à son appareil parent.
  • Les dépendances de durée de vie entre les objets GPU ou les dépendances qui s’étendent sur l’UC et le GPU ne sont pas gérées automatiquement. Il est de la responsabilité de votre application de s’assurer que les ressources GPU vivent au moins jusqu’à ce que tout le travail à l’aide de cette ressource ait terminé l’exécution sur le GPU.

Appareils DirectML

L’appareil DirectML est un objet d’usine sans état thread-safe. Chaque enfant d’appareil (voir IDMLDeviceChild) contient une référence forte à son appareil DirectML parent (voir IDMLDevice). Cela signifie que vous pouvez toujours récupérer l’interface de l’appareil parent à partir de n’importe quelle interface enfant de l’appareil.

Un appareil DirectML contient à son tour une référence forte à l’appareil Direct3D 12 qui a été utilisé pour le créer (voir ID3D12Device et interfaces dérivées).

Comme l’appareil DirectML est sans état, il est implicitement thread-safe. Vous pouvez appeler des méthodes sur l’appareil DirectML à partir de plusieurs threads simultanément sans avoir besoin de synchronisation externe.

Toutefois, contrairement à l’appareil Direct3D 12, l’appareil DirectML n’est pas un objet singleton. Vous êtes libre de créer autant d’appareils DirectML que vous le souhaitez. Cependant, vous ne pouvez pas mélanger et assortir les enfants d’appareils qui appartiennent à des appareils différents. Par exemple, IDMLBindingTable et IDMLCompiledOperator sont deux types d’enfants d’appareils (les deux interfaces dérivent directement ou indirectement d’IDMLDeviceChild). Et vous ne pouvez pas utiliser une table de liaison (IDMLBindingTable) pour lier pour un opérateur (IDMLCompiledOperator) si l’opérateur et la table de liaison appartiennent à différentes instances d’appareil DirectML.

Étant donné que le dispositif DirectML n’est pas un singleton, la suppression de dispositif se fait individuellement par dispositif, au lieu d’être un événement à l’échelle du processus, comme c’est le cas pour un dispositif Direct3D 12. Pour plus d’informations, consultez Gestion des erreurs et suppression d’appareils dans DirectML.

Exigences de durée de vie des ressources GPU

Comme Direct3D 12, DirectML ne se synchronise pas automatiquement entre l’UC et le GPU ; il ne conserve pas automatiquement les ressources actives pendant qu’elles sont utilisées par le GPU. Au lieu de cela, c’est votre application qui exerce ces responsabilités.

Lors de l’exécution d’une liste de commandes qui contient des répartitions DirectML, votre application doit s’assurer que les ressources GPU sont conservées actives jusqu’à ce que toutes les ressources utilisant ces ressources soient exécutées sur le GPU.

Dans le cas d’IDMLCommandRecorder ::RecordDispatch pour un opérateur DirectML, qui inclut les objets suivants.

  • IDMLCompiledOperator en cours d’exécution (ou IDMLOperatorInitializer à la place, si l’initialisation d’opérateur est effectuée).
  • IDMLCompiledOperator qui prend en charge la table de liaison utilisée pour lier l’opérateur.
  • Objets ID3D12Resource liés en tant qu’entrées/sorties de l’opérateur.
  • Objets ID3D12Resource liés en tant que ressources persistantes et temporaires, le cas échéant.
  • ID3D12CommandAllocator qui prend en charge la liste de commandes elle-même.

Toutes les interfaces DirectML ne représentent pas les ressources GPU. Par exemple, une table de liaison n’a pas besoin d’être conservée active tant que toutes les distributions qui l’utilisent n’ont pas terminé l’exécution sur le GPU. Cela est dû au fait que la table de liaison elle-même ne possède aucune ressource GPU. Au lieu de cela, c’est le tas de descripteurs qui le fait. Par conséquent, le segment de descripteur sous-jacent est l’objet qui doit être conservé actif tant que l’exécution n’est pas terminée, et non la table de liaison elle-même.

Un concept similaire existe dans Direct3D 12. Un allocateur de commande doit être conservé actif jusqu’à ce que toutes les exécutions qui l’utilisent soient terminées sur le GPU ; étant donné qu’il possède la mémoire GPU. Toutefois, une liste de commandes ne possède pas de mémoire GPU. Elle peut donc être réinitialisée ou libérée dès qu’elle a été envoyée pour exécution.

Dans DirectML, les opérateurs compilés (IDMLCompiledOperator) et les initialiseurs d’opérateur (IDMLOperatorInitializer) possèdent directement les ressources GPU, de sorte qu’ils doivent être conservés actifs jusqu’à ce que toutes les distributions les utilisant aient terminé l’exécution sur le GPU. En outre, toute ressource Direct3D 12 utilisée (allocateurs de commande, tas de descripteurs, mémoires tampons) doit également être maintenue active par votre application.

Si vous relâchez prématurément un objet alors qu’il est toujours utilisé par le GPU, le résultat est un comportement non défini, ce qui a le potentiel de provoquer la suppression de l’appareil ou d’autres erreurs.

Synchronisation du processeur et du GPU

DirectML n’envoie pas de travail pour l’exécution sur le GPU. Au lieu de cela, la méthode IDMLCommandRecorder ::RecordDispatchenregistre la répartition de ce travail dans une liste de commandes pour une exécution ultérieure. Votre application doit ensuite fermer et envoyer sa liste de commandes pour l’exécution en appelant ID3D12CommandQueue ::ExecuteCommandLists, comme avec n’importe quelle liste de commandes Direct3D 12.

Étant donné que DirectML n’envoie pas de travail pour l’exécution sur le GPU, il ne crée pas non plus de clôtures, ni n’effectue aucune forme de synchronisation UC/GPU en votre nom. Il incombe à votre application d’utiliser les primitives Direct3D 12 appropriées pour attendre que le travail soumis termine l’exécution sur le GPU, si nécessaire. Pour plus d’informations, consultez ID3D12Fence et ID3D12CommandQueue ::Signal.

Voir aussi