python - Perché TensorFlow 2 è molto più lento di TensorFlow 1?




keras performance-testing (2)

QUESTA RISPOSTA : mira a fornire una descrizione dettagliata, a livello di grafico / hardware, del problema, inclusi loop di treni TF2 vs. TF1, processori di dati di input ed esecuzioni in modalità Eager vs. Graph. Per un riepilogo dei problemi e linee guida per la risoluzione, vedere la mia altra risposta.

VERDETTO DELLE PRESTAZIONI : a volte uno è più veloce, a volte l'altro, a seconda della configurazione. Per quanto riguarda TF2 vs TF1, sono in media alla pari, ma esistono differenze significative basate sulla configurazione e TF1 supera TF2 più spesso di viceversa. Vedi "BENCHMARKING" di seguito.

EAGER VS. GRAFICO : la carne di questa intera risposta per alcuni: il desideroso di TF2 è più lento di quello di TF1, secondo i miei test. Dettagli più in basso.

La differenza fondamentale tra i due è: Graph imposta una rete computazionale in modo proattivo ed esegue quando "detto a" - mentre Eager esegue tutto al momento della creazione. Ma la storia inizia solo qui:

  • Desideroso NON è privo di Grafico , e in realtà può essere principalmente Grafico, contrariamente alle aspettative. Quello che è in gran parte, viene eseguito Graph - questo include i pesi del modello e dell'ottimizzatore, che comprende una grande porzione del grafico.

  • Eager ricostruisce parte del proprio grafico durante l'esecuzione ; conseguenza diretta di Graph non completamente costruito - vedere i risultati del profiler. Questo ha un sovraccarico computazionale.

  • Eager è più lento con input Numpy ; in base a questo commento e codice Git , gli input Numpy in Eager includono i costi generali di copia dei tensori dalla CPU alla GPU. Passando attraverso il codice sorgente, le differenze nella gestione dei dati sono chiare; Eager passa direttamente a Numpy, mentre Graph passa a tensori che poi valutano a Numpy; incerto dell'esatto processo, ma quest'ultimo dovrebbe comportare ottimizzazioni a livello di GPU

  • TF2 Eager è più lento di TF1 Eager - questo è ... inaspettato. Vedi i risultati del benchmarking di seguito. Le differenze vanno da trascurabili a significative, ma sono coerenti. Non sono sicuro del perché - se un dev TF chiarisce, aggiornerà la risposta.

TF2 vs. TF1 : citando parti rilevanti di uno sviluppatore TF, Q. Scott Zhu, confirmed - con un po 'della mia enfasi e riformulazione:

In impazienza, il runtime deve eseguire le operazioni e restituire il valore numerico per ogni riga di codice Python. La natura dell'esecuzione a singolo passaggio fa sì che sia lenta .

In TF2, Keras sfrutta la funzione tf.per costruire il suo grafico per allenamento, valutazione e previsione. Li chiamiamo "funzione di esecuzione" per il modello. In TF1, la "funzione di esecuzione" era un FuncGraph, che condivideva alcuni componenti comuni come funzione TF, ma ha un'implementazione diversa.

Durante il processo, abbiamo in qualche modo lasciato un'implementazione errata per train_on_batch (), test_on_batch () e predict_on_batch () . Sono ancora numericamente corretti , ma la funzione di esecuzione per x_on_batch è una funzione Python pura, piuttosto che una funzione Python con funzione tf.function. Ciò causerà lentezza

In TF2, convertiamo tutti i dati di input in un tf.data.Dataset, mediante il quale possiamo unificare la nostra funzione di esecuzione per gestire il singolo tipo di input. Potrebbe esserci un certo overhead nella conversione del set di dati e penso che si tratti di un overhead solo una volta, piuttosto che di un costo per batch

Con l'ultima frase dell'ultimo paragrafo sopra e l'ultima clausola del paragrafo seguente:

Per superare la lentezza in modalità desideroso, abbiamo @ tf.function, che trasformerà una funzione python in un grafico. Quando si alimenta un valore numerico come l'array np, il corpo della funzione tf. viene convertito in grafico statico, ottimizzato, e restituisce il valore finale, che è veloce e dovrebbe avere prestazioni simili alla modalità grafico TF1.

Non sono d'accordo - per i miei risultati di profilazione, che mostrano che l'elaborazione dei dati di input di Eager è sostanzialmente più lenta di quella di Graph. Inoltre, non tf.data.Dataset sicuro di tf.data.Dataset in particolare, ma Eager chiama ripetutamente più degli stessi metodi di conversione dei dati - vedi profiler.

Infine, il commit collegato di dev: Numero significativo di modifiche per supportare i loop di Keras v2 .

Train Loops : dipende da (1) desideroso vs. grafico; (2) formato dei dati di input, l'addestramento procederà con un circuito distinto del treno - in TF2, _select_training_loop() , training.py , uno di:

training_v2.Loop()
training_distributed.DistributionMultiWorkerTrainingLoop(
              training_v2.Loop()) # multi-worker mode
# Case 1: distribution strategy
training_distributed.DistributionMultiWorkerTrainingLoop(
            training_distributed.DistributionSingleWorkerTrainingLoop())
# Case 2: generator-like. Input is Python generator, or Sequence object,
# or a non-distributed Dataset or iterator in eager execution.
training_generator.GeneratorOrSequenceTrainingLoop()
training_generator.EagerDatasetOrIteratorTrainingLoop()
# Case 3: Symbolic tensors or Numpy array-like. This includes Datasets and iterators 
# in graph mode (since they generate symbolic tensors).
training_generator.GeneratorLikeTrainingLoop() # Eager
training_arrays.ArrayLikeTrainingLoop() # Graph

Ognuno gestisce l'allocazione delle risorse in modo diverso e ha conseguenze su prestazioni e capacità.

Loop dei treni: fit vs train_on_batch , keras vs. tf.keras : ciascuno dei quattro utilizza diversi loop di treni, anche se forse non in tutte le combinazioni possibili. L' fit keras , ad esempio, utilizza una forma di fit_loop , ad esempio training_arrays.fit_loop() , e il suo train_on_batch può usare K.function() . tf.keras ha una gerarchia più sofisticata descritta in parte nella sezione precedente.

Train Loops: documentazione - documentazione sorgente pertinente su alcuni dei diversi metodi di esecuzione:

A differenza di altre operazioni TensorFlow, non convertiamo input numerici python in tensori. Inoltre, viene generato un nuovo grafico per ciascun valore numerico python distinto

function crea un'istanza di un grafico separato per ogni set univoco di forme di input e tipi di dati .

Potrebbe essere necessario mappare un singolo oggetto tf.function su più grafici di calcolo sotto il cofano. Questo dovrebbe essere visibile solo come prestazione (i grafici di tracciamento hanno un costo computazionale e di memoria diverso da zero )

Processori di dati di input : simile al precedente, il processore viene selezionato caso per caso, a seconda dei flag interni impostati in base alle configurazioni di runtime (modalità di esecuzione, formato dei dati, strategia di distribuzione). Il caso più semplice è con Eager, che funziona direttamente con gli array Numpy. Per alcuni esempi specifici, vedi questa risposta .

MISURA MODELLO, MISURA DATI:

  • È decisivo; nessuna singola configurazione si incoronava in cima a tutte le dimensioni di modello e dati.
  • La dimensione dei dati relativa alla dimensione del modello è importante; per dati e modello di piccole dimensioni, può prevalere il sovraccarico di trasferimento dati (ad es. da CPU a GPU). Allo stesso modo, i piccoli processori overhead possono funzionare più lentamente su dati di grandi dimensioni per tempo di conversione dei dati dominante (vedere convert_to_tensor in "PROFILER")
  • La velocità differisce per i diversi circuiti dei circuiti di treno e di input dei diversi gestori di dati per la gestione delle risorse.

BENCHMARKS : la carne macinata. - Documento Word - Foglio di calcolo Excel

Terminologia :

  • % -less numeri sono tutti i secondi
  • % calcolato come (1 - longer_time / shorter_time)*100 ; motivazione: siamo interessati a quale fattore uno è più veloce dell'altro; shorter / longer è in realtà una relazione non lineare, non utile per il confronto diretto
  • Determinazione del segno%:
    • TF2 vs TF1: + se TF2 è più veloce
    • GvE (Graph vs. Eager): + se Graph è più veloce
  • TF2 = TensorFlow 2.0.0 + Keras 2.3.1; TF1 = TensorFlow 1.14.0 + Keras 2.2.5

PROFILER :

PROFILER - Spiegazione : Spyder 3.3.6 IDE profiler.

  • Alcune funzioni si ripetono nei nidi di altre; quindi, è difficile rintracciare l'esatta separazione tra le funzioni di "elaborazione dei dati" e di "addestramento", quindi ci saranno alcune sovrapposizioni, come si pronuncia nell'ultimo risultato.

  • % delle cifre calcolate runtime wrt meno tempo di costruzione

  • Tempo di costruzione calcolato sommando tutti i runtime (unici) che sono stati chiamati 1 o 2 volte
  • Tempo del treno calcolato sommando tutti i runtime (unici) che sono stati chiamati lo stesso numero di volte del numero di iterazioni e alcuni dei runtime dei loro nidi
  • Le funzioni sono profilate secondo i loro nomi originali , sfortunatamente (cioè _func = func si _func = func come func ), che si mescola nel tempo di costruzione - da qui la necessità di escluderlo

TEST DELL'AMBIENTE :

  • Codice eseguito in basso con attività in background minime in esecuzione
  • La GPU è stata "riscaldata" con alcune iterazioni prima di temporizzare le iterazioni, come suggerito in questo post
  • CUDA 10.0.130, cuDNN 7.6.0, TensorFlow 1.14.0 e TensorFlow 2.0.0 costruiti dalla sorgente, più Anaconda
  • Python 3.7.4, Spyder 3.3.6 IDE
  • GTX 1070, Windows 10, 24 GB di RAM DDR4 da 2,4 MHz, CPU i7-7700HQ da 2,8 GHz

METODOLOGIA :

  • Benchmark 'piccolo', 'medio', e 'grande' modello e dimensioni dei dati
  • Correzione del numero di parametri per ciascuna dimensione del modello, indipendentemente dalla dimensione dei dati di input
  • Il modello "più grande" ha più parametri e livelli
  • I dati "più grandi" hanno una sequenza più lunga, ma stessi batch_size e num_channels
  • I modelli usano solo Conv1D , Dense "apprendibili"; RNN evitati per implementazione della versione TF. differenze
  • Funzionava sempre con un treno al di fuori del ciclo di benchmarking, per omettere la costruzione di grafici di ottimizzatori e modelli
  • Non utilizzare dati sparsi (ad es. layers.Embedding() ) o target sparsi (ad es. SparseCategoricalCrossEntropy()

LIMITAZIONI : una risposta "completa" spiegherebbe ogni possibile ciclo del treno e iteratore, ma sicuramente oltre la mia capacità di tempo, busta paga inesistente o necessità generale. I risultati sono buoni quanto la metodologia: interpretare con una mente aperta.

CODICE :

import numpy as np
import tensorflow as tf
import random
from termcolor import cprint
from time import time

from tensorflow.keras.layers import Input, Dense, Conv1D
from tensorflow.keras.layers import Dropout, GlobalAveragePooling1D
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
import tensorflow.keras.backend as K
#from keras.layers import Input, Dense, Conv1D
#from keras.layers import Dropout, GlobalAveragePooling1D
#from keras.models import Model 
#from keras.optimizers import Adam
#import keras.backend as K

#tf.compat.v1.disable_eager_execution()
#tf.enable_eager_execution()

def reset_seeds(reset_graph_with_backend=None, verbose=1):
    if reset_graph_with_backend is not None:
        K = reset_graph_with_backend
        K.clear_session()
        tf.compat.v1.reset_default_graph()
        if verbose:
            print("KERAS AND TENSORFLOW GRAPHS RESET")

    np.random.seed(1)
    random.seed(2)
    if tf.__version__[0] == '2':
        tf.random.set_seed(3)
    else:
        tf.set_random_seed(3)
    if verbose:
        print("RANDOM SEEDS RESET")

print("TF version: {}".format(tf.__version__))
reset_seeds()

def timeit(func, iterations, *args, _verbose=0, **kwargs):
    t0 = time()
    for _ in range(iterations):
        func(*args, **kwargs)
        print(end='.'*int(_verbose))
    print("Time/iter: %.4f sec" % ((time() - t0) / iterations))

def make_model_small(batch_shape):
    ipt   = Input(batch_shape=batch_shape)
    x     = Conv1D(128, 40, strides=4, padding='same')(ipt)
    x     = GlobalAveragePooling1D()(x)
    x     = Dropout(0.5)(x)
    x     = Dense(64, activation='relu')(x)
    out   = Dense(1,  activation='sigmoid')(x)
    model = Model(ipt, out)
    model.compile(Adam(lr=1e-4), 'binary_crossentropy')
    return model

def make_model_medium(batch_shape):
    ipt = Input(batch_shape=batch_shape)
    x = ipt
    for filters in [64, 128, 256, 256, 128, 64]:
        x  = Conv1D(filters, 20, strides=1, padding='valid')(x)
    x     = GlobalAveragePooling1D()(x)
    x     = Dense(256, activation='relu')(x)
    x     = Dropout(0.5)(x)
    x     = Dense(128, activation='relu')(x)
    x     = Dense(64,  activation='relu')(x)
    out   = Dense(1,   activation='sigmoid')(x)
    model = Model(ipt, out)
    model.compile(Adam(lr=1e-4), 'binary_crossentropy')
    return model

def make_model_large(batch_shape):
    ipt   = Input(batch_shape=batch_shape)
    x     = Conv1D(64,  400, strides=4, padding='valid')(ipt)
    x     = Conv1D(128, 200, strides=1, padding='valid')(x)
    for _ in range(40):
        x = Conv1D(256,  12, strides=1, padding='same')(x)
    x     = Conv1D(512,  20, strides=2, padding='valid')(x)
    x     = Conv1D(1028, 10, strides=2, padding='valid')(x)
    x     = Conv1D(256,   1, strides=1, padding='valid')(x)
    x     = GlobalAveragePooling1D()(x)
    x     = Dense(256, activation='relu')(x)
    x     = Dropout(0.5)(x)
    x     = Dense(128, activation='relu')(x)
    x     = Dense(64,  activation='relu')(x)    
    out   = Dense(1,   activation='sigmoid')(x)
    model = Model(ipt, out)
    model.compile(Adam(lr=1e-4), 'binary_crossentropy')
    return model

def make_data(batch_shape):
    return np.random.randn(*batch_shape), \
           np.random.randint(0, 2, (batch_shape[0], 1))

def make_data_tf(batch_shape, n_batches, iters):
    data = np.random.randn(n_batches, *batch_shape),
    trgt = np.random.randint(0, 2, (n_batches, batch_shape[0], 1))
    return tf.data.Dataset.from_tensor_slices((data, trgt))#.repeat(iters)

batch_shape_small  = (32, 140,   30)
batch_shape_medium = (32, 1400,  30)
batch_shape_large  = (32, 14000, 30)

batch_shapes = batch_shape_small, batch_shape_medium, batch_shape_large
make_model_fns = make_model_small, make_model_medium, make_model_large
iterations = [200, 100, 50]
shape_names = ["Small data",  "Medium data",  "Large data"]
model_names = ["Small model", "Medium model", "Large model"]

def test_all(fit=False, tf_dataset=False):
    for model_fn, model_name, iters in zip(make_model_fns, model_names, iterations):
        for batch_shape, shape_name in zip(batch_shapes, shape_names):
            if (model_fn is make_model_large) and (batch_shape is batch_shape_small):
                continue
            reset_seeds(reset_graph_with_backend=K)
            if tf_dataset:
                data = make_data_tf(batch_shape, iters, iters)
            else:
                data = make_data(batch_shape)
            model = model_fn(batch_shape)

            if fit:
                if tf_dataset:
                    model.train_on_batch(data.take(1))
                    t0 = time()
                    model.fit(data, steps_per_epoch=iters)
                    print("Time/iter: %.4f sec" % ((time() - t0) / iters))
                else:
                    model.train_on_batch(*data)
                    timeit(model.fit, iters, *data, _verbose=1, verbose=0)
            else:
                model.train_on_batch(*data)
                timeit(model.train_on_batch, iters, *data, _verbose=1)
            cprint(">> {}, {} done <<\n".format(model_name, shape_name), 'blue')
            del model

test_all(fit=True, tf_dataset=False)

È stato citato da molti utenti come la ragione per passare a Pytorch, ma devo ancora trovare una giustificazione / spiegazione per sacrificare la più importante qualità pratica, velocità, per un'esecuzione entusiasta.

Di seguito sono riportate le prestazioni di benchmarking del codice, TF1 vs. TF2, con TF1 in esecuzione ovunque dal 47% al 276% più veloce .

La mia domanda è: che cos'è, a livello di grafico o hardware, che produce un rallentamento così significativo?

Alla ricerca di una risposta dettagliata, ho già familiarità con concetti generali. Git pertinente

Specifiche : CUDA 10.0.130, cuDNN 7.4.2, Python 3.7.4, Windows 10, GTX 1070

Risultati benchmark :

AGGIORNAMENTO : Disabilitare l'esecuzione desiderosa per il codice sottostante non aiuta. Il comportamento, tuttavia, è incoerente: a volte l'esecuzione in modalità grafica aiuta notevolmente, altre volte corre più lentamente rispetto a Eager.

Dato che gli sviluppatori di TF non compaiono in giro da nessuna parte, indagherò io stesso sulla questione: posso seguire i progressi nel problema di Github collegato.

AGGIORNAMENTO 2 : tonnellate di risultati sperimentali da condividere, insieme a spiegazioni; dovrebbe essere fatto oggi.

Codice benchmark :

# use tensorflow.keras... to benchmark tf.keras; used GPU for all above benchmarks
from keras.layers import Input, Dense, LSTM, Bidirectional, Conv1D
from keras.layers import Flatten, Dropout
from keras.models import Model
from keras.optimizers import Adam
import keras.backend as K
import numpy as np
from time import time

batch_shape = (32, 400, 16)
X, y = make_data(batch_shape)

model_small = make_small_model(batch_shape)
model_small.train_on_batch(X, y)  # skip first iteration which builds graph
timeit(model_small.train_on_batch, 200, X, y)

K.clear_session()  # in my testing, kernel was restarted instead

model_medium = make_medium_model(batch_shape)
model_medium.train_on_batch(X, y)  # skip first iteration which builds graph
timeit(model_medium.train_on_batch, 10, X, y)

Funzioni utilizzate :

def timeit(func, iterations, *args):
    t0 = time()
    for _ in range(iterations):
        func(*args)
    print("Time/iter: %.4f sec" % ((time() - t0) / iterations))

def make_small_model(batch_shape):
    ipt   = Input(batch_shape=batch_shape)
    x     = Conv1D(128, 400, strides=4, padding='same')(ipt)
    x     = Flatten()(x)
    x     = Dropout(0.5)(x)
    x     = Dense(64, activation='relu')(x)
    out   = Dense(1,  activation='sigmoid')(x)
    model = Model(ipt, out)
    model.compile(Adam(lr=1e-4), 'binary_crossentropy')
    return model

def make_medium_model(batch_shape):
    ipt   = Input(batch_shape=batch_shape)
    x     = Bidirectional(LSTM(512, activation='relu', return_sequences=True))(ipt)
    x     = LSTM(512, activation='relu', return_sequences=True)(x)
    x     = Conv1D(128, 400, strides=4, padding='same')(x)
    x     = Flatten()(x)
    x     = Dense(256, activation='relu')(x)
    x     = Dropout(0.5)(x)
    x     = Dense(128, activation='relu')(x)
    x     = Dense(64,  activation='relu')(x)
    out   = Dense(1,   activation='sigmoid')(x)
    model = Model(ipt, out)
    model.compile(Adam(lr=1e-4), 'binary_crossentropy')
    return model

def make_data(batch_shape):
    return np.random.randn(*batch_shape), np.random.randint(0, 2, (batch_shape[0], 1))

VERDETTO : non lo è , SE sai cosa stai facendo. Ma se non lo fai , potrebbe costarti molto, con alcuni aggiornamenti GPU in media e nel caso peggiore di più GPU.

QUESTA RISPOSTA : mira a fornire una descrizione di alto livello del problema, nonché linee guida su come decidere la configurazione della formazione specifica per le tue esigenze. Per una descrizione dettagliata di basso livello, che include tutti i risultati di benchmarking + il codice utilizzato, vedere la mia altra risposta.

Aggiornerò la / le mia / e risposta / e con ulteriori informazioni se ne apprendo - è possibile contrassegnare / "contrassegnare" questa domanda come riferimento.

SINTESI DEL PROBLEMA : come confirmed da uno sviluppatore di TensorFlow, Q. Scott Zhu, TF2 ha focalizzato lo sviluppo sull'esecuzione desiderosa e la stretta integrazione con Keras, che ha comportato cambiamenti radicali nella fonte TF - anche a livello di grafico. Vantaggi: capacità di elaborazione, distribuzione, debug e distribuzione notevolmente ampliate. Il costo di alcuni di questi, tuttavia, è la velocità.

La questione, tuttavia, è abbastanza più complessa. Non è solo TF1 vs. TF2 - i fattori che producono differenze significative nella velocità del treno includono:

  1. TF2 vs. TF1
  2. Modalità desideroso vs. grafico
  3. keras vs. tf.keras
  4. numpy vs. tf.data.Dataset vs. ...
  5. train_on_batch() vs. fit()
  6. GPU vs. CPU

Sfortunatamente, quasi nessuna delle precedenti è indipendente dall'altra e ognuna può almeno raddoppiare i tempi di esecuzione rispetto a un'altra. Fortunatamente, puoi determinare cosa funzionerà meglio sistematicamente e con alcune scorciatoie, come mostrerò.

COSA DOVREI FARE? Attualmente, l'unico modo è: sperimentare il modello, i dati e l'hardware specifici. Nessuna configurazione singola funzionerà sempre meglio, ma ci sono cose da fare e da non fare per semplificare la ricerca:

>> DO:

  • train_on_batch() + numpy + tf.keras + TF1 + Eager / Graph
  • train_on_batch() + numpy + tf.keras + TF2 + Grafico
  • fit() + numpy + tf.keras + TF1 / TF2 + Grafico + modello e dati di grandi dimensioni

>> NON:

  • fit() + numpy + keras per modelli e dati di piccole e medie dimensioni
  • fit() + numpy + tf.keras + TF1 / TF2 + Eager
  • train_on_batch() + numpy + keras + TF1 + Eager

  • [Major] tf.python.keras ; può funzionare 10-100 volte più lentamente e con molti bug; Ulteriori informazioni

    • Ciò include layers , models , optimizers e relative importazioni di utilizzo "out-of-box"; ops, utils e le relative importazioni "private" vanno bene, ma per essere sicuri, controlla gli alts e se sono usati in tf.keras

Fare riferimento al codice in fondo all'altra mia risposta per un esempio di impostazione di benchmarking. L'elenco sopra riportato si basa principalmente sulle tabelle "BENCHMARKS" nell'altra risposta.

LIMITAZIONI dei precedenti DO e NON:

  • Questa domanda si intitola "Perché TF2 è molto più lenta di TF1?", E mentre il suo corpo riguarda l'allenamento esplicito, la questione non si limita ad essa; anche l'inferenza è soggetta a importanti differenze di velocità, anche all'interno della stessa versione TF, importazione, formato dati, ecc. - vedi questa risposta .
  • È probabile che gli RNN cambino notevolmente la griglia di dati nell'altra risposta, poiché sono stati migliorati in TF2
  • I modelli utilizzavano principalmente Conv1D e Dense - nessun RNN, dati / target sparsi, input 4 / 5D e altre configurazioni
  • I dati di input sono limitati a numpy e tf.data.Dataset , mentre esistono molti altri formati; vedi altra risposta
  • È stata utilizzata la GPU; i risultati differiranno su una CPU. In effetti, quando ho posto la domanda, il mio CUDA non era configurato correttamente e alcuni dei risultati erano basati sulla CPU.

Perché TF2 ha sacrificato la qualità più pratica, la velocità, per un'esecuzione desiderosa? Non è chiaro, il grafico è ancora disponibile. Ma se la domanda è "perché ansioso":

  • Debug di qualità superiore : è probabile che ci siano molte domande che chiedono "come posso ottenere output di livello intermedio" o "come posso controllare i pesi"; con ansioso, è (quasi) semplice come .__dict__ . Il grafico, al contrario, richiede familiarità con le funzioni di backend speciali, complicando notevolmente l'intero processo di debug e introspezione.
  • Prototipazione più rapida : per idee simili a quelle sopra; comprensione più veloce = più tempo rimanente per il DL reale.

COME ATTIVARE / DISATTIVARE EAGER?

tf.enable_eager_execution()  # TF1; must be done before any model/tensor creation
tf.compat.v1.disable_eager_execution() # TF2; above holds

INFORMAZIONI AGGIUNTIVE :

  • Attento ai metodi _on_batch() in TF2; secondo lo sviluppatore TF, usano ancora un'implementazione più lenta, ma non intenzionalmente - cioè deve essere risolto. Vedi altra risposta per i dettagli.

RICHIESTE AI DISPOSITIVI TENSORFLOW :

  1. Correggi train_on_batch() e l'aspetto prestazionale di chiamare fit() iterativo; i circuiti personalizzati sono importanti per molti, specialmente per me.
  2. Aggiungi documentazione / docstring menzione di queste differenze di prestazioni per la conoscenza degli utenti.
  3. Migliora la velocità generale di esecuzione per impedire ai pip di saltare a Pytorch.

RINGRAZIAMENTI : Grazie a

  • D. Scott Zhu, sviluppatore di TensorFlow, per i suoi confirmed sull'argomento.
  • P. Andrey per aver condiviso test utili e discussioni.




tensorflow2.0