Fehlerbehebung bei TensorFlow – TPU

Dieser Leitfaden bietet zusammen mit den FAQ eine Anleitung zur Fehlerbehebung für Nutzer, die TensorFlow-Modelle auf Cloud TPU trainieren. Informationen zur Fehlerbehebung bei Pytorch- oder JAX-Trainings finden Sie in den Dokumenten zur Fehlerbehebung für diese Frameworks:

Allgemeine Anleitungen zur Verwendung von Cloud TPU finden Sie unter:

Übersicht

Häufige Probleme, die bei Cloud TPUs auftreten, fallen in die folgenden Kategorien:

  1. Probleme beim Herstellen einer Verbindung zur TPU

  2. Häufige Fehler beheben

  3. Arbeitsspeichernutzung reduzieren

  4. Trainingsgeschwindigkeit verbessern

  5. Fehlerbehebung bei sinkenden Modellgenauigkeiten

Fehler beim Herstellen einer Verbindung zum TPU-Server

In diesem Abschnitt wird beschrieben, wie Sie Fehler beheben, in denen TensorFlow aufhört, auf die TPU zu reagieren, oder einen Fehler ausgibt, wenn eine Verbindung zur TPU hergestellt wird. Beachten Sie, dass der Schritt zur Kompilierung des TPU-Graphen bei großen Modellen sehr lange dauern kann. Das Skript sollte daher mindestens 5 Minuten lang ausgeführt werden, um zu ermitteln, ob wirklich keine Antworten mehr erfolgen.

Der erste Schritt besteht darin, zu überprüfen, ob es sich um ein Problem mit dem Server selbst oder mit Ihrer TensorFlow-Trainings-Pipeline handelt. Führen Sie dazu die Schritte der MNIST-Anleitung über Ihre TPU-Server-URL aus und überprüfen Sie, ob sie ordnungsgemäß funktioniert. Wenn weiterhin Probleme beim Herstellen der Verbindung mit der MNIST-Anleitung bestehen, bestätigt dies, dass ein Problem beim TPU-Server vorliegt. In diesem Fall gilt:

  1. Führen Sie den folgenden Befehl aus, um die verfügbaren TPUs aufzulisten. Ersetzen Sie zone und project-id durch die Zone und die Projekt-ID.

    (vm)$ gcloud compute tpus list --zone zone --project project-id
    

    Dabei wird beispielsweise Folgendes ausgegeben:

    NAME       ZONE           ACCELERATOR_TYPE  NETWORK_ENDPOINT   NETWORK  RANGE          STATUS
    demo-tpu   us-central1-b  v2-8              10.240.1.2:8470    default  10.240.1.0  READY

  2. Prüfen Sie, ob Sie den richtigen Wert an --tpu übergeben haben (demo-tpu im Beispiel oben) und ob diese TPU als READY gelistet ist.

  3. Wenn Ihre TPU nicht als READY gelistet ist oder Sie weiterhin keine Verbindung herstellen können, starten Sie den Server hiermit manuell neu:

    (vm)$ gcloud compute tpus stop $TPU_SERVER_NAME && gcloud compute tpus start $TPU_SERVER_NAME

    $TPU_SERVER_NAME im obigen Beispiel entspricht demo-tpu. Dies kann einige Minuten dauern.

  4. Führen Sie den oben genannten Befehl ... tpus list noch einmal aus und warten Sie, bis sich die TPU im READY befindet. Dieser Vorgang kann einige Minuten dauern.

  5. Versuchen Sie, die MNIST-Anleitung noch einmal auszuführen.

  6. Wenn Sie weiterhin Probleme beim Ausführen der MNIST-Anleitung haben, können Sie über einen der unter Support beschriebenen Wege Unterstützung anfordern.

Wenn das MNIST-Beispiel korrekt ausgeführt wird, Ihr Modell jedoch weiterhin nicht reagiert, ist das Problem wahrscheinlich auf Ihre Trainingspipeline zurückzuführen. Ersetzen Sie zuerst die TPUStrategy im Code durch die Standardstrategie, um dieses Problem zu beheben. Wenn Sie die Standardstrategie verwenden, wird das Modell überall dort, wo Sie strategy.scope() oder strategy.run() verwenden, auf der CPU (oder gegebenenfalls der GPU) und nicht auf der TPU ausgeführt. Wenn das Modell auf CPU und nicht auf TPU ausgeführt wird, muss es ein TPU-spezifisches Problem geben. Wenn es immer noch nicht ausgeführt wird, sollten Sie das Problem auf der CPU beheben.

Verlust der ssh-Verbindung während des Trainings

Bei einer ssh-Verbindung zur Cloud TPU kann während eines lang andauernden Trainings eine Zeitüberschreitung auftreten (insbesondere, wenn Sie die Cloud Shell verwenden). An diesem Punkt wird keine Ausgabe an die TPU-Konsole gesendet und es sieht so aus, als ob die TPU das Training beendet hat. Führen Sie die Trainingssitzung mit einem Terminal-Multiplexer oder einem Sitzungsverwaltungstool wie tmux oder screen aus, um dies zu vermeiden. Dadurch bleibt die ssh-Verbindung unabhängig von der Länge des Trainings aktiviert.

Behebung von allgemeinen Fehlern

Das lokale Dateisystem kann nicht verwendet werden.

Fehlermeldung

InvalidArgumentError: Unimplemented: File system scheme '[local]' not implemented

Betroffene Frameworks und Konfigurationen

Diese Meldung kann auftreten, wenn Sie mit TensorFlow mithilfe der TPU-Knotenarchitektur trainieren.

Details

Alle Eingabedateien und das Modellverzeichnis müssen einen Pfad zu einem Cloud Storage-Bucket verwenden (gs://bucket-name/... ) und dieser Bucket muss über den TPU-Server zugänglich sein. Beachten Sie, dass alle Datenverarbeitungs- und Modellprüfpunkte auf dem TPU-Server und nicht auf dem lokalen Computer ausgeführt werden. Informationen zum ordnungsgemäßen Konfigurieren von Cloud Storage für die Verwendung mit der TPU finden Sie im Leitfaden Verbindung mit Cloud Storage-Buckets herstellen.

Nicht unterstützter Datentyp

Fehlermeldung

TypeError: DataType is not a supported TPU infeed type.

Betroffene Frameworks und Konfigurationen

Diese Meldung kann auftreten, wenn Sie mit TensorFlow mithilfe der TPU-Knotenarchitektur trainieren.

Details

Derzeit werden auf der TPU nur die Datentypen tf.float32, tf.int32, tf.bfloat16 und tf.bool unterstützt. Andere gängige Datentypen wie tf.uint8, tf.string und tf.int64 müssen während der Datenvorverarbeitung in einen der unterstützten Datentypen konvertiert werden, also in der tf.data.Dataset-Pipeline).

Ein Beispiel der Conversion in der Funktion decode_image finden Sie im MNIST-Training.

Dynamische Formen werden nicht unterstützt

Fehlermeldung

ValueError: shape [Shape] must have a fixed size for dimension d that is known at graph construction time.

Betroffene Frameworks und Konfigurationen

Diese Meldung wird nur während der XLA-Kompilierung mit TensorFlow angezeigt.

Details

Zum Ausführen eines Modells auf der TPU kompiliert TensorFlow das Modell mit dem XLA-Compiler. Dieser Kompilierungsschritt verbessert zwar die Trainingsgeschwindigkeit und die Speichernutzung erheblich, die Formen (Dimensionsgrößen) aller Tensoren im Diagramm müssen jedoch bei der Kompilierungszeit des Diagramms bekannt sein. Wenn beim Kompilieren keine Formen erkannt werden können, schlägt die TPU-Kompilierung mit einem Fehler wie dem obigen fehl.

Ein häufiger Vorgang, der eine dynamische Form zurückgibt, ist dataset.batch(batch_size), da die Anzahl der in einem Stream verbleibenden Stichproben möglicherweise kleiner als die Batchgröße ist. Setzen Sie daher beim Training auf der TPU drop remainder=True auf dataset.batch. Dadurch werden möglicherweise die letzten Beispiele aus einer Datei gelöscht, damit jeder Batch eine statische Form von batch_size hat. Beispiel:

dataset = tf.data.Dataset.range(8)
dataset = dataset.batch(3, drop_remainder=True)

Nicht verfügbare TensorFlow-Operation

Fehlermeldung

NotFoundError: No registered 'OpName' OpKernel for XLA_TPU_JIT devices compatible with node

Betroffene Frameworks und Konfigurationen

Diese Meldung kann beim Training mit TensorFlow auftreten.

Details

Das Modell verwendet eine TensorFlow-Operation, die derzeit nicht auf der TPU verfügbar ist.

Eine Liste der auf der TPU verfügbaren Operationen sowie Pläne für zukünftige Unterstützung und Vorschläge für Workarounds finden Sie in der Anleitung zu verfügbaren TensorFlow-Operationen.

Fehlermeldung aufgrund von fehlendem Speicherplatz

Fehlermeldung

ResourceExhaustedError: Ran out of memory in memory space hbm; used: YYY; limit: 7.48G.

Betroffene Frameworks und Konfigurationen

Diese Meldung kann auftreten, wenn Sie mit TensorFlow, PyTorch oder JAX trainieren.

Details

Jede Cloud TPU besteht aus acht TPU-Kernen, v2 TPUs haben 8 GB und v3 TPUs haben 16 GB RAM (oder HBM, High-Bandwidth Memory). Dieser Speicher dient zum Speichern der Gewichtungssensoren (Variable) sowie der Zwischenergebnistensoren, die für die Gradientenberechnung benötigt werden. Wenn das Modell für den TPU-RAM zu groß ist, schlägt die Initialisierung fehl und die obige Fehlermeldung wird ausgegeben. Weitere Informationen finden Sie unter Arbeitsspeichernutzung reduzieren.

Tipps zum Reduzieren des Arbeitsspeicherverbrauchs:

Probleme beim Beenden der Ausführung

Wenn TensorFlow während der TPU-Ausführung einen Fehler feststellt, scheint das Skript manchmal hängen zu bleiben, anstatt die Operation zu beenden und zur Shell zurückzukehren. Drücken Sie in diesem Fall die Tastenkombination CTRL+\ auf der Tastatur, um einen SIGQUIT auszulösen, wodurch Python sofort beendet wird.

Entsprechend wird mit der Tastenkombination CTRL+C während der TPU-Ausführung TensorFlow nicht sofort heruntergefahren, sondern bis zum Ende der aktuellen Iterationsschleife gewartet, um die Operation ordnungsgemäß zu beenden.

Wenn beim erneuten Herstellen einer Verbindung zur TPU nach einem solchen Exit neue Fehler auftreten, setzen Sie den TPU-Server mit dem folgenden Befehl manuell zurück:

gcloud compute tpus stop tpu-name --zone=zone && gcloud compute tpus start tpu-name --zone=zone

Dabei wird tpu-name aus der ersten Spalte übernommen, die mit dem Befehl gcloud compute tpus list angezeigt wird, und zone ist die Zone, die in der zweiten Spalte angezeigt wird.

Übermäßiges Padding von Tensoren

Mögliche Ursache des Speicherproblems

Tensoren im TPU-Speicher werden mit Leerzeichen aufgefüllt, d. h. die TPU rundet die Größen von Tensoren ab, die im Speicher abgelegt sind, damit Berechnungen effizienter durchgeführt werden. Das Padding erfolgt auf transparente Weise auf der Hardwareebene und hat keine Auswirkungen auf die Ergebnisse. In bestimmten Fällen kann Padding jedoch zu einer deutlich erhöhten Speicherauslastung und Ausführungszeit führen.

So reduzieren Sie die Arbeitsspeichernutzung

Die TPU-Software versucht, Tensoren im Speicher auszulegen, um die Rechenleistung zu maximieren und das Padding zu minimieren. Dieser Speicher-Layout-Prozess ist jedoch komplex. Zur Erzielung optimaler Ergebnisse sollte das Modell nach folgender Faustregel ausgelegt werden. Wenn der Speicheraufwand minimiert und die Recheneffizienz maximiert werden soll, muss eine der folgenden Bedingungen zutreffen:

  • Die Gesamt-Batchgröße sollte ein Vielfaches von 64 sein (8 pro TPU-Kern). Die Feature-Dimensionen sollten ein Vielfaches von 128 sein.

    Oder

  • Die Gesamt-Batchgröße sollte ein Vielfaches von 1.024 (128 pro TPU-Kern) sein. Die Feature-Dimensionen sollten ein Vielfaches von 8 sein.

Die Verwendung einer Batchgröße von 1.024 und von Feature-Dimensionen, die ein Vielfaches von 128 sind, ermöglicht eine optimale Effizienz, obwohl dies unter Umständen nicht für alle Modelle möglich ist. Der Einfachheit halber bezieht sich "Feature-Dimension" auf die versteckte Größe einer vollständig verbundenen Ebene oder die Anzahl der Ausgabekanäle in einer Faltung. Nicht alle Ebenen können dieser Regel entsprechen. Dies gilt insbesondere für die erste und die letzte Ebene des Netzwerks. Das ist in Ordnung und die meisten Modelle erfordern voraussichtlich ein gewisses Maß an Padding.

Arbeitsspeichernutzung reduzieren

Wenn beim Ausführen Ihres Modells auf der TPU ein Fehler aufgrund fehlenden Speichers auftritt, müssen Sie Maßnahmen ergreifen, um die Arbeitsspeichernutzung des Modells zu reduzieren.

Sie erreichen die effektivste Methode, um die Speicherauslastung zu verringern:

  • Übermäßige Tensor-Padding verringern
  • Batchgröße reduzieren

Batchgröße oder Modell zu groß

Mögliche Ursache des Speicherproblems

Beim Trainieren eines neuronalen Netzwerks auf einer CPU, GPU oder TPU hat die Speichernutzung zwei Ursachen:

  1. Die Speichernutzung ist proportional zur Anzahl der Gewichtungen im Modell.
  2. Speichern von Zwischenaktivierungen aus dem Vorwärtsdurchlauf, die für die Berechnung des Rückwärtsdurchlaufs erforderlich sind. Die Arbeitsspeichernutzung ist direkt proportional zur Batchgröße, zu den Ebenengrößen und zur Anzahl der Ebenen.

Daher hängt der von einem Modell benötigte Speicher weitgehend von der Batchgröße ab.

Der für ein Modell erforderliche Arbeitsspeicher hängt von der Anzahl der Ebenen im Netzwerk ab.

Die TPU-Laufzeit versucht, Operatoren zu optimieren, damit das Modell in den Speicher passt (sogenanntesRematerialisierung , ähneltGradientenprüfpunkt ). Das ist jedoch nicht immer möglich.

So reduzieren Sie die Arbeitsspeichernutzung

Reduzieren Sie die Batchgröße langsam, bis sie in den Arbeitsspeicher passt. Die gesamte Batchgröße muss ein Vielfaches von 64 sein (die Batchgröße pro Kern sollte ein Vielfaches von 8 sein). Beachten Sie, dass größere Batches auf der TPU effizienter sind. Eine Gesamt-Batchgröße von 1.024 (128 pro Kern) ist im Allgemeinen ein guter Ausgangspunkt.

Wenn das Modell auch mit einer kleinen Batchgröße (z. B. 64) nicht auf der TPU ausgeführt werden kann, versuchen Sie, die Anzahl der Ebenen oder die Ebenengrößen zu reduzieren.

Verbesserung der Trainingsgeschwindigkeit

Wenn Ihr Modell erfolgreich auf der TPU ausgeführt werden kann, die Trainingsgeschwindigkeit jedoch geringer als erwartet ist, finden Sie in diesem Abschnitt eine Beschreibung der verschiedenen Möglichkeiten zur Verbesserung der Geschwindigkeit. Weitere Vorschläge zur Verbesserung der Trainingsleistung finden Sie im Leistungsleitfaden.

Zu wenige Schritte pro Ausführung und Trainingsschleife

Beschreibung des Leistungsproblems

Durch Übergabe des Arguments steps_per_execution an Model.compile wird gesteuert, wie viele Trainingsschritte zwischen Host-Callbacks ausgeführt werden. Jeder Host-Callback erfordert eine beträchtliche Kommunikation zwischen der Host-CPU des TPU-Servers und dem TPU-Gerät. Wenn steps_per_execution zu klein ist, kann das Training verlangsamt werden.

So ermitteln Sie, ob Ihr Modell betroffen ist

Wenn ein TPU-Profil häufige Host-CPU-Callbacks zwischen TPU-Geräteschritten aufdeckt, kann Ihr Training von einem größeren steps_per_execution-Wert profitieren.

So leiten Sie Gegenmaßnahmen ein

Setzen Sie steps_per_execution auf einen höheren Wert. Für steps_per_execution kann ein hoher Wert festgelegt werden. Beachten Sie jedoch, dass das Logging von Nachrichten und das Speichern eines Prüfpunkts erst nach der angegebenen Anzahl der Schritte erfolgen können.

Engpass bei der Eingabeverarbeitung

Beschreibung des Leistungsproblems

Während die TPU an einem bestimmten Datenblock trainiert, bereitet die Eingabeverarbeitungsfunktion den nächsten Datenblock auf der CPU vor. Wenn Ihre Eingabefunktion länger als die Modellfunktion dauert, bleibt die TPU inaktiv, während Ihre Eingabefunktion Daten abruft.

So ermitteln Sie, ob Ihr Modell betroffen ist

Folgen Sie der Anleitung unter Cloud TPU Tools: Input Pipeline Analyzer, um die Analyse der Eingabe-Pipeline in TensorBoard aufzurufen:

Bild

Die Seite für die Analyse der Eingabe-Pipeline zeigt eine übersichtliche Zusammenfassung an, der zu entnehmen ist, ob die Eingabeverarbeitung bei Ihrem Modell einen Engpass verursacht hat. Auf derselben Seite wird auch die Ausführungszeit pro Operation angezeigt, sodass Sie problematische Operationen ermitteln können.

So leiten Sie Gegenmaßnahmen ein

Beim Laden von Daten mit der Dataset API gibt es mehrere mögliche Maßnahmen:

  1. Speichern Sie die Daten als Sammlung von tf.train.Example-Strukturen in TFRecord-Dateien und laden Sie sie mit TFRecordDataset. Beispiele finden Sie in der Dataset API-Anleitung und der ResNet-Anleitung.
  2. Verwenden Sie zum Puffern der Eingabedaten dataset.cache() und/oder dataset.prefetch(). Dadurch wird verhindert, dass sporadische Verlangsamungen beim Dateizugriff zu Engpässen führen.
  3. Legen Sie den Parameter num_parallel_calls der Funktion dataset.map() fest, um Multithread-Vorgänge vom Typ map() zu aktivieren. Eine einfache Heuristik für den Wert von num_parallel_calls ist die Verwendung der Anzahl der verfügbaren CPU-Kerne.
  4. Führen Sie die teure Datenvorverarbeitung offline durch, sodass dafür nur einmal Kosten anfallen und nicht in jeder Epoche jedes Trainings.

Die gesamte Eingabeverarbeitung erfolgt auf CPUs, die sich auf dem TPU-Server befinden, nicht auf dem lokalen Computer. Daher spielt die Geschwindigkeit des lokalen Computers keine Rolle.

Langsame Schrittzeiten und geringe MXU-Auslastung

Beschreibung des Leistungsproblems

Die Cloud TPU kann Matrixmultiplikationen und -faltungen bei unglaublich hohen Geschwindigkeiten ausführen. Die meisten anderen TensorFlow-Operationen haben effiziente Implementierungen auf der TPU, diese sind im Verhältnis zu anderer Hardware jedoch nicht deren primäre Stärke. Daher sollte ein Modell von den Matrixmultiplikationen oder -faltungen dominiert werden, um die TPU optimal nutzen zu können.

So ermitteln Sie, ob Ihr Modell betroffen ist

Zu den Symptomen gehören in diesem Fall langsame Schrittzeiten und eine niedrige MXU-Auslastung, die Sie beim Profilieren der Leistung sehen.

So leiten Sie Gegenmaßnahmen ein

Versuchen Sie, die Anzahl der Vorgänge zu reduzieren, die keine Matrixmultiplikationen sind. Nachdem Sie die Anzahl der Matrixmultiplikationen reduziert haben, führen Sie ein erneutes Benchmarking durch, um festzustellen, ob die Leistung auf TPUs akzeptabel ist.

Übermäßiges Padding von Tensoren

Beschreibung des Leistungsproblems

Die TPU füllt Tensoren im Speicher auf, sodass die TPU ihre Recheneinheiten effizient nutzen kann. Durch Padding kann die Nutzung des Speichers und auch der Speicherbandbreite gesteigert werden. Weitere Informationen zu Problemen beim Padding von Tensoren und zu deren Behebung finden Sie im Abschnitt Padding von Tensoren.

Langsamer Durchsatz und geringe Speichernutzung

Beschreibung des Leistungsproblems

In der Regel führt die Verwendung größerer Batchgrößen im Hinblick auf Stichproben/Sekunde zu einer höheren Trainingsgeschwindigkeit auf der TPU.

So ermitteln Sie, ob Ihr Modell betroffen ist

Die Batchgröße jedes Modells sollte immer mindestens 64 betragen (8 pro TPU-Kern), da die TPU die Tensoren immer entsprechend der Größe auffüllt. Die ideale Batchgröße beim Training auf der TPU ist 1.024 (128 pro TPU-Kern), da hierdurch Ineffizienzen in Bezug auf die Speicherübertragung und das Padding beseitigt werden.

So leiten Sie Gegenmaßnahmen ein

Als Best Practice wird empfohlen, die größte Batchgröße zu verwenden, die in den Arbeitsspeicher passt und ein Vielfaches von 64 ist. Der einfachste Weg, dies zu erreichen, besteht darin, mit 1.024 zu beginnen. Wenn dies zu einem Fehler aufgrund fehlenden Speichers führt, versuchen Sie, die Batchgröße zu reduzieren, bis das Modell erfolgreich ausgeführt wird. Wenn Sie die Batchgröße eines Modells ändern, müssen Sie möglicherweise andere Hyperparameter anpassen, um die gleiche Modellgenauigkeit wie die Lernrate zu erreichen. Dies muss jedoch von Fall zu Fall überprüft werden.

Ebenengrößen zu klein

Beschreibung des Leistungsproblems

Selbst wenn ein Modell von Matrixmultiplikationen oder -faltungen dominiert wird, läuft die TPU möglicherweise nicht mit voller Effizienz, wenn die Eingangstensoren klein sind. Im Vergleich zu anderer Hardware wird die TPU am effizientesten ausgeführt, wenn die Batchgröße und die Ebenengröße größer sind (z. B. Dimension >= 512).

So ermitteln Sie, ob Ihr Modell betroffen ist

Als allgemeine Regel gilt, dass Ebenengrößen kleiner als 128 eine schlechte Effizienz auf der TPU erreichen, da 128 die native Dimension der TPU-Matrixmultiplikationseinheit ist. Für vollständig verbundene Ebenen wird zur Erzielung einer hohen Effizienz eine minimale versteckte Größe von 512 empfohlen. Beachten Sie, dass Faltungsebenen in der Regel nicht so groß wie vollständig verbundene Ebenen sein müssen, um ein gleiches Effizienzniveau zu erreichen.

So leiten Sie Gegenmaßnahmen ein

Wenn die primäre Motivation für kleine Ebenengrößen in Ihrem Modell die Trainingsgeschwindigkeit ist, bewerten Sie Ihre Modelle mit größeren Ebenen auf der TPU neu. Wenn Sie beispielsweise die Ausgabegröße einer Ebene von 256 auf 512 erhöhen, kann die Trainingszeit nur um 20% erhöht werden, obwohl das Modell die Berechnungen doppelt ausführt.

Modellprofilierung auf Operationsebene

Häufig ist es hilfreich, die Ausführungszeit und Speichernutzung auf der Operationsebene zu messen, um Leistungsengpässe zu identifizieren. Weitere Informationen dazu finden Sie in der Anleitung
Cloud TPU-Tools: Trace Viewer.

Debugging verringert die Modellgenauigkeit

Eines der Ziele der Cloud TPU-Umgebung ist, dass jedes Modell, das gerade auf einer CPU oder GPU trainiert wird, eine sehr ähnliche Accuracy erreicht, wenn es auf der TPU trainiert wird, und zwar mit möglicherweise geringeren Anpassungen an Hyperparameter wie Batchgröße und Lernrate. Gelegentlich können Nutzer jedoch eine Verschlechterung der Accuracy beobachten, wenn sie Modelle auf der TPU trainieren. Die Behebung solcher Probleme kann aufgrund der zufälligen Art des neuronalen Netzwerktrainings extrem frustrierend sein. In diesem Abschnitt wird erläutert, wie Sie die Ursache für die Verringerung der Modellgenauigkeit bei der Portierung eines Modells auf die TPU ermitteln können.

Informationen zur Datenfragmentierung (Datenparallelität)

Eines der Hauptziele von TensorFlow besteht darin, dass jeder Vorgang nahezu identische Ergebnisse liefert, unabhängig davon, ob er auf der CPU, GPU oder TPU ausgeführt wird. Hiervon gibt es bestimmte Ausnahmen, z. B. zufällige Vorgänge. Wenn Sie einen signifikanten Unterschied zwischen der Ausgabe nicht zufälliger Operationen auf der TPU und der CPU feststellen, melden Sie dies als Programmfehler.

Für die Trainingspipeline insgesamt besteht jedoch ein deutlicher Unterschied zwischen dem Training auf der CPU/GPU und der TPU. Beim Training auf einer TPU führt TensorFlow Datenfragmentierung durch. Jede Cloud TPU enthält acht TPU-Kerne, die als unabhängige Verarbeitungseinheiten fungieren. Für jeden Schritt im Training empfängt jeder TPU-Kern einen Batch von Daten, berechnet die Gewichtsverläufe, tauscht die Gradienten mit den anderen TPU-Kernen aus und berechnet dann die Gewichtungsaktualisierung. Standardmäßig wird der Verlust über die Kerne gemittelt, er kann aber auch summiert werden, indem der Parameter CrossShardOptimizer geändert wird.

Wenn der Gesamtverlust des Modells als der Durchschnitt (oder die Summe) der unabhängigen Verluste pro Stichprobe berechnet werden kann, entspricht dieses Verfahren mathematisch dem Training für einen einzelnen großen Batch.

Die gängigste nicht unabhängige Operation pro Stichprobe ist die Batchnormalisierung, die jeden Pro-Kern-Batch getrennt durchläuft. Wenn der Batch eine Gesamtgröße von beispielsweise 128 aufweist, beträgt die Batchgröße pro Kern 16 und jeder der 8 Kerne führt die Batchnormalisierung für die eigenen 16 Stichproben aus. In einigen Fällen hat die Durchführung der Batchnormalisierung für kleine Batches (z. B. weniger als 32) zu einer Verschlechterung der Genauigkeit geführt. Im Idealfall sollte die Gesamt-Batchgröße groß sein (z. B. 256 bis 1.024). Wenn eine solche Batchgröße zu groß ist, um in den Speicher zu passen, muss der Fragmentierungseffekt von Fall zu Fall bewertet werden.

Deterministisches Training

Ein Grund dafür, warum es schwierig ist, Unterschiede in der Modellgenauigkeit zu beheben, besteht darin, dass die Trainingssoftware in verschiedenen Frameworks (TensorFlow, PyTorch, JAX) jedes Mal, wenn ein Modell trainiert wird, unterschiedliche Gewichtungsinitialisierung und Daten-Shuffling verwendet. aus. Es ist vorteilhaft, das Trainingsverfahren so zu ändern, dass es deterministisch ist, sodass mehrere Ausführungen nahezu identische Modelle erzeugen. In diesem Abschnitt wird gezeigt, wie die MNIST-Anleitung deterministisch ausgeführt wird:

  1. Erstellen Sie eine erste Prüfpunktdatei durch Ausführen eines einzelnen Schritts auf der CPU. Mit diesem Schritt erzielen Sie eine deterministische Gewichtungsinitialisierung. Achten Sie außerdem darauf, dass Sie für jede Zufallsfunktion im Modell einen festen zufälligen Wert verwenden.
# Run training for 1 step to create an initial checkpoint.
python mnist_tpu.py \
  --use_tpu=False \
  --data_dir=${STORAGE_BUCKET}/data/ \
  --model_dir=${STORAGE_BUCKET}/init_output \
  --random_seed=12345 \
  --iterations=1
  --train_steps=1
  1. Ändern Sie alle Funktionen der Datenfragmentierung in Ihrer Eingabefunktion, um einen zufälligen Ausgangswert zu verwenden. Dies wurde bereits im Rahmen der MNIST-Anleitung durchgeführt. Dies funktioniert für die Vorgänge der Eingabedatenverarbeitung, da diese immer auf der CPU ausgeführt werden. Zufallsvorgänge in der Modellfunktion sind zwischen der TPU und der CPU möglicherweise nicht deterministisch. Übergeben Sie jedes Mal, wenn ein zufälliger Vorgang aufgerufen wird, einen festen Wert, um dafür zu sorgen, dass zwischen den Ausführungen dieselben Ergebnisse erzielt werden. Beispiel:
# In the flag definitions
tf.flags.DEFINE_integer("batch_size", None, "Random seed for training")

# In the input_fn
if FLAGS.random_seed is not None:
dataset = dataset.shuffle(seed=FLAGS.random_seed)
  1. Führen Sie dasselbe Modell zweimal auf der CPU aus, um zu prüfen, ob das Training deterministisch ist. Beachten Sie, dass das Training für eine angemessene Anzahl von Schritten (z. B. 1.000) ausgeführt werden muss, aber nicht für die Konvergenz.

    Da das CPU-Training mit einem Einzelkern-TPU-Training verglichen wird, verwenden Sie eine vollständige Batchgröße, die auf einen einzelnen TPU-Kern passt (in der Regel die vollständige Batchgröße geteilt durch 8). TensorFlow garantiert keinen bitweisen Determinismus zwischen Ausführungen, aber der Verlust sollte den dabei erreichten Werten sehr nahe kommen:
# Copy the initial weights
gsutil mkdir ${STORAGE_BUCKET}/cpu_output_1
gsutil cp -f ${STORAGE_BUCKET}/init_output/* ${STORAGE_BUCKET}/cpu_output_1
gsutil mkdir ${STORAGE_BUCKET}/cpu_output_2
gsutil cp -f ${STORAGE_BUCKET}/init_output/* ${STORAGE_BUCKET}/cpu_output_2

# Run 1
python mnist_tpu.py \
  --use_tpu=False \
  --data_dir=${STORAGE_BUCKET}/data/ \
  --model_dir=${STORAGE_BUCKET}/cpu_output_1 \
  --batch_size=128 \
  --random_seed=12345 \
  --train_steps=2000 \
  --eval_steps=10

# Output 1
accuracy = 0.9910644, global_step = 1000, loss = 0.025323588

# Run 2
python mnist_tpu.py \
  --use_tpu=False \
  --data_dir=${STORAGE_BUCKET}/data/ \
  --model_dir=${STORAGE_BUCKET}/cpu_output_1 \
  --batch_size=128 \
  --random_seed=12345 \
  --train_steps=2000 \
  --eval_steps=10

# Output 2
accuracy = 0.9910644, global_step = 1000, loss = 0.025323414

Einzelkern-TPU-Training

Sobald Sie die MNIST-Anleitung deterministisch ausführen können, besteht der nächste Schritt darin, die CPU-trainierten Ergebnisse auf der TPU zu replizieren, wobei ein einzelner TPU-Kern verwendet wird, um festzustellen, ob das Problem mit der Datenfragmentierung oder der TPU-Ausführungsengine selbst zusammenhängt.

So führen Sie das Einzelkern-Training und die Evaluierung in der MNIST-Anleitung aus:

# Use the same weight initialization as the CPU
gsutil cp -f ${STORAGE_BUCKET}/init_output/* ${STORAGE_BUCKET}/tpu_output

# Run training for 1000 steps
python mnist.py \
    --use_tpu=True \
    --master=$GRPC_SERVER \
    --train_file=${STORAGE_BUCKET}/data/train.tfrecords \
    --model_dir=${STORAGE_BUCKET}/tpu_output \
    --random_seed=12345 \
    --num_shards=1 \
    --batch_size=128 \
    --train_steps=1000 \
    --eval_steps=10

  accuracy = 0.9910644, global_step = 1000, loss = 0.02514153

Der Verlust stimmt nicht genau mit dem CPU-trainierten Modell überein, kommt diesem jedoch nahe. Ist Letzteres bei Ihrem Modell nicht der Fall, kann dies darauf hindeuten, dass ein Fehler in der TPU-Ausführungs-Engine vorliegt. Prüfen Sie Folgendes, bevor Sie einen Fehlerbericht senden:

  1. Sie übergeben num_shards=1 an TPUConfig.

  2. In Ihrer Modellfunktion liegen keine zufälligen Operationen vor und in Ihrer Eingabefunktion wird für alle zufälligen Operationen ein korrektes Seeding ausgeführt.

  3. Sie verwenden für das CPU- und das TPU-Training dieselbe initiale Prüfpunktdatei.

Fehlerbehebung beim Mehrkern-TPU-Training

Wenn Ihr Modell den gleichen Verlust auf der CPU und der Einzelkern-TPU erreicht, liegt möglicherweise eines der folgenden Probleme vor:

(a) Die Verschlechterung ist auf die natürliche zufällige Varianz zurückzuführen, wenn neuronale Modelle mit unterschiedlichen Initialisierungen trainiert werden.

(b) Die Verschlechterung ist auf ein Problem bei der Datenfragmentierung auf der TPU zurückzuführen.

Um festzustellen, ob Problem (a) zutrifft, trainieren Sie das vollständige Modell auf der CPU/GPU und der Mehrkern-TPU mit der gleichen Gewichtungsinitialisierung, wie oben beschrieben erneut.

Wenn Sie sicher sind, dass der Genauigkeitsabfall statistisch signifikant ist, handelt es sich bei den Problemen im Zusammenhang mit der Datenfragmentierung mit hoher Wahrscheinlichkeit um die Folgenden:

  1. Wenn das Modell Batchnormalisierung verwendet, kann eine Gesamt-Batchgröße von weniger als 256 (z. B. weniger als 32 pro Kern) die Accuracy verringern.
  2. Batchbasierte Verlustfunktionen werden von Fragmentierung beeinflusst. Solche Verlustfunktionen sind in der Regel ziemlich speziell. Beispiel: Karras et al. 2017 verwendet beim Trainieren eines generativen kontradiktorischen Netzwerks (GAN, Generative Adversarial Network) beispielsweise einen Batchdiskriminator.

Fehlerbehebung bei TPU-VMs

Die folgenden Probleme und Lösungen gelten nur für TPU-VM-Konfigurationen.

Fehlerbehebung bei der gcloud-Einrichtung

Problem

gcloud components update zeigt die folgende Fehlermeldung an:

ERROR: (gcloud.components.update)
You cannot perform this action because the Cloud SDK component manager
is disabled for this installation.
Lösung

Wenn Sie gcloud mit der TPU-VM verwenden möchten, ist dazu eine gcloud-Installation erforderlich, die nicht über einen Paketmanager verwaltet wird. Zum Installieren gcloud des Quellcodes führen Sie die folgenden Schritte aus:

sudo apt-get remove google-cloud-sdk
curl -O https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-311.0.0-linux-x86_64.tar.gz
tar -xzf google-cloud-sdk-311.0.0-linux-x86_64.tar.gz
./google-cloud-sdk/install.sh
source ~/.bashrc
Problem

Wenn Sie einen Befehl ausführen, der mit gcloud alpha compute tpus tpu-vm beginnt, wird Folgendes angezeigt:

ERROR: (gcloud.alpha.compute.tpus) Invalid choice: 'tpu-vm'.
Lösung

Dies tritt auf, wenn das Komponenten-Repository nicht ordnungsgemäß aktualisiert wurde. Zur Prüfung rufen Sie gcloud --version auf. Die erste Zeile der Ausgabe muss "Google Cloud SDK HEAD" lauten. Andernfalls wird die Aktualisierung nicht ausgeführt. Versuchen Sie in diesem Fall, die gcloud-Komponenten mit dem folgenden Befehl zu aktualisieren.

gcloud components update

Wenn der Fehler weiterhin auftritt, installieren Sie gcloud mit dem folgenden Befehl neu:

gcloud components reinstall
Problem

Der Befehl gcloud alpha compute tpus tpu-vm ssh ${TPU_NAME} --zone ${ZONE} ergibt die folgende Fehlermeldung:

Waiting for SSH key to propagate.
ssh: connect to host 34.91.136.59 port 22: Connection timed out
ssh: connect to host 34.91.136.59 port 22: Connection timed out
ssh: connect to host 34.91.136.59 port 22: Connection timed out
ERROR: (gcloud.alpha.compute.tpus.tpu-vm.ssh) Could not SSH into the instance.  It is possible that your SSH key has not propagated to the instance yet. Try running this command again.  If you still cannot connect, verify that the firewall and instance are set to accept ssh traffic.
Lösung

Möglicherweise liegt ein Problem mit der SSH-Schlüsselverteilung vor. Verschieben Sie zur Fehlerbehebung die automatisch generierten Schlüssel an einen Sicherungsspeicherort, damit gcloud sie neu erstellt:

mv ~/.ssh/google_compute_engine ~/.ssh/old-google_compute_engine
mv ~/.ssh/google_compute_engine.pub ~/.ssh/old-google_compute_engine.pub

Fehlerbehebungsprotokolle

Die unterstützten Cloud TPU-Frameworks, JAX, PyTorch und TensorFlow greifen über eine gemeinsam genutzte Bibliothek namens libtpu auf TPUs zu, die auf jeder TPU-VM vorhanden ist. Diese Bibliothek enthält den XLA-Compiler, der zum Kompilieren von TPU-Programmen verwendet wird, die TPU-Laufzeit, die zum Ausführen kompilierter Programme verwendet wird, und den TPU-Treiber, der von der Laufzeit für den Low-Level-Zugriff auf die TPU verwendet wird.

Die Bibliothek libtpu protokolliert Informationen, die für das Debugging nützlich sein können. Standardmäßig werden diese Logs auf jeder Cloud TPU-VM in /tmp/tpu_logs geschrieben. Die folgenden Umgebungsvariablen können vor dem Training festgelegt werden, um das Logging-Verhalten zu ändern:

TPU_LOG_DIR: das Verzeichnis, in das Logs geschrieben werden
Der Verzeichnisspeicherort ist standardmäßig auf /tmp/tpu_logs gesetzt. Das Verzeichnis wird erstellt, wenn noch nicht vorhanden, aber es werden keine übergeordneten Verzeichnisse erstellt. Wenn beim Ermitteln oder Erstellen des angegebenen Verzeichnisses ein Fehler auftritt, wird eine Meldung an stderr ausgegeben, das Programm wird jedoch nicht angehalten und Logging wird deaktiviert. Setzen Sie den Verzeichnisnamen auf "disabled", um das Logging auf dem Laufwerk vollständig zu deaktivieren.
TPU_MIN_LOG_LEVEL: Der minimale Schweregrad, der auf dem Laufwerk protokolliert wird
Die Auswahlmöglichkeiten sind 0 (INFO), 1 (WARNUNG), 2 (FEHLER) und 3 (SCHWERWIEGEND). Der Standardwert ist 0.
TPU_STDERR_LOG_LEVEL: Der minimale Schweregrad, der gegebenenfalls zusätzlich zum Laufwerk in stderr protokolliert wird
Die Auswahlmöglichkeiten sind identisch mit TPU_MIN_LOG_LEVEL. Der Standardwert ist 3.
TPU_MAX_LOG_SIZE_MB: die maximale Größe jeder Protokolldatei in Megabyte
Eine neue Logdatei wird automatisch gestartet, wenn die vorherige Logdatei etwa diese Größe erreicht. Die Standardeinstellung ist 1024.