Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Wymagania dotyczące ograniczeń widoku dostępu nieuporządkowanego (UAV)
Bariery UAV w trybie Direct3D 12
W Direct3D 12, sąsiadujące dyspozycje cieniowania obliczeniowego na tej samej liście poleceń mogą być wykonywane równolegle na układzie GPU, chyba że są zsynchronizowane z pośredniczącą zaporą nieuporządkowanego dostępu (UAV). Może to poprawić wydajność, zwiększając wykorzystanie sprzętu procesora GPU. Jednak domyślnie, bez użycia bariery UAV, równoległe wykonywanie dwóch sąsiednich operacji dyspozytorskich może spowodować stan wyścigu, jeśli istnieje zależność danych między tymi dwiema operacjami lub jeśli obie wykonują zapisy UAV do tych samych obszarów pamięci.
Bariera UAV wymusza, aby wszystkie wcześniej przesłane operacje zostały ukończone na procesorze GPU, zanim rozpoczną się kolejne operacje. Bariery UAV służą do synchronizowania między wysyłkami na tej samej liście poleceń, aby uniknąć wyścigów danych. Barierę UAV można ustawić przy użyciu metody ID3D12GraphicsCommandList::ResourceBarrier.
Bariery UAV w języku DirectML
W DirectML operatory są wysyłane w sposób podobny do tego, w jaki shadery obliczeniowe są wysyłane w Direct3D 12. Oznacza to, że sąsiadujące zlecenia operatorów mogą być wykonywane równolegle na procesorze GPU, chyba że istnieje pośrednicząca bariera UAV między nimi. Typowy model uczenia maszynowego zawiera zależności danych między operatorami; na przykład dane wyjściowe jednego operatora są wprowadzane do danych wejściowych innego. Dlatego ważne jest, aby prawidłowo synchronizować wysyłki przy użyciu barier UAV.
DirectML gwarantuje, że będzie odczytywać tylko z (i nigdy nie zapisywać) tensorów wejściowych. Gwarantuje również, że nigdy nie będzie dokonywać zapisów do tensoru wyjściowego poza zakresem pola członkowskiego DML_BUFFER_TENSOR_DESC::TotalTensorSizeInBytes. Oznacza to, że zależności danych między operatorami w języku DirectML mogą być uzasadnione, patrząc tylko na powiązania wejściowe i wyjściowe operatora.
Na przykład te gwarancje umożliwiają wysyłanie dwóch operatorów, którzy wiążą ten sam region zasobu jako wejście, bez konieczności wydawania bariery UAV pośredniczącej. Jest to zawsze bezpieczne, ponieważ język DirectML nigdy nie zapisuje w tensorach wejściowych. Innym przykładem jest to, że zawsze bezpieczne jest powiązanie tensorów wyjściowych dwóch współbieżnych wywołań operatorów do tego samego zasobu Direct3D 12 (tak długo, jak ich tensory nie nakładają się), ponieważ DirectML nigdy nie zapisuje poza granicami tensora (zgodnie z definicją tensora w DML_BUFFER_TENSOR_DESC::TotalTensorSizeInBytes).
Ponieważ bariery UAV są formą synchronizacji, niepotrzebne użycie barier UAV może negatywnie wpłynąć na wydajność. W związku z tym najlepiej jest użyć minimalnej liczby barier UAV niezbędnych do poprawnej synchronizacji wydawania poleceń w ramach listy poleceń.
Przykład 1
W poniższym przykładzie wynik operatora konwolucji jest przekazywany do aktywacji ReLU, a następnie przeprowadzana jest normalizacja wsadowa.
CONVOLUTION (conv1)
|
ACTIVATION_RELU (relu1)
|
BATCH_NORMALIZATION (batch1)
Ponieważ zależność danych istnieje między wszystkimi trzema operatorami, będzie potrzebna bariera UAV między poszczególnymi kolejnymi wysyłkami (zobacz IDMLCommandRecorder::RecordDispatch).
-
dmlCommandRecorder->RecordDispatch(d3d12CommandList,konw.1 powiedział:) -
d3d12CommandList->ResourceBarrier(Bariera UAV) -
dmlCommandRecorder->RecordDispatch(d3d12CommandList,relu1 powiedział:) -
d3d12CommandList->ResourceBarrier(Bariera UAV) -
dmlCommandRecorder->RecordDispatch(d3d12CommandList,Partia1)
Przykład 2
MAX_POOLING (pool1)
/ \
CONVOLUTION CONVOLUTION
(conv1) (conv2)
\ /
JOIN (join1)
W tym przypadku dane wyjściowe buforowania są przekazywane do dwóch konwojów, których dane wyjściowe są następnie łączone razem przy użyciu operatora JOIN. Zależność danych istnieje między pool1 a conv1 i conv2; a także między conv1 a conv2 i join1. Oto jeden prawidłowy sposób wykonania tego grafu.
-
dmlCommandRecorder->RecordDispatch(d3d12CommandList,Basen1) -
d3d12CommandList->ResourceBarrier(Bariera UAV) -
dmlCommandRecorder->RecordDispatch(d3d12CommandList,konw.1 powiedział:) -
dmlCommandRecorder->RecordDispatch(d3d12CommandList,conv2 powiedział:) -
d3d12CommandList->ResourceBarrier(Bariera UAV) -
dmlCommandRecorder->RecordDispatch(d3d12CommandList,join1 (łączenie1))
W takim przypadku conv1 i conv2 mogą być wykonywane współbieżnie na procesorze GPU, co może poprawić wydajność.
Wymagania dotyczące stanu bariery zasobów
Jako obiekt wywołujący odpowiadasz za dopilnowanie, że wszystkie zasoby Direct3D 12 są w prawidłowym stanie bariery zasobów przed wykonaniem operacji DirectML na procesorze GPU. DirectML nie wykonuje żadnych barier przejścia samodzielnie.
Przed wykonaniem IDMLCommandRecorder::RecordDispatch na GPU, należy przenieść wszystkie powiązane zasoby do stanu D3D12_RESOURCE_STATE_UNORDERED_ACCESS lub do stanu niejawnie promowanego do D3D12_RESOURCE_STATE_UNORDERED_ACCESS, na przykład D3D12_RESOURCE_STATE_COMMON. Po zakończeniu tego połączenia, zasoby pozostają w stanie D3D12_RESOURCE_STATE_UNORDERED_ACCESS. Aby uzyskać więcej informacji, zobacz Binding in DirectML (Wiązanie w języku DirectML).