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.
Os tensores DirectML, que são suportados por buffers Direct3D 12, são descritos por propriedades conhecidas como os tamanhos e os passos do tensor. Os tamanhos do tensor descrevem as dimensões lógicas do tensor. Por exemplo, um tensor 2D pode ter uma altura de 2 e uma largura de 3. Logicamente, o tensor tem 6 elementos distintos, embora os tamanhos não especifiquem como esses elementos são armazenados na memória. Os passos do tensor descrevem o layout da memória física dos elementos do tensor.
Matrizes bidimensionais (2D)
Considere um tensor 2D que tenha uma altura de 2 e uma largura de 3; Os dados são compostos por caracteres textuais. Em C/C++, isso pode ser expresso usando uma matriz multidimensional.
constexpr int rows = 2;
constexpr int columns = 3;
char tensor[rows][columns];
tensor[0][0] = 'A';
tensor[0][1] = 'B';
tensor[0][2] = 'C';
tensor[1][0] = 'D';
tensor[1][1] = 'E';
tensor[1][2] = 'F';
A visão lógica do tensor acima é visualizada abaixo.
A B C
D E F
Em C/C++, uma matriz multidimensional é armazenada em ordem de linha maior. Em outras palavras, os elementos consecutivos ao longo da dimensão de largura são armazenados contíguamente no espaço de memória linear.
| Compensação: | 0 | 1 | 2 | 3 | 4 | 5 |
|---|---|---|---|---|---|---|
| Valor: | Um | B | C | D | E | F |
O deslocamento de uma dimensão é o número de elementos a serem ignorados para aceder ao próximo elemento nessa dimensão. Strides expressam o layout do tensor na memória. Com uma ordem de armazenamento por linhas, o passo da dimensão da largura é sempre 1, uma vez que os elementos adjacentes na dimensão são armazenados de forma contígua. O passo da dimensão altura depende da largura da dimensão; no exemplo acima, a distância entre elementos consecutivos ao longo da dimensão altura (por exemplo, de A até D) é igual à largura do tensor, que neste caso é 3.
Para ilustrar um layout diferente, considere a ordem principal das colunas. Em outras palavras, os elementos consecutivos ao longo da dimensão altura são armazenados contíguamente no espaço de memória linear. Neste caso, o passo de altura é sempre 1, e o passo de largura é 2 (o tamanho da dimensão largura).
| Compensação: | 0 | 1 | 2 | 3 | 4 | 5 |
|---|---|---|---|---|---|---|
| Valor: | Um | D | B | E | C | F |
Dimensões superiores
Quando se trata de mais de duas dimensões, é complicado referir-se a um layout como linha maior ou coluna maior. Assim, o resto deste tópico usa termos e rótulos como estes.
- 2D: "HW" — altura é a dimensão de ordem mais alta (prioridade por linha).
- 2D: "WH"—largura é a dimensão de ordem mais alta (coluna maior).
- 3D: "PHL" — profundidade é a dimensão de ordem mais alta, seguida pela altura e, em seguida, pela largura.
- 3D: "WHD" — largura é a dimensão de maior ordem, seguida pela altura e, em seguida, pela profundidade.
- 4D: "NCHW" — o número de imagens (tamanho do lote), depois o número de canais, depois a altura e, em seguida, a largura.
Em geral, o passo compactado de uma dimensão é igual ao produto dos tamanhos das dimensões de ordem inferior. Por exemplo, com um layout "AQS", a passada D é igual a H * W; a passada H é igual a W; e a passada W é igual a 1. Diz-se que os passos são compactos quando o tamanho físico total do tensor é igual ao tamanho lógico total do tensor; por outras palavras, não há espaço extra nem elementos sobrepostos.
Vamos estender o exemplo 2D para três dimensões, de modo que tenhamos um tensor com profundidade 2, altura 2 e largura 3 (para um total de 12 elementos lógicos).
A B C
D E F
G H I
J K L
Com um layout "DHW", este tensor é armazenado da seguinte forma.
| Compensação: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Valor: | Um | B | C | D | E | F | G | H | Eu | J | K | L |
- D-stride = altura (2) * largura (3) = 6 (por exemplo, a distância entre 'A' e 'G').
- H-stride = largura (3) = 3 (por exemplo, a distância entre 'A' e 'D').
- W-stride = 1 (por exemplo, a distância entre 'A' e 'B').
O produto escalar dos índices/coordenadas de um elemento e os incrementos determina o deslocamento desse elemento no buffer. Por exemplo, o deslocamento do elemento H (d=1, h=0, w=1) é 7.
{1, 0, 1} ⋅ {6, 3, 1} = 1 * 6 + 0 * 3 + 1 * 1 = 7
Tensores embalados
Os exemplos acima ilustram tensores compactados . Diz-se que um tensor é embalado quando o tamanho lógico do tensor (em elementos) é igual ao tamanho físico do buffer (em elementos), e cada elemento tem um endereço/deslocamento exclusivo. Por exemplo, um tensor 2x2x3 é compactado se o buffer tiver 12 elementos de comprimento e nenhum par de elementos compartilhar o mesmo deslocamento no buffer. Os tensores embalados são o caso mais comum; mas os avanços permitem layouts de memória mais complexos.
Radiodifusão com avanços
Se o tamanho do buffer de um tensor (em elementos) é menor do que o produto de suas dimensões lógicas, então segue-se que deve haver alguma sobreposição de elementos. O caso habitual é conhecido como radiodifusão; onde os elementos de uma dimensão são uma duplicação de outra dimensão. Por exemplo, vamos revisitar o exemplo 2D. Digamos que queremos um tensor que seja logicamente 2x3, mas a segunda linha é idêntica à primeira linha. Veja como fica.
A B C
A B C
Isso pode ser armazenado como um tensor HW/linha-maior compactado. Mas um armazenamento mais compacto conteria apenas 3 elementos (A, B e C) e usaria uma "stride" de altura de 0 em vez de 3. Neste caso, o tamanho físico do tensor é de 3 elementos, mas o tamanho lógico é de 6 elementos.
Em geral, se o passo de uma dimensão é 0, então todos os elementos nas dimensões de ordem inferior são repetidos ao longo da dimensão difundida; por exemplo, se o tensor é NCHW e o passo do C é 0, então cada canal tem os mesmos valores ao longo de H e W.
Acolchoamento com passadas
Diz-se que um tensor é preenchido se o seu tamanho físico for maior do que o tamanho mínimo necessário para acomodar os seus elementos. Quando não há transmissão nem elementos sobrepostos, o tamanho mínimo do tensor (em elementos) é simplesmente o produto de suas dimensões. Você pode usar a função DMLCalcBufferTensorSize auxiliar (consulte Funções auxiliares do DirectML para obter uma lista dessa função) para calcular o tamanho mínimo do buffer para seus tensores DirectML.
Digamos que um buffer contenha os seguintes valores (os elementos 'x' indicam valores de preenchimento).
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|---|---|---|---|---|---|---|---|---|---|
| Um | B | C | x | x | D | E | F | x | x |
O tensor acolchoado pode ser descrito utilizando um passo de altura de 5 em vez de 3. Em vez de passar por 3 elementos para chegar à próxima linha, a etapa é de 5 elementos (3 elementos reais mais 2 elementos de preenchimento). O preenchimento é comum na computação gráfica, por exemplo, para garantir que uma imagem tenha um alinhamento de potência de dois.
A B C
D E F
Descrições do tensor de buffer DirectML
O DirectML pode trabalhar com uma variedade de layouts de tensores físicos, uma vez que a estrutura DML_BUFFER_TENSOR_DESC tem ambos os membros Sizes e Strides. Algumas implementações de operador podem ser mais eficientes com um layout específico, por isso não é incomum alterar a forma como os dados tensores são armazenados para um melhor desempenho.
A maioria dos operadores do DirectML requer tensores 4D ou 5D, e a ordem dos tamanhos e valores de deslocamentos é fixa. Ao fixar a ordem dos tamanhos e dos valores de passo numa descrição de tensor, o DirectML consegue inferir diferentes layouts físicos.
4D
- DML_BUFFER_TENSOR_DESC::Tamanhos = { N-size, C-size, H-size, W-size }
- DML_BUFFER_TENSOR_DESC::Passos = { N-stride, C-stride, H-stride, W-stride }
5D
- DML_BUFFER_TENSOR_DESC::Tamanhos = { tamanho-N, tamanho-C, tamanho-D, tamanho-H, tamanho-W }
- DML_BUFFER_TENSOR_DESC::Passos = { N-stride, C-stride, D-stride, H-stride, W-stride }
Se um operador DirectML requer um tensor 4D ou 5D, mas os dados reais têm uma classificação menor (por exemplo, 2D), então as dimensões principais devem ser preenchidas com 1s. Por exemplo, um tensor "HW" é definido usando DML_BUFFER_TENSOR_DESC::Sizes = { 1, 1, H, W }.
Se os dados do tensor forem armazenados em NCHW/NCDHW, não é necessário definir DML_BUFFER_TENSOR_DESC::Strides, a menos que você queira transmitir ou preencher. Você pode definir o campo de passadas como nullptr. No entanto, se os dados tensores forem armazenados em outro layout, como NHWC, você precisará de avanços para expressar a transformação de NCHW para esse layout.
Para um exemplo simples, considere a descrição de um tensor 2D com altura 3 e largura 5.
NCHW compactado (avanços implícitos)
- DML_BUFFER_TENSOR_DESC::Tamanhos = { 1, 1, 3, 5 }
-
DML_BUFFER_TENSOR_DESC::Passos =
nullptr
NCHW embalado (passos explícitos)
- N-stride = C-size * H-size * W-size = 1 multiplicado por 3 multiplicado por 5 = 15
- C-stride = tamanho H * tamanho W = 3 * 5 = 15
- Passada H = Tamanho W = 5
- W-passo = 1
- DML_BUFFER_TENSOR_DESC::Tamanhos = { 1, 1, 3, 5 }
- DML_BUFFER_TENSOR_DESC::Passadas = { 15, 15, 5, 1 }
NHWC compactado
- N-stride = tamanho H * tamanho W * tamanho C = 3 * 5 * 1 = 15
- H-stride = tamanho W * tamanho C = 5 * 1 = 5
- W-stride = tamanho C = 1
- C-passada = 1
- DML_BUFFER_TENSOR_DESC::Tamanhos = { 1, 1, 3, 5 }
- DML_BUFFER_TENSOR_DESC::Passadas = { 15, 1, 5, 1 }
Ver também
- de IA do Windows
- Funções auxiliares do DirectML
- Estrutura DML_BUFFER_TENSOR_DESC