Guide des performances de Cloud TPU

Pour résoudre les problèmes de performances du TPU, la première étape consiste à profiler votre modèle. Pour en savoir plus sur la capture d'un profil de performances, consultez Profiler votre modèle sur Cloud TPU.

Performances des modèles TPU

Cette section décrit les problèmes généraux susceptibles de réduire les performances des modèles et explique comment les résoudre.

  1. Le modèle est lié aux entrées

    Les TPU effectuent des calculs très rapidement. Pour s'assurer que le TPU n'est pas inactif, il est important de s'assurer qu'un flux constant de données est chargé sur le TPU. La procédure à suivre dépend de la manière dont vous chargez et prétraitez votre ensemble de données. Par exemple, vous pouvez lire des fichiers de données en parallèle à l'aide de tf.data.TFRecordset(). et le paramètre num_parallel_reads.

  2. La taille de lot est trop petite en raison de la segmentation (répartition des lots sur plusieurs cœurs)

    L'environnement d'exécution TPU divise un lot sur les huit cœurs d'un appareil TPU (par exemple, v2-8 ou v3-8). Si vous spécifiez une taille de lot globale de 128, chaque cœur reçoit une taille de lot de 16 (128 / 8).

    Pour une utilisation optimale de la mémoire, utilisez la plus grande taille de lot adaptée à la mémoire TPU. Chaque cœur de TPU utilise des registres vectoriels bidimensionnels de 8 x 128 pour traiter les multiplications matricielles. En général, votre taille de lot doit être divisible de manière uniforme par 8 ou 128.

Optimisations du compilateur XLA

XLA est un compilateur de code capable de produire des binaires pour les TPU, les CPU, les GPU et d'autres plates-formes. XLA fait partie du code base TensorFlow standard, mais peut aussi être utilisé sur Modèles PyTorch et JAX. Modèles pour Cloud TPU sont convertis en graphe XLA, que XLA compile ensuite en TPU exécutable. Pour en savoir plus sur XLA, consultez XLA: optimiser le compilateur pour le machine learning.

Remplissage

Pour utiliser efficacement la mémoire TPU, structurez vos données de sorte qu'elles puissent être regroupées 128 x 8 morceaux. Lorsque les données d’un calcul matriciel ne remplissent pas tout un Bloc 128 x 8, le compilateur XLA remplit les Tensors. Cette méthode présente toutefois deux inconvénients :

  1. Les Tensors rembourrés sous-utilisent le cœur du TPU.
  2. Le remplissage augmente la quantité de mémoire sur puce requise pour un Tensor. Cette technique peut également entraîner une erreur de mémoire insuffisante.

Bien que le remplissage soit automatiquement effectué par le compilateur XLA en cas de besoin, vous pouvez déterminer la quantité de remplissage effectuée à l'aide de l'outil d'affichage de la mémoire. Vous pouvez éviter le remplissage en choisissant des dimensions de Tensor adaptées au TPU.

Dimensions de Tensor

Le compilateur XLA arrondit les tailles des Tensors stockés dans la mémoire du TPU HBM au effectuer des calculs plus efficacement. Cette marge intérieure est transparente au niveau le niveau matériel et n'affecte pas les résultats. Toutefois, dans certains cas, le remplissage peut entraîner une augmentation significative de l'utilisation de la mémoire et du temps d'exécution.

L'environnement d'exécution TPU organise les tenseurs en mémoire afin de maximiser l'efficacité des calculs et de minimiser le remplissage. Pour minimiser la surcharge de mémoire et optimiser les ressources de calcul l'efficacité, l'une des conditions suivantes doit être remplie:

  1. La taille totale du lot doit être un multiple de 64 (8 par cœur de TPU) et les dimensions des caractéristiques doivent être un multiple de 128.

  2. La taille totale du lot doit être un multiple de 1 024 (128 par cœur de TPU), et les dimensions des caractéristiques doivent être un multiple de huit.

L'efficacité maximale est atteinte avec une taille de lot de 1 024 et des dimensions de caractéristiques multiples de 128, bien que cela ne soit pas toujours possible pour tous les modèles.

Fusion

La Fusion est une technique générale que le compilateur XLA utilise pour optimiser les programmes. Une opération fusionnée est la combinaison de plusieurs opérations constitutives devant être exécutées ensemble.

Par exemple, considérons la série d'opérations suivante :

    tmp = tf.add(x, y)
    result = tf.multiply(tmp, z)

Ce code est à peu près équivalent au pseudo-code suivant :

    for (i = 0; i < element_count; i++) {
      tmp[i] = x[i] + y[i];
    }

    for (i = 0; i < element_count; i++) {
      result = tmp[i] * z[i];
    }

Avec la fusion, les accès au tableau surviennent en même temps :

    for (i = 0; i < element_count; i++) {
      result = (x[i] + y[i]) * z[i];
    }

Dans cet exemple, le nombre d'allers-retours de la mémoire est réduit, mais pas XLA besoin d'allouer de l'espace pour « tmp ».

La fusion est une optimisation critique et profite à Cloud TPU de plusieurs manières :

  • Elle réduit les transferts mémoire en éliminant la nécessité de stocker des résultats intermédiaires dans la mémoire principale, qui est lente.
  • Elle permet un usage accru des unités matérielles, qui autrement seraient inutilisées.
  • Elle peut réduire l'utilisation de la mémoire d'un modèle, car le nombre de tampons devant être actifs en même temps est moins élevé.

Broadcasting

Le broadcasting survient implicitement lorsque deux Tensors de formes différentes, mais compatibles, sont combinés.

Par exemple, tf.add(vector, matrix) nécessite que le vecteur soit broadcasté vers la forme de la matrice. Le résultat de l'opération a la même forme que la matrice. Pour en savoir plus, consultez le guide sur le broadcasting des tableaux.

Bien que les broadcasts puissent souvent être fusionnés avec leurs destinataires, le fait de les forcer à être des résultats matérialisés peut entraîner de mauvaises performances et une augmentation de l'utilisation de la mémoire.

Dans l'exemple suivant, le broadcast implicite dans l'ajout d'un vecteur et d'une matrice ne peut pas être fusionné avec l'argmax, ce qui entraîne sa matérialisation :

`tf.argmax(tf.add(vector, zero_matrix), axis=0)`