Utilisation d’opérateurs fusionnés pour améliorer les performances
Certains opérateurs DirectML prennent en charge un concept appelé fusion. La fusion d’opérateurs est un moyen d’améliorer les performances en fusionnant un opérateur (généralement une fonction d’activation) avec un autre opérateur afin qu’ils soient exécutés ensemble sans faire d’aller-retour à la mémoire.
Quand fusionner les activations
Les activations fusionnées sont une optimisation des performances. Un scénario extrêmement courant dans de nombreux modèles d’apprentissage automatique (ML) consiste à appliquer une non-linéarité (fonction d’activation) à la sortie de chaque couche du modèle.
En règle générale, cela nécessite un aller-retour à la mémoire graphique. Par exemple, si une convolution est suivie d’une activation Relu non fusionnée, le GPU doit attendre que les résultats de la convolution soient écrits en mémoire GPU avant de commencer à calculer la couche d’activation Relu. Étant donné que la charge de travail de calcul de la plupart des fonctions d’activation a tendance à être petite, cet aller-retour à la mémoire graphique peut être un goulot d’étranglement majeur des performances.
La fusion d’opérateurs permet à la fonction d’activation (Relu dans l’exemple ci-dessus) d’être effectuée dans le cadre de l’opérateur précédent (Convolution, par exemple). Cela permet au GPU de calculer la fonction d’activation sans attendre que les résultats de l’opérateur précédent soient écrits en mémoire, ce qui améliore les performances.
Étant donné que les activations fusionnées produisent le même résultat, mais sont plus rapides dans de nombreux cas, nous vous recommandons d’éliminer les couches d’activation en les fusionnant dans l’opérateur qui les précède dans la mesure du possible.
Comment fusionner les activations
Les opérateurs qui prennent en charge les activations fusionnées ont un paramètre facultatif supplémentaire dans leur struct d’opérateur, const DML_OPERATOR_DESC* FusedActivation
. Convolution, par exemple, prend en charge l’activation fusionnée et a une FusedActivation correspondant dans sa description d’opérateur (voir DML_CONVOLUTION_OPERATOR_DESC).
struct DML_CONVOLUTION_OPERATOR_DESC
{
const DML_TENSOR_DESC* InputTensor;
const DML_TENSOR_DESC* FilterTensor;
_Maybenull_ const DML_TENSOR_DESC* BiasTensor;
const DML_TENSOR_DESC* OutputTensor;
DML_CONVOLUTION_MODE Mode;
DML_CONVOLUTION_DIRECTION Direction;
UINT DimensionCount;
_Field_size_(DimensionCount) const UINT* Strides;
_Field_size_(DimensionCount) const UINT* Dilations;
_Field_size_(DimensionCount) const UINT* StartPadding;
_Field_size_(DimensionCount) const UINT* EndPadding;
_Field_size_(DimensionCount) const UINT* OutputPadding;
UINT GroupCount;
_Maybenull_ const DML_OPERATOR_DESC* FusedActivation;
};
Pour fusionner une activation, construisez une DML_OPERATOR_DESC qui décrit le type d’activation à fusionner. Par exemple, pour fusionner une fonction Relu, le type d’opérateur correct serait DML_OPERATOR_ACTIVATION_RELU.
Remarque
Lors de la construction de la description de l’opérateur pour la fonction d’activation, vous devez définir les paramètres de InputTensor et OutputTensor pour la fonction d’activation sur NULL.
Exemple
DML_ACTIVATION_LEAKY_RELU_OPERATOR_DESC leakyReluDesc;
leakyReluDesc.InputTensor = nullptr;
leakyReluDesc.OutputTensor = nullptr;
leakyReluDesc.Alpha = 0.01f;
DML_OPERATOR_DESC activationDesc = { DML_OPERATOR_ACTIVATION_LEAKY_RELU, &leakyReluDesc };
DML_CONVOLUTION_OPERATOR_DESC convDesc;
// ...
convDesc.FusedActivation = &activationDesc;
Pour obtenir un exemple complet, l’exemple DirectMLSuperResolution utilise des activations fusionnées pour améliorer les performances.
Opérateurs qui prennent en charge l’activation fusionnée
La liste ci-dessous est basée sur des constantes de l’énumération DML_OPERATOR_TYPE. Chaque constante de cette rubrique établit des liens vers la structure de description appropriée à utiliser.
- DML_OPERATOR_BATCH_NORMALIZATION
- DML_OPERATOR_BATCH_NORMALIZATION_TRAINING
- DML_OPERATOR_CONVOLUTION
- DML_OPERATOR_ELEMENT_WISE_ADD1
- DML_OPERATOR_GEMM
- DML_OPERATOR_MEAN_VARIANCE_NORMALIZATION
- DML_OPERATOR_MEAN_VARIANCE_NORMALIZATION1
Activations prises en charge pour fusion
La liste ci-dessous est basée sur des constantes de l’énumération DML_OPERATOR_TYPE. Chaque constante de cette rubrique établit des liens vers la structure de description appropriée à utiliser.
- DML_OPERATOR_ELEMENT_WISE_CLIP
- DML_OPERATOR_ACTIVATION_LINEAR
- DML_OPERATOR_ACTIVATION_SIGMOID
- DML_OPERATOR_ACTIVATION_HARD_SIGMOID
- DML_OPERATOR_ACTIVATION_TANH
- DML_OPERATOR_ACTIVATION_SCALED_TANH
- DML_OPERATOR_ACTIVATION_RELU
- DML_OPERATOR_ACTIVATION_LEAKY_RELU
- DML_OPERATOR_ACTIVATION_THRESHOLDED_RELU
- DML_OPERATOR_ACTIVATION_ELU
- DML_OPERATOR_ACTIVATION_CELU
- DML_OPERATOR_ACTIVATION_SCALED_ELU
- DML_OPERATOR_ACTIVATION_SOFTPLUS
- DML_OPERATOR_ACTIVATION_PARAMETRIC_SOFTPLUS
- DML_OPERATOR_ACTIVATION_SOFTSIGN
- DML_OPERATOR_ACTIVATION_IDENTITY
- DML_OPERATOR_ACTIVATION_SHRINK
- DML_OPERATOR_ACTIVATION_GELU
Les opérateurs qui ne figurent pas dans cette liste ne sont pas pris en charge pour l’activation fusionnée.