[PYTHON] Informationen zur Optimierung der Berechnungsgraphenoptimierung in tf.function

Dies ist der Artikel zum 22. Tag von TensorFlow2.0 Adventskalender 2019.

In diesem Artikel stellt TensorFlow beim Erstellen eines TensorFlow-Berechnungsdiagramms aus einem Python-Programm mit tf.function den internen Optimierungsprozess für das Berechnungsdiagramm und die Steuerung der Optimierung vor.

In diesem Artikel wird erläutert, was hinter tf.function getan wird. Weitere Informationen zur Verwendung von tf.function selbst finden Sie in anderen Artikeln. Der TensorFlow2.0 Adventskalender 2019 hat auch einige Artikel über tf.function veröffentlicht.

tf.function

Die mit "@ tf.function" dekorierte Funktion wird in ein TensorFlow-Berechnungsdiagramm konvertiert. Betrachten Sie beispielsweise das folgende Programm.

import tensorflow as tf

@tf.function
def simple_func(arg):
    a = tf.constant(7.9)
    b = tf.constant(6.3)
    c = arg + a
    d = a * b
    ret = c + d
    
    return ret

arg = tf.constant(8.9)
print(simple_func(arg))

Das mit der Funktion simple_func erstellte Berechnungsdiagramm sieht folgendermaßen aus:

user_graph.png

Optimierungsprozess für Berechnungsdiagramme

Der durch tf.function konvertierte berechnete Graph wird in TensorFlow (C ++ - Ebene) optimiert. Dieser Optimierungsprozess wird auch im Grafikmodus verwendet, der die Standardeinstellung für TensorFlow 1.x war, und die in TensorFlow 1.x entwickelte Technologie zur Optimierung von Berechnungsgraphen wird auch in tf.function verwendet.

Dies ist ein alter Artikel für TensorFlow 1.13. Wenn Sie jedoch an dem in TensorFlow durchgeführten Optimierungsprozess für Berechnungsdiagramme interessiert sind, lesen Sie bitte auch den folgenden Artikel. In TensorFlow 2.0 wurden zusätzlich zu den im Artikel eingeführten Optimierungen neue Optimierungen wie Auto Mixed Precision hinzugefügt. Zu einem anderen Zeitpunkt möchte ich den neuesten Optimierungsprozess vorstellen.

Zurück zum vorherigen Berechnungsdiagramm: Das Berechnungsdiagramm nach dem Optimieren des durch tf.function erzeugten Berechnungsdiagramms lautet wie folgt.

optimized_graph.png

Wenn Sie sich das generierte Berechnungsdiagramm ansehen, sehen Sie, dass einige Knoten im Berechnungsdiagramm gelöscht wurden. Die hier vorgenommene Optimierung wird als [Konstante Faltung] bezeichnet (https://qiita.com/nuka137/items/f1b0fe9c820e4d5f80cc#3-constant-folding), wobei alle Knoteneingaben konstante Werte sind. Bewerten Sie beim Erstellen des Berechnungsdiagramms und ersetzen Sie es durch den Const-Knoten. Durch Auswerten der Teile, die zum Zeitpunkt der Erstellung des Berechnungsdiagramms im Voraus ausgewertet werden können, kann die Verarbeitungszeit des gesamten Berechnungsdiagramms verkürzt werden.

Überprüfen Sie das optimierte Berechnungsdiagramm

Sie können das optimierte Berechnungsdiagramm mit TensorBoard überprüfen. Um Zusammenfassungsdaten für TensorBoard auszugeben, müssen Sie "tf.summary.trace_on ()" aufrufen, bevor Sie den von tf.function erstellten Rechengraphen aufrufen. Beachten Sie, dass das optimierte Berechnungsdiagramm nur ausgegeben wird, wenn für die Argumente "Diagramm" und "Profiler" von "tf.summary.trace_on ()" "True" angegeben ist. Anschließend können Sie das optimierte Berechnungsdiagramm ausgeben, indem Sie "tf.summary.trace_export ()" aufrufen, nachdem Sie das zu überprüfende Berechnungsdiagramm ausgeführt haben. Der Quellcode, der das optimierte Berechnungsdiagramm für TensorBoard ausgibt, ist unten dargestellt.

import tensorflow as tf

@tf.function
def simple_func(arg):
    a = tf.constant(7.9)
    b = tf.constant(6.3)
    c = arg + a
    d = a * b
    ret = c + d
    
    return ret

#Aktivieren Sie die Zusammenfassung der Datenerfassung für TensorBoard
writer = tf.summary.create_file_writer("summary")
#Sie können das optimierte Berechnungsdiagramm überprüfen, indem Sie True für das Argumentdiagramm und den Profiler angeben.
tf.summary.trace_on(graph=True, profiler=True)

arg = tf.constant(8.9)
print(simple_func(arg))

#Geben Sie die gesammelten Zusammenfassungsdaten aus
with writer.as_default():
    tf.summary.trace_export("summary", step=0, profiler_outdir="summary")

#Deaktivieren Sie die Erfassung von Zusammenfassungsdaten
tf.summary.trace_off()

Verwenden Sie TensorBoard, um die Zusammenfassungsdaten für die TensorBoard-Ausgabe durch Ausführen des Programms zu lesen. Schauen wir uns zunächst das benutzerdefinierte Diagramm an. Wenn die Registerkarte GRAFIKEN des TensorBoards ausgewählt ist, können Sie ein benutzerdefiniertes Diagramm anzeigen, indem Sie im Optionsfeld links die Option Diagramm auswählen.

Das benutzerdefinierte Diagramm ist das berechnete Diagramm selbst, das in "simple_func" definiert ist.

user_defined_graph.png

Als nächstes überprüfen wir das Berechnungsdiagramm nach der Optimierung. Wenn die Registerkarte "GRAFIKEN" von TensorBoard ausgewählt ist, können Sie das optimierte Berechnungsdiagramm anzeigen, indem Sie links im Optionsfeld "Profil" auswählen.

In dem optimierten Berechnungsdiagramm sind ein Mul-Knoten und sein konstanter Eingabeknoten schattiert. Schattierte Knoten sind Knoten, die in TensorFlow nicht berechnet wurden. Aufgrund der Optimierung des Berechnungsdiagramms in TensorFlow ist es wahrscheinlich, dass diese schattierten Knoten nicht mehr berechnet werden.

optimized_graph.png

Auf diese Weise können Sie mit TensorBoard den Unterschied zwischen dem benutzerdefinierten Berechnungsdiagramm und dem optimierten Berechnungsdiagramm überprüfen.

Steuern Sie den Optimierungsprozess des Berechnungsdiagramms

Der in TensorFlow durchgeführte Optimierungsprozess für Berechnungsdiagramme kann durch Aufrufen von "tf.config.optimizer.set_experimental_options ()" aktiviert / deaktiviert werden. Beachten Sie, dass der einzige Optimierungsprozess, der durch "tf.config.optimizer.set_experimental_options ()" aktiviert / deaktiviert werden kann, [von Grappler durchgeführter Optimierungsprozess] ist (https://qiita.com/nuka137/items/f1b0fe9c820e4d5f80cc). ist. Beachten Sie, dass die Optimierung mit GraphOptimizationPass und GraphOptimizer immer durchgeführt wird. Bitte.

Bevor wir den Optimierungsprozess für das Berechnungsdiagramm erläutern, bei dem zwischen Aktivieren und Deaktivieren umgeschaltet wird, überprüfen wir die Standardoptimierungseinstellungen. Sie können die Einstellungen für die Optimierung des Berechnungsdiagramms überprüfen, indem Sie "tf.config.optimizer.get_experimental.options ()" aufrufen.

import tensorflow as tf

tf.config.optimizer.get_experimental_options()

Wenn Sie die oben genannten Schritte ausführen, erhalten Sie die folgenden Ergebnisse:

{'disable_meta_optimizer': False, 'disable_model_pruning': False}

disable_meta_optimizer ist eine Einstellung, die [Von Grappler durchgeführte Verarbeitung optimieren] deaktiviert (https://qiita.com/nuka137/items/f1b0fe9c820e4d5f80cc), und False ist standardmäßig angegeben. Daraus können wir ersehen, dass der Optimierungsprozess von Grappler standardmäßig aktiviert ist. Darüber hinaus sind keine anderen Optimierungen festgelegt, daher [Standardoptimierungseinstellungen](https://qiita.com/nuka137/items/f1b0fe9c820e4d5f80cc#grappler%E3%81%AB%E3%82%88 % E3% 82% 8B% E6% 9C% 80% E9% 81% A9% E5% 8C% 96% E9% A0% 85% E7% 9B% AE) wurde angewendet.

Lassen Sie uns nun den Effekt überprüfen, indem wir ein Beispiel für das tatsächliche Aktivieren / Deaktivieren der Optimierung geben.

Deaktivieren Sie die Optimierung "Debug Stripper"

Debug Stripper ist ein Optimierungsprozess, bei dem Knoten (z. B. Assert) gelöscht werden, die für Debugging-Zwecke verwendet werden. Der Debug-Stripper ist standardmäßig deaktiviert, sodass Assert-Knoten, die durch "tf.Assert" hinzugefügt wurden, nicht entfernt werden. Infolgedessen löst der folgende Code eine Ausnahme bei "tf.Assert" aus.

import tensorflow as tf

@tf.function
def assert_func():
    a = tf.constant(1.2)
    computation_graph = tf.Assert(tf.less_equal(a, 1.0), [a])   #Ausnahme "InvalidArgumentError" tritt auf
    return a

print(assert_func())

Wenn Sie dagegen Debug Stripper aktivieren und ausführen, wird der durch tf.Assert hinzugefügte Assert-Knoten gelöscht und die oben angegebene Ausnahme tritt nicht mehr auf.

import tensorflow as tf

#Aktivieren Sie "Debug Stripper"
tf.config.optimizer.set_experimental_options({'debug_stripper': True})

@tf.function
def assert_func():
    a = tf.constant(1.2)
    computation_graph = tf.Assert(tf.less_equal(a, 1.0), [a])   #Keine Ausnahmen
    return a

print(assert_func())

Für Debugging-Zwecke hinzugefügte Asserts benötigen Zeit für die Verarbeitung, z. B. die Notwendigkeit, die Tensordaten zu überprüfen, was sich auf die Ausführungszeit des Berechnungsdiagramms auswirkt. Nachdem das Debuggen abgeschlossen ist, ist es gut, das zum Debuggen hinzugefügte "tf.Assert" usw. zu löschen, aber nur, indem Sie den Debug-Stripper mit der hier gezeigten Methode aktivieren, die Berechnung für Debugging-Zwecke Wird gelöscht, warum also nicht davon profitieren?

Deaktiviert alle von Grappler vorgenommenen Optimierungen von Rechengraphen

Ich habe geschrieben, dass die gesamte von Grappler durchgeführte Optimierungsverarbeitung deaktiviert wird, indem disable_meta_optimizer auf True gesetzt wird, aber hier möchte ich den Effekt sehen.

Lassen Sie uns zunächst das berechnete Diagramm nach der Optimierung mit den Standardoptimierungseinstellungen überprüfen. In dem unten gezeigten Quellcode erstellt Transpose ein kontinuierliches Berechnungsdiagramm.

import tensorflow as tf
import numpy as np

@tf.function
def optimized(arg):
    a = arg * 2

    #Entfernt von "Arithmetic Optimizer"
    b = tf.transpose(a, perm=[1, 0])
    ret = tf.transpose(b, perm=[1, 0])

    return ret

writer = tf.summary.create_file_writer("summary")
tf.summary.trace_on(graph=True, profiler=True)

arg = tf.constant(np.random.normal(size=(30, 40)))
optimized(arg)

with writer.as_default():
    tf.summary.trace_export("summary", step=0, profiler_outdir="summary")

tf.summary.trace_off()

Wenn Sie das Berechnungsdiagramm nach der Optimierung mit TensorBoard überprüfen, können Sie feststellen, dass der Transponierungsknoten gelöscht wurde. Dies erfolgt durch RemoveIdentityTranspose von Arithmetic Optimizer Dies liegt daran, dass wir die Inversionspaare gelöscht haben, die sich gegenseitig aufheben. Sie können auch sehen, dass der Identitätsknoten, der den Vorgang nicht beeinflusst, durch die Optimierung entfernt wurde.

meta_optimizer_enabled.png

Führen Sie als Nächstes dasselbe Berechnungsdiagramm mit disable_meta_optimizer auf True aus und überprüfen Sie das Berechnungsdiagramm, nachdem es von TensorBoard optimiert wurde.

import tensorflow as tf
import numpy as np

#Deaktiviert alle von Grappler durchgeführten Berechnungen zur Optimierung von Rechengraphen
tf.config.optimizer.set_experimental_options({'disable_meta_optimizer': True})

@tf.function
def not_optimized(arg):
    a = arg * 2
    b = tf.transpose(a, perm=[1, 0])
    ret = tf.transpose(b, perm=[1, 0])

    return ret

writer = tf.summary.create_file_writer("summary")
tf.summary.trace_on(graph=True, profiler=True)

arg = tf.constant(np.random.normal(size=(30, 40)))
not_optimized(arg)

with writer.as_default():
    tf.summary.trace_export("summary", step=0, profiler_outdir="summary")

tf.summary.trace_off()

Wenn Sie sich das berechnete Diagramm ansehen, nachdem es optimiert wurde, können Sie sehen, dass der Transponierungsknoten intakt bleibt und das arithmetische Optimierungsprogramm deaktiviert ist. Beachten Sie auch, dass der Identitätsknoten nicht gelöscht wurde.

meta_optimizer_disabled.png

Zusammenfassung

Wir haben vorgestellt, wie der von tf.function erstellte Rechengraph in TensorFlow optimiert wird, und erklärt, wie diese Optimierung gesteuert werden kann. Es wird erwartet, dass die Optimierungsfunktion des Berechnungsdiagramms weiterentwickelt wird, beispielsweise durch Hinzufügen neuer Optimierungen in jüngster Zeit. Freuen wir uns in Zukunft darauf.

Der in diesem Artikel vorgestellte Inhalt wurde neulich erfolgreich mit der als englische Version des Dokuments herausgegebenen Pull Request zusammengeführt. Ich denke, dass es offiziell als TensorFlow-Dokument veröffentlicht wird, also hoffe ich, dass Sie die Tatsache erleben können, dass die Optimierung des Berechnungsdiagramms tatsächlich auf Google Colab funktioniert. Ich denke, dass das diesmal zusammengeführte Dokument ins Japanische übersetzt und zum TensorFlow-Dokument (https://qiita.com/Suguru_Toyohara/items/f5d9f42578eec7cc1497) beigetragen wird. Freuen Sie sich also darauf.

Recommended Posts

Informationen zur Optimierung der Berechnungsgraphenoptimierung in tf.function
Über die Optimierung des Vanille-Kontinents