Ini telah dikutip oleh banyak pengguna sebagai alasan untuk beralih ke Pytorch, tetapi saya belum menemukan alasan / penjelasan untuk mengorbankan kualitas praktis yang paling penting, kecepatan, untuk pelaksanaan yang bersemangat.
Di bawah ini adalah kinerja pembandingan kode, TF1 vs TF2 - dengan TF1 berjalan di mana saja dari 47% menjadi 276% lebih cepat .
Pertanyaan saya adalah: apakah itu, pada grafik atau tingkat perangkat keras, yang menghasilkan perlambatan yang signifikan?
Mencari jawaban terinci - saya sudah terbiasa dengan konsep luas. Git yang relevan
Spesifikasi : CUDA 10.0.130, cuDNN 7.4.2, Python 3.7.4, Windows 10, GTX 1070
Hasil patok banding :
UPDATE : Menonaktifkan Eksekusi Eager per kode di bawah ini tidak membantu. Perilaku ini, bagaimanapun, tidak konsisten: kadang-kadang berjalan dalam mode grafik sangat membantu, di lain waktu itu berjalan lebih lambat dibandingkan dengan Eager.
Karena TF devs tidak muncul di mana-mana, saya akan menyelidiki masalah ini sendiri - dapat mengikuti kemajuan dalam masalah Github yang tertaut.
PEMBARUAN 2 : banyak hasil percobaan untuk dibagikan, beserta penjelasannya; harus dilakukan hari ini.
Kode 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)
Fungsi yang digunakan :
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))
sumber
Jawaban:
UPDATE 2/18/2020 : Saya telah duduk di bangku 2.1 dan 2.1 malam; hasilnya dicampur. Semua kecuali satu konfigurasi (model & ukuran data) secepat atau jauh lebih cepat daripada yang terbaik dari TF2 & TF1. Yang lebih lambat, dan lebih lambat secara dramatis, adalah Besar-Besar - esp. dalam eksekusi Grafik ( 1,6x ke 2,5x lebih lambat ).
Selain itu, ada perbedaan reproduktifitas ekstrim antara Graph dan Eager untuk model besar yang saya uji - yang tidak dapat dijelaskan melalui keacakan / kompute-paralelisme. Saat ini saya tidak dapat menyajikan kode yang dapat direproduksi untuk klaim ini per batasan waktu, jadi alih-alih saya sangat merekomendasikan pengujian ini untuk model Anda sendiri.
Belum membuka masalah Git tentang ini, tapi saya mengomentari aslinya - belum ada tanggapan. Saya akan memperbarui jawaban setelah kemajuan dibuat.
VERDICT : tidak , JIKA Anda tahu apa yang Anda lakukan. Tetapi jika Anda tidak melakukannya , harganya mungkin mahal, banyak - dengan beberapa peningkatan GPU rata-rata, dan oleh beberapa kasus terburuk GPU.
JAWABAN INI : bertujuan untuk memberikan deskripsi tingkat tinggi tentang masalah ini, serta pedoman untuk bagaimana memutuskan konfigurasi pelatihan khusus untuk kebutuhan Anda. Untuk deskripsi terperinci, tingkat rendah, yang mencakup semua hasil + kode pembandingan yang digunakan, lihat jawaban saya yang lain.
Saya akan memperbarui jawaban saya dengan info lebih lanjut jika saya mengetahui ada - dapat menandai / "membintangi" pertanyaan ini untuk referensi.
RINGKASAN MASALAH : sebagaimana dikonfirmasi oleh pengembang TensorFlow, Q. Scott Zhu, TF2 memfokuskan pengembangan pada pelaksanaan Eager & integrasi yang ketat dengan Keras, yang melibatkan perubahan menyeluruh pada sumber TF - termasuk di tingkat grafik. Manfaat: kemampuan pemrosesan, distribusi, debug, dan penyebaran yang sangat diperluas. Biaya beberapa di antaranya, bagaimanapun, adalah kecepatan.
Masalahnya, bagaimanapun, cukup rumit. Ini bukan hanya TF1 vs TF2 - faktor-faktor yang menghasilkan perbedaan kecepatan kereta yang signifikan termasuk:
keras
vs.tf.keras
numpy
vs.tf.data.Dataset
vs. ...train_on_batch()
vs.fit()
model(x)
vs.model.predict(x)
vs. ...Sayangnya, hampir tidak ada di atas yang independen dari yang lain, dan masing-masing setidaknya dapat menggandakan waktu eksekusi relatif terhadap yang lain. Untungnya, Anda dapat menentukan apa yang akan bekerja paling baik secara sistematis, dan dengan beberapa cara pintas - seperti yang akan saya tunjukkan.
APA YANG HARUS SAYA LAKUKAN? Saat ini, satu-satunya cara adalah - bereksperimen untuk model, data, dan perangkat keras spesifik Anda. Tidak ada satu konfigurasi yang akan selalu berfungsi dengan baik - tetapi ada yang harus dan yang tidak boleh dilakukan untuk menyederhanakan pencarian Anda:
>> LAKUKAN:
train_on_batch()
+numpy
+tf.keras
+ TF1 + Eager / Grafiktrain_on_batch()
+numpy
+tf.keras
+ TF2 + Grafikfit()
+numpy
+tf.keras
+ TF1 / TF2 + Grafik + model & data besar>> JANGAN:
fit()
+numpy
+keras
Untuk model kecil & menengah dan datafit()
+numpy
+tf.keras
+ TF1 / TF2 + Bersemangattrain_on_batch()
+numpy
+keras
+ TF1 + Ingin[Mayor]
tf.python.keras
; itu bisa berjalan 10-100x lebih lambat, dan dengan banyak bug; Info lebih lanjutlayers
,models
,optimizers
, & terkait "out-of-box" impor penggunaan; ops, utils, & impor 'pribadi' terkait baik-baik saja - tetapi untuk memastikan, periksa alts, & apakah mereka digunakan ditf.keras
Lihat kode di bagian bawah jawaban saya yang lain untuk contoh pengaturan benchmarking. Daftar di atas didasarkan terutama pada tabel "BENCHMARKS" di jawaban lain.
PEMBATASAN atas DO & JANGAN di atas:
Conv1D
danDense
- tidak ada RNN, data / target jarang, input 4 / 5D, & konfigurasi lainnyanumpy
dantf.data.Dataset
, sementara banyak format lain ada; lihat jawaban lainMengapa TF2 mengorbankan kualitas, kecepatan, untuk eksekusi yang paling praktis? Tidak, jelas - grafik masih tersedia. Tetapi jika pertanyaannya adalah "mengapa bersemangat sekali":
.__dict__
. Grafik, sebaliknya, membutuhkan keakraban dengan fungsi backend khusus - sangat menyulitkan seluruh proses debugging & introspeksi.BAGAIMANA CARA MENGaktifkan / MENONAKTIFKAN EAGER?
INFO TAMBAHAN :
_on_batch()
metode dalam TF2; menurut TF dev, mereka masih menggunakan implementasi lebih lambat, tetapi tidak sengaja - yaitu itu harus diperbaiki. Lihat jawaban lain untuk detailnya.PERMINTAAN UNTUK PERANGKAT TENSORFLOW :
train_on_batch()
, dan aspek kinerja dari panggilanfit()
iteratif; loop kereta adat penting bagi banyak orang, terutama bagi saya.UCAPAN TERIMA KASIH : Terima kasih kepada
PEMBARUAN :
11/14/19 - menemukan model (dalam aplikasi saya yang sebenarnya) yang berjalan lebih lambat pada TF2 untuk semua * konfigurasi dengan data input Numpy. Perbedaan berkisar 13-19%, rata-rata 17%. Perbedaan antara
keras
dantf.keras
, bagaimanapun, lebih dramatis: 18-40% , rata-rata. 32% (baik TF1 & 2). (* - kecuali Eager, di mana TF2 OOM)11/17/19 - devs memperbarui
on_batch()
metode dalam komit baru - baru ini , yang menyatakan telah meningkatkan kecepatan - untuk dirilis dalam TF 2.1, atau tersedia sekarang sebagaitf-nightly
. Karena saya tidak bisa menjalankan yang terakhir, akan menunda bangku hingga 2.1.sumber
fit_generator
? ... Saya hampir tidak pernah mautrain_on_batch
dan mengelola loop pelatihan saya sendiri di seluruh batch adalah sangat besar, anti-pola yang harus dihindari bahkan dengan biaya besar.fit
tambahan biaya pemrosesan data tambahan. Adapun loop kereta, saya menulis kustom saya sendiri yang akhirnya berubah menjadi semacam API;fit_generator
kurang introspeksi, kemampuan penyesuaian, dan menghemat / memuat - jadi tidak mutlak bagi saya. Saya akan menerbitkan loop pelatihan saya pada akhirnya, di Github.fit_generator
dengan aplikasi Anda adalah, baik, mengujinya.JAWABAN INI : bertujuan untuk memberikan deskripsi rinci, grafik / tingkat perangkat keras masalah - termasuk loop kereta TF2 vs TF1, prosesor data input, dan eksekusi mode Eager vs. Graph. Untuk ringkasan masalah & pedoman resolusi, lihat jawaban saya yang lain.
VERDICT PERFORMANCE : kadang-kadang satu lebih cepat, kadang-kadang yang lain, tergantung pada konfigurasi. Sejauh TF2 vs TF1 berjalan, mereka hampir setara, tetapi perbedaan berbasis konfigurasi yang signifikan memang ada, dan TF1 mengalahkan TF2 lebih sering daripada sebaliknya. Lihat "BENCHMARKING" di bawah ini.
EAGER VS. GRAFIK : daging dari seluruh jawaban ini untuk beberapa: keinginan TF2 lebih lambat dari pada TF1, menurut pengujian saya. Detail lebih jauh ke bawah.
Perbedaan mendasar antara keduanya adalah: Grafik mengatur jaringan komputasi secara proaktif , dan dijalankan ketika 'disuruh' - sedangkan Eager mengeksekusi semuanya saat penciptaan. Tetapi cerita hanya dimulai di sini:
Bersemangat TIDAK tanpa Grafik , dan mungkin sebagian besar Grafik, bertentangan dengan harapan. Apa itu sebagian besar, dijalankan Grafik - ini termasuk bobot model & pengoptimal, terdiri dari sebagian besar grafik.
Eager membangun kembali sebagian dari grafiknya sendiri pada saat eksekusi ; konsekuensi langsung dari Grafik yang tidak sepenuhnya dibangun - lihat hasil profiler. Ini memiliki overhead komputasi.
Eager lebih lambat dengan input Numpy ; sesuai komentar & kode Git ini , input Numpy di Eager termasuk biaya overhead untuk menyalin tensor dari CPU ke GPU. Melangkah melalui kode sumber, perbedaan penanganan data jelas; Bersemangat langsung melewati Numpy, sementara Grafik melewati tensor yang kemudian mengevaluasi ke Numpy; tidak yakin proses pastinya, tetapi yang terakhir harus melibatkan optimasi level GPU
TF2 Eager lebih lambat dari TF1 Eager - ini ... tidak terduga. Lihat hasil pembandingan di bawah ini. Perbedaan rentang dari diabaikan hingga signifikan, tetapi konsisten. Tidak yakin mengapa demikian - jika seorang TF mengklarifikasi, akan memperbarui jawaban.
TF2 vs. TF1 : mengutip bagian yang relevan dari TF dev, Q. Scott Zhu's, respons - dengan sedikit penekanan & penulisan ulang saya:
Dengan kalimat terakhir dari paragraf terakhir di atas, dan klausa terakhir dari paragraf di bawah:
Saya tidak setuju - per hasil profil saya, yang menunjukkan pemrosesan data input Eager jauh lebih lambat daripada Graph. Juga, tidak yakin tentang
tf.data.Dataset
khususnya, tetapi Eager berulang kali memanggil beberapa metode konversi data yang sama - lihat profiler.Terakhir, komitmen tertaut dev: Jumlah perubahan signifikan untuk mendukung loop Keras v2 .
Train Loops : tergantung pada (1) Eager vs. Graph; (2) memasukkan format data, pelatihan akan dilanjutkan dengan loop kereta yang berbeda - di TF2
_select_training_loop()
,, training.py , salah satu dari:Masing-masing menangani alokasi sumber daya secara berbeda, dan membawa konsekuensi pada kinerja & kemampuan.
Train Loops:
fit
vstrain_on_batch
,keras
vstf.keras
.: masing-masing dari empat menggunakan loop kereta yang berbeda, meskipun mungkin tidak dalam setiap kombinasi yang memungkinkan.keras
'fit
, misalnya, menggunakan bentukfit_loop
, misalnyatraining_arrays.fit_loop()
, dantrain_on_batch
mungkin menggunakanK.function()
.tf.keras
memiliki hierarki yang lebih canggih yang dijelaskan pada bagian di bagian sebelumnya.Train Loops: dokumentasi - dokumentasi sumber yang relevan tentang beberapa metode eksekusi yang berbeda:
Input data processor : mirip dengan di atas, prosesor dipilih kasus per kasus, tergantung pada flag internal yang diatur sesuai dengan konfigurasi runtime (mode eksekusi, format data, strategi distribusi). Kasing paling sederhana dengan Eager, yang bekerja langsung dengan array Numpy. Untuk beberapa contoh spesifik, lihat jawaban ini .
UKURAN MODEL, UKURAN DATA:
convert_to_tensor
di "PROFILER")BENCHMARKS : daging yang digiling. - Dokumen Word - Excel Spreadsheet
Terminologi :
(1 - longer_time / shorter_time)*100
; alasan: kami tertarik dengan faktor apa yang lebih cepat dari yang lain;shorter / longer
sebenarnya adalah hubungan non-linear, tidak berguna untuk perbandingan langsung+
jika TF2 lebih cepat+
jika Grafik lebih cepatPROFILER :
PROFILER - Penjelasan : Spyder 3.3.6 IDE profiler.
Beberapa fungsi diulang di sarang orang lain; karenanya, sulit untuk melacak pemisahan yang tepat antara fungsi "pemrosesan data" dan "pelatihan", sehingga akan ada beberapa tumpang tindih - seperti yang diucapkan dalam hasil terakhir.
% angka dihitung waktu kerja dikurangi dikurangi waktu pembuatan
_func = func
akan diprofilkan sebagaifunc
), yang bercampur dalam waktu pembuatan - karenanya perlu untuk mengecualikannyaLINGKUNGAN PENGUJIAN :
METODOLOGI :
batch_size
dannum_channels
Conv1D
,Dense
'dipelajari' lapisan; RNN dihindari per implem versi TF. perbedaanlayers.Embedding()
) Atau target jarang (misSparseCategoricalCrossEntropy()
BATASAN : jawaban "lengkap" akan menjelaskan setiap loop kereta & iterator yang mungkin, tetapi itu jelas di luar kemampuan waktu saya, gaji tidak ada, atau kebutuhan umum. Hasilnya hanya sebagus metodologi - menafsirkan dengan pikiran terbuka.
Kode :
sumber
model.compile
tanparun_eagerly=True
argumen. Jika dalam mode bersemangat, Anda dapat menjalankan bagian dari kode Anda dalam mode grafik menggunakantf.function
. Oleh karena itu saya pikir implementasi defaultcompile
adalah untuk membuat grafik komputasi daripada menjalankannya dengan penuh semangat untuk alasan kinerja. Perhatikan juga bahwa jika model Anda konvolusional maka Anda tidak melihat speedup dalam mode grafik karena interaksi python minimal. Jika Anda melakukan banyak operasi matematika, itu dapat membuat perbedaan besar (juga dalam pemanfaatan memori).model.compile
tanparun_eagerly=True
memastikan mode grafik, atau tidak?model.compile
ataumodel.fit
harus memastikan bahwa pelatihan berjalan dalam mode grafik secara internal.run_eagerly=True
sebagai parameter untuk dikompilasi." (sumber tensorflow.org/guide/keras/overview ) Oleh karena itu saya jika Anda tidak lulusrun_eagerly=True
model BISA berjalan dalam mode grafik. Saya tidak yakin apa yang menjadi faktor penentu tetapi mengapa itu tidak berjalan dalam mode grafik jika lebih efisien daripada bersemangat.