Delen via


Stapgroottes gebruiken om opvulling en geheugenindeling uit te drukken

DirectML-tensors, die worden ondersteund door Direct3D 12-buffers, worden beschreven door eigenschappen die bekend staan als de grootten en de stappen van de tensor. De grootten van de tensor beschrijven de logische dimensies van de tensor. Een 2D-tensor kan bijvoorbeeld een hoogte van 2 en een breedte van 3 hebben. Logisch gezien heeft de tensor 6 afzonderlijke elementen, hoewel de grootten niet aangeven hoe deze elementen in het geheugen worden opgeslagen. De stappen van de tensor beschrijven de fysieke geheugenindeling van de elementen van de tensor.

Tweedimensionale matrices (2D)

Overweeg een 2D-tensor met een hoogte van 2 en een breedte van 3; de gegevens bestaan uit tekstuele tekens. In C/C++ kan dit worden uitgedrukt met behulp van een multidimensionale matrix.

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';

De logische weergave van de bovenstaande tensor wordt hieronder gevisualiseerd.

A B C
D E F

In C/C++ wordt een multidimensionale matrix opgeslagen in rij-primaire volgorde. Met andere woorden, de opeenvolgende elementen langs de breedtedimensie worden aaneengesloten opgeslagen in lineaire geheugenruimte.

Afstand: 0 1 2 3 4 5
Waarde: Een B C D E F

De stapgrootte van een dimensie is het aantal elementen dat moet worden overgeslagen om het volgende element in die dimensie te bereiken. Strides geven de indeling van de tensor in het geheugen weer. Met een rijen-volgorde is de stapgrootte van de breedtedimensie altijd 1, omdat aangrenzende elementen langs de dimensie aaneengesloten worden opgeslagen. De stap van de hoogtedimensie is afhankelijk van de grootte van de breedtedimensie; in het bovenstaande voorbeeld is de afstand tussen opeenvolgende elementen langs de hoogtedimensie (bijvoorbeeld van A naar D) gelijk aan de breedte van de tensor (die in dit voorbeeld 3 is).

Als u een andere indeling wilt illustreren, kunt u kolomvolgorde overwegen. Met andere woorden, de opeenvolgende elementen langs de hoogtedimensie worden aaneengesloten opgeslagen in lineaire geheugenruimte. In dit geval is de hoogte-stride altijd 1 en is de breedte-stride 2 (de grootte van de breedtedimensie).

Afstand: 0 1 2 3 4 5
Waarde: Een D B E C F

Hogere dimensies

Als het gaat om meer dan twee dimensies, is het onhandig om een indeling rij-georiënteerd of kolom-georiënteerd te noemen. In de rest van dit onderwerp worden termen en labels gebruikt, zoals deze.

  • 2D: "HW": hoogte is de hoogste-volgordedimensie (rij-primaire).
  • 2D: "WH"—breedte is de hoogste volgordedimensie (kolom-major).
  • 3D: "DHW": diepte is de hoogste ordedimensie, gevolgd door hoogte en vervolgens breedte.
  • 3D: "WHD": breedte is de hoogste ordedimensie, gevolgd door hoogte en vervolgens diepte.
  • 4D: 'NCHW': het aantal afbeeldingen (batchgrootte), vervolgens het aantal kanalen, de hoogte en de breedte.

Over het algemeen is de verpakte stapgrootte van een dimensie gelijk aan het product van de afmetingen van de lagere volgorde. Met een "DHW"-indeling is de D-stride bijvoorbeeld gelijk aan H * W; de H-stride is gelijk aan W; en de W-stride is gelijk aan 1. De stappen worden ingepakt wanneer de totale fysieke grootte van de tensor gelijk is aan de totale logische grootte van de tensor; met andere woorden, er is geen extra ruimte of overlappende elementen.

Laten we het 2D-voorbeeld uitbreiden naar drie dimensies, zodat we een tensor hebben met diepte 2, hoogte 2 en breedte 3 (voor een totaal van 12 logische elementen).

A B C
D E F

G H I
J K L

Met een DHW-indeling wordt deze tensor als volgt opgeslagen.

Afstand: 0 1 2 3 4 5 6 7 8 9 10 11
Waarde: Een B C D E F G H Ik J K L
  • D-stride = hoogte (2) * breedte (3) = 6 (bijvoorbeeld de afstand tussen 'A' en 'G').
  • H-stride = width (3) = 3 (bijvoorbeeld de afstand tussen 'A' en 'D').
  • W-stride = 1 (bijvoorbeeld de afstand tussen 'A' en 'B').

Het puntproduct van de indexen/coördinaten van een element en de stappen biedt de verschuiving naar dat element in de buffer. De verschuiving van het H-element (d=1, h=0, w=1) is bijvoorbeeld 7.

{1, 0, 1} ⋅ {6, 3, 1} = 1 * 6 + 0 * 3 + 1 * 1 = 7

Verpakte tensoren

De bovenstaande voorbeelden illustreren verpakte tensors. Een tensor wordt verpakt genoemd wanneer de logische grootte van de tensor (in elementen) gelijk is aan de fysieke grootte van de buffer (in elementen) en elk element een uniek adres/offset heeft. Een tensor van 2x2x3 wordt bijvoorbeeld verpakt als de buffer 12 elementen lang is en geen enkele paar elementen dezelfde offset in de buffer delen. Verpakte tensors zijn het meest voorkomende geval; maar tredes kunnen complexere geheugenindelingen mogelijk maken.

Uitzenden met stappen

Als de buffergrootte van een tensor (in elementen) kleiner is dan het product van de logische dimensies, moet er een aantal overlappende elementen zijn. De gebruikelijke zaak hiervoor staat bekend als uitzenden; waarbij de elementen van een dimensie een duplicaat van een andere dimensie zijn. Laten we bijvoorbeeld het 2D-voorbeeld opnieuw bekijken. Stel dat we een tensor willen die logisch 2x3 is, maar de tweede rij is identiek aan de eerste rij. Dit ziet er als volgt uit.

A B C
A B C

Dit kan worden opgeslagen als een verpakte HW/rij-primaire tensor. Maar een compactere opslag bevat slechts 3 elementen (A, B en C) en gebruikt een hoogte-stride van 0 in plaats van 3. In dit geval is de fysieke grootte van de tensor 3 elementen, maar de logische grootte is 6 elementen.

In het algemeen, als de stride van een dimensie 0 is, worden alle elementen in de dimensies in de lagere volgorde herhaald langs de uitgezonden dimensie; Als de tensor bijvoorbeeld NCHW is en de C-stride 0 is, heeft elk kanaal dezelfde waarden langs H en W.

Opvulling met stappen

Een tensor wordt beschouwd als opgevuld als de fysieke grootte groter is dan de minimale grootte die nodig is om de elementen te bevatten. Wanneer er geen uitzendings- of overlappende elementen zijn, is de minimale grootte van de tensor (in elementen) gewoon het product van de afmetingen. U kunt de helperfunctie DMLCalcBufferTensorSize (zie DirectML-helperfuncties voor een lijst met die functie) gebruiken om de minimale buffergrootte voor uw DirectML-tensors te berekenen.

Stel dat een buffer de volgende waarden bevat (de 'x'-elementen geven opvullingswaarden aan).

0 1 2 3 4 5 6 7 8 9
Een B C x x D E F x x

De opgevulde tensor kan worden beschreven met behulp van een hoogte-stride van 5 in plaats van 3. In plaats van met drie elementen te stappen om naar de volgende rij te gaan, is de stap 5 elementen (3 echte elementen plus 2 opvullingselementen). Opvulling is gebruikelijk bij computergraphics, bijvoorbeeld om ervoor te zorgen dat een afbeelding een uitlijning heeft die een macht van twee is.

A B C
D E F

Beschrijvingen van DirectML-buffertensor

DirectML kan werken met verschillende fysieke tensor-indelingen, omdat de DML_BUFFER_TENSOR_DESC structuur zowel als SizesStrides leden heeft. Sommige implementaties van operators kunnen efficiënter zijn met een specifieke indeling, dus het is niet ongebruikelijk om te wijzigen hoe tensor-gegevens worden opgeslagen voor betere prestaties.

De meeste DirectML-operators vereisen 4D- of 5D-tensors en de volgorde van de grootten en stappenwaarden is vast. Door de volgorde van de grootten en de stride-waarden in een tensorbeschrijving vast te stellen, kan DirectML verschillende fysieke indelingen afleiden.

4D

5D

  • DML_BUFFER_TENSOR_DESC::Maten = { N-maat, C-maat, D-maat, H-maat, W-maat }
  • DML_BUFFER_TENSOR_DESC::Stappen = { N-stap, C-stap, D-stap, H-stap, W-stap }

Als een DirectML-operator een 4D- of 5D-tensor vereist, maar de werkelijke gegevens een kleinere rang hebben (bijvoorbeeld 2D), moeten de voorloopdimensies worden gevuld met 1s. Een 'HW'-tensor wordt bijvoorbeeld ingesteld met behulp van DML_BUFFER_TENSOR_DESC::Sizes = { 1, 1, H, W }.

Als tensor-gegevens worden opgeslagen in NCHW/NCDHW, is het niet nodig om DML_BUFFER_TENSOR_DESC::Strides in te stellen, tenzij u wilt uitzenden of opvulling. U kunt het veld 'stappen' instellen op nullptr. Als de tensorgegevens echter worden opgeslagen in een andere indeling, zoals NHWC, hebt u stappen nodig om de transformatie van NCHW naar die indeling uit te drukken.

Bekijk voor een eenvoudig voorbeeld de beschrijving van een 2D-tensor met hoogte 3 en breedte 5.

Verpakte NCHW (impliciete stappen)

  • DML_BUFFER_TENSOR_DESC::Maten = { 1, 1, 3, 5 }
  • DML_BUFFER_TENSOR_DESC::Stappen = nullptr

Verpakte NCHW (expliciete stappen)

  • N-stride = C-maat * H-size * W-size = 1 * 3 * 5 = 15
  • C-stride = H-grootte * W-grootte = 3 * 5 = 15
  • H-stap = W-grootte = 5
  • W-stap = 1
  • DML_BUFFER_TENSOR_DESC::Maten = { 1, 1, 3, 5 }
  • DML_BUFFER_TENSOR_DESC::Stappen = { 15, 15, 5, 1 }

Verpakt NHWC

  • N-stap = H-grootte * W-grootte * C-grootte = 3 * 5 * 1 = 15
  • H-stap = W-maat * C-maat = 5 * 1 = 5
  • W-stap = C-maat = 1
  • C-stap = 1
  • DML_BUFFER_TENSOR_DESC::Maten = { 1, 1, 3, 5 }
  • DML_BUFFER_TENSOR_DESC::Stappen = { 15, 1, 5, 1 }

Zie ook