Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Requisitos de barreira de visualização de acesso não ordenado (UAV)
Barreiras de UAV no Direct3D 12
No Direct3D 12, os despachos de sombreador de computação adjacentes dentro da mesma lista de comandos podem ser executados em paralelo na GPU, a menos que estejam sincronizados com uma barreira de visualização de acesso não ordenado (UAV) interveniente. Isso pode melhorar o desempenho aumentando a utilização do hardware da GPU. No entanto, por padrão, sem o uso de uma barreira UAV, a execução paralela de dois despachos adjacentes pode causar uma condição de corrida se existir uma dependência de dados entre os dois despachos; ou se ambos os despachos executarem gravações UAV nas mesmas regiões de memória.
Uma barreira de UAV força todos os despachos enviados anteriormente a concluir a execução na GPU antes que os despachos subsequentes possam começar. As barreiras de UAV são usadas para sincronizar entre despachos na mesma lista de comandos para evitar corridas de dados. Você pode emitir uma barreira UAV usando o método ID3D12GraphicsCommandList::ResourceBarrier.
Barreiras de UAV no DirectML
No DirectML, os operadores são despachados de forma semelhante à maneira como os sombreadores de computação são despachados no Direct3D 12. Ou seja, despachos adjacentes de operadores podem ser executados em paralelo na GPU, a menos que exista uma barreira de UAV interveniente entre eles. Um modelo típico de aprendizado de máquina contém dependências de dados entre seus operadores; por exemplo, a saída de um operador alimenta a entrada de outro. Portanto, é importante usar barreiras de UAV para sincronizar corretamente os despachos.
O DirectML garante que ele só vai ler (e nunca gravar em) tensores de entrada. Ele também garante que nunca fabricará gravações em um tensor de saída fora do intervalo do membro DML_BUFFER_TENSOR_DESC::TotalTensorSizeInBytes do tensor. Isso significa que as dependências de dados entre operadores no DirectML podem ser raciocinadas examinando apenas as ligações de entrada e saída de um operador.
Por exemplo, essas garantias permitem que você despache dois operadores que ligam a mesma região de um recurso como entrada, sem ter que emitir uma barreira de UAV interveniente. Isso é sempre seguro porque o DirectML nunca grava em tensores de entrada. Como outro exemplo, é sempre seguro vincular os tensores de saída de dois despachos de operadores simultâneos ao mesmo recurso Direct3D 12 (desde que seus tensores não se sobreponham), porque o DirectML nunca grava fora dos limites de um tensor (conforme definido pelo DML_BUFFER_TENSOR_DESC::TotalTensorSizeInBytes do tensor).
Como as barreiras de UAV são uma forma de sincronização, o uso desnecessário de barreiras de UAV pode afetar negativamente o desempenho. Portanto, é melhor para você usar o número mínimo de barreiras de UAV necessário para sincronizar corretamente os despachos dentro de uma lista de comandos.
Exemplo 1
No exemplo a seguir, a saída de um operador de convolução é alimentada em uma ativação ReLU, seguida por uma normalização em lote.
CONVOLUTION (conv1)
|
ACTIVATION_RELU (relu1)
|
BATCH_NORMALIZATION (batch1)
Como existe uma dependência de dados entre os três operadores, você precisará de uma barreira de UAV entre cada despacho sucessivo (consulte IDMLCommandRecorder::RecordDispatch).
-
dmlCommandRecorder->RecordDispatch(d3d12CommandList,conv1) -
d3d12CommandList->ResourceBarrier(Barreira UAV) -
dmlCommandRecorder->RecordDispatch(d3d12CommandList,RELU1) -
d3d12CommandList->ResourceBarrier(Barreira UAV) -
dmlCommandRecorder->RecordDispatch(d3d12CommandList,lote 1)
Exemplo 2
MAX_POOLING (pool1)
/ \
CONVOLUTION CONVOLUTION
(conv1) (conv2)
\ /
JOIN (join1)
Aqui, a saída do pooling é alimentada em duas convoluções, cujas saídas são então concatenadas usando o operador JOIN. Existe uma dependência de dados entre pool1 e ambos conv1 e conv2; bem como entre ambos conv1 e conv2 e join1. Aqui está uma maneira válida de executar este gráfico.
-
dmlCommandRecorder->RecordDispatch(d3d12CommandList,piscina1) -
d3d12CommandList->ResourceBarrier(Barreira UAV) -
dmlCommandRecorder->RecordDispatch(d3d12CommandList,conv1) -
dmlCommandRecorder->RecordDispatch(d3d12CommandList,conv2) -
d3d12CommandList->ResourceBarrier(Barreira UAV) -
dmlCommandRecorder->RecordDispatch(d3d12CommandList,juntar-se1)
Neste caso, conv1 e conv2 são capazes de executar simultaneamente na GPU, o que pode melhorar o desempenho.
Requisitos de estado de barreira de recursos
Como chamador, é sua responsabilidade garantir que todos os recursos do Direct3D 12 estejam no estado correto de barreira de recursos antes de executar despachos DirectML na GPU. O DirectML não executa nenhuma barreira de transição em seu nome.
Antes da execução de IDMLCommandRecorder::RecordDispatch na GPU, você deve fazer a transição de todos os recursos vinculados para o estado D3D12_RESOURCE_STATE_UNORDERED_ACCESS ou para um estado implicitamente promocional para D3D12_RESOURCE_STATE_UNORDERED_ACCESS, como D3D12_RESOURCE_STATE_COMMON. Após a conclusão dessa chamada, os recursos permanecem no estado D3D12_RESOURCE_STATE_UNORDERED_ACCESS . Para obter mais detalhes, consulte Vinculação em DirectML.