Genel Bakış
Bu kılavuz, TensorFlow Profiler ve tf.data
bilgi sahibi olduğunuzu varsayar. Kullanıcıların giriş ardışık düzeni performans sorunlarını teşhis etmesine ve düzeltmesine yardımcı olmak için örneklerle birlikte adım adım talimatlar sağlamayı amaçlamaktadır.
Başlamak için TensorFlow işinizin bir profilini toplayın. Bunun nasıl yapılacağına ilişkin talimatlar CPU'lar / GPU'lar ve Cloud TPU'lar için mevcuttur .
Aşağıda ayrıntıları verilen analiz iş akışı, Profiler'daki izleme görüntüleyici aracına odaklanır. Bu araç, TensorFlow programınız tarafından yürütülen işlemlerin süresini gösteren bir zaman çizelgesi görüntüler ve hangi işlemlerin yürütülmesinin en uzun sürdüğünü belirlemenize olanak tanır. İz görüntüleyici hakkında daha fazla bilgi için, TF Profiler kılavuzunun bu bölümüne bakın . Genel olarak, tf.data
olayları ana bilgisayar CPU zaman çizelgesinde görünecektir.
Analiz İş Akışı
Lütfen aşağıdaki iş akışını takip edin. İyileştirmemize yardımcı olacak geri bildiriminiz varsa, lütfen "comp: data" etiketiyle bir github sorunu oluşturun .
1. tf.data
ardışık tf.data
yeterince hızlı veri üretiyor mu?
Giriş ardışık düzeninin TensorFlow programınız için darboğaz olup olmadığını belirleyerek başlayın.
Bunu yapmak için izleme görüntüleyicide IteratorGetNext::DoCompute
işlemlerini IteratorGetNext::DoCompute
. Genel olarak, bunları bir adımın başında görmeyi beklersiniz. Bu dilimler, girdi ardışık düzeninizin istendiğinde bir dizi öğe vermesi için geçen süreyi temsil eder. Keras kullanıyorsanız veya bir tf.function
veri kümeniz üzerinde yineleme tf.function
, bunlar tf_data_iterator_get_next
iş parçacıklarında tf_data_iterator_get_next
.
Bir dağıtım stratejisi kullanıyorsanız, IteratorGetNext::DoCompute
(TF 2.3'ten itibaren) yerine IteratorGetNextAsOptional::DoCompute
olaylarını görebileceğinizi IteratorGetNextAsOptional::DoCompute
.
Çağrılar hızlı bir şekilde geri gelirse (<= 50 bize), bu, verilerinizin istendiğinde kullanılabilir olduğu anlamına gelir. Giriş ardışık düzeni, darboğazınız değildir; Daha genel performans analizi ipuçları için Profiler kılavuzuna bakın.
Çağrılar yavaş tf.data
, tf.data
, tüketicinin isteklerine yetişemez. Sonraki bölüme devam edin.
2. Verileri önceden mi yüklüyorsunuz?
Giriş ardışık tf.data.Dataset.prefetch
performansı için en iyi uygulama, tf.data
ardışık tf.data
sonuna bir tf.data.Dataset.prefetch
dönüşümü tf.data
. Bu dönüşüm, girdi ardışık düzeninin ön işleme hesaplamasını bir sonraki model hesaplama adımı ile örtüşür ve modelinizi eğitirken optimum girdi ardışık düzeni performansı için gereklidir. Verileri önceden IteratorGetNext::DoCompute
, IteratorGetNext::DoCompute
aynı iş parçacığı üzerinde bir Iterator::Prefetch
dilimi IteratorGetNext::DoCompute
.
Ardışık prefetch
sonunda bir prefetch
yüklemeniz yoksa, bir tane eklemelisiniz. tf.data
performans önerileri hakkında daha fazla bilgi için tf.data performans kılavuzuna bakın .
Zaten verileri önceden getiriyorsanız ve giriş ardışık düzeni hala darboğazınızsa, performansı daha ayrıntılı analiz etmek için sonraki bölüme geçin.
3. Yüksek CPU kullanımına mı ulaşıyorsunuz?
tf.data
, mevcut kaynakları mümkün olan en iyi şekilde kullanmaya çalışarak yüksek verim elde eder. Genel olarak, modelinizi GPU veya TPU gibi bir hızlandırıcıda çalıştırırken bile, tf.data
ardışık tf.data
CPU üzerinde çalıştırılır. Kullanımınızı sar ve htop gibi araçlarla veya GCP'de çalıştırıyorsanız bulut izleme konsolunda kontrol edebilirsiniz.
Kullanımınız düşükse, bu, giriş ardışık düzeninizin ana bilgisayar CPU'sundan tam olarak yararlanmıyor olabileceğini gösterir. En iyi uygulamalar için tf.data performans kılavuzuna başvurmalısınız. En iyi uygulamaları uyguladıysanız ve kullanım ve aktarım hızı düşükse, aşağıdaki Darboğaz analizine devam edin.
Kullanımınız kaynak sınırına yaklaşıyorsa, performansı daha da iyileştirmek için, giriş ardışık düzeninizin verimliliğini (örneğin, gereksiz hesaplamadan kaçınmak) veya yük aktarımı hesaplamasını iyileştirmeniz gerekir.
tf.data
gereksiz hesaplamalardan kaçınarak girdi ardışık tf.data
. Bunu yapmanın bir yolu, verileriniz belleğe tf.data.Dataset.cache
yoğun hesaplama gerektiren çalışmadan sonra tf.data.Dataset.cache
dönüşümü tf.data.Dataset.cache
; bu, artan bellek kullanımı pahasına hesaplamayı azaltır. Ek olarak, tf.data
operasyon içi paralelliği devre dışı bırakmak, verimliliği% 10'dan fazla artırma potansiyeline sahiptir ve giriş ardışık düzeninizde aşağıdaki seçeneği ayarlayarak yapılabilir:
dataset = ...
options = tf.data.Options()
options.experimental_threading.max_intra_op_parallelism = 1
dataset = dataset.with_options(options)
4. Darboğaz Analizi
Aşağıdaki bölümde, darboğazın nerede olduğunu ve olası azaltma stratejilerini anlamak için izleme görüntüleyicide tf.data
olaylarının nasıl okunacağı tf.data
.
Profiler'da tf.data
olaylarını anlama
Profiler'daki her tf.data
olayının Iterator::<Dataset>
adı vardır; burada <Dataset>
, veri kümesi kaynağının veya dönüşümün adıdır. Her olay, tf.data
olayına tıklayarak görebileceğiniz uzun Iterator::<Dataset_1>::...::<Dataset_n>
tf.data
de tf.data
. Uzun adda, <Dataset_n>
(kısa) <Dataset_n>
<Dataset>
<Dataset_n>
eşleşir ve uzun <Dataset_n>
diğer veri kümeleri aşağı akış dönüşümlerini temsil eder.
Örneğin, yukarıdaki ekran görüntüsü aşağıdaki koddan oluşturulmuştur:
dataset = tf.data.Dataset.range(10)
dataset = dataset.map(lambda x: x)
dataset = dataset.repeat(2)
dataset = dataset.batch(5)
Burada, Iterator::Map
olayının uzun adı Iterator::BatchV2::FiniteRepeat::Map
. Veri kümelerinin adının python API'sinden biraz farklı olabileceğini (örneğin Repeat yerine FiniteRepeat), ancak ayrıştırmak için yeterince sezgisel olması gerektiğini unutmayın.
Eşzamanlı ve eşzamansız dönüşümler
Eşzamanlı tf.data
dönüşümleri için ( Batch
ve Map
), aynı iş parçacığı üzerinde yukarı akış dönüşümlerinden gelen olayları göreceksiniz. Yukarıdaki örnekte, kullanılan tüm dönüştürmeler eşzamanlı olduğundan, tüm olaylar aynı iş parçacığında görünür.
Eşzamansız dönüşümler için ( Prefetch
, ParallelMap
, ParallelInterleave
ve MapAndBatch
) yukarı akış dönüşümlerinden gelen olaylar farklı bir iş parçacığında olacaktır. Bu gibi durumlarda, "uzun ad" bir olayın bir kanaldaki hangi dönüşüme karşılık geldiğini belirlemenize yardımcı olabilir.
Örneğin, yukarıdaki ekran görüntüsü aşağıdaki koddan oluşturulmuştur:
dataset = tf.data.Dataset.range(10)
dataset = dataset.map(lambda x: x)
dataset = dataset.repeat(2)
dataset = dataset.batch(5)
dataset = dataset.prefetch(1)
Burada, Iterator::Prefetch
olayları tf_data_iterator_get_next
konuları üzerindedir. Prefetch
eşzamansız olduğundan, girdi olayları ( BatchV2
) farklı bir iş parçacığında olacaktır ve Iterator::Prefetch::BatchV2
uzun adı Iterator::Prefetch::BatchV2
. Bu durumda, bunlar tf_data_iterator_resource
iş parçacığı üzerindedir. Uzun adından, BatchV2
Prefetch
yukarı akışı olduğunu BatchV2
. Bundan başka, parent_id
arasında BatchV2
olay numarası eşleşir Prefetch
etkinliği.
Darboğazın belirlenmesi
Genel olarak, girdi ardışık düzeninizdeki darboğazı belirlemek için, girdi ardışık düzenini en dıştaki dönüşümden kaynağa kadar yürüyün. TFRecord
son dönüşümden başlayarak, yavaş bir dönüşüm bulana veya TFRecord
gibi bir kaynak veri kümesine ulaşana kadar yukarı akış dönüşümlerine TFRecord
. Yukarıdaki örnekte, başlayacağını Prefetch
sonra, yukarı yönde yürümeye BatchV2
, FiniteRepeat
, Map
ve son olarak Range
.
Genel olarak, yavaş bir dönüşüm, olayları uzun olan ancak girdi olayları kısa olana karşılık gelir. Aşağıda bazı örnekler verilmiştir.
Çoğu ana bilgisayar girdi ardışık Iterator::Model
son (en dıştaki) dönüşümün Iterator::Model
olayı olduğunu unutmayın. Model dönüşümü tf.data
çalışma zamanı tarafından otomatik olarak tanıtılır ve giriş ardışık tf.data
performansını tf.data
ve otomatik olarak ayarlamak için kullanılır.
İşiniz bir dağıtım stratejisi kullanıyorsa, izleme görüntüleyici, cihaz giriş ardışık düzenine karşılık gelen ek olaylar içerecektir. Aygıt ardışık IteratorGetNextOp::DoCompute
en dıştaki dönüşümü ( IteratorGetNextOp::DoCompute
veya IteratorGetNextAsOptionalOp::DoCompute
altında yuvalanmış), yukarı akış Iterator::Generator
olayına sahip bir Iterator::Prefetch
olayı olacaktır. Iterator::Model
olaylarını arayarak ilgili ana bilgisayar ardışık Iterator::Model
bulabilirsiniz.
örnek 1
Yukarıdaki ekran görüntüsü aşağıdaki giriş hattından oluşturulmuştur:
dataset = tf.data.TFRecordDataset(filename)
dataset = dataset.map(parse_record)
dataset = dataset.batch(32)
dataset = dataset.repeat()
Ekran görüntüsünde, (1) Iterator::Map
olaylarının uzun olduğunu, ancak (2) girdi olaylarının ( Iterator::FlatMap
) hızlı bir şekilde geri döndüğünü Iterator::FlatMap
. Bu, sıralı Harita dönüşümünün darboğaz olduğunu göstermektedir.
Ekran görüntüsünde, InstantiatedCapturedFunction::Run
olayının, harita işlevini yürütmek için geçen süreye karşılık geldiğini unutmayın.
Örnek 2
Yukarıdaki ekran görüntüsü aşağıdaki giriş hattından oluşturulmuştur:
dataset = tf.data.TFRecordDataset(filename)
dataset = dataset.map(parse_record, num_parallel_calls=2)
dataset = dataset.batch(32)
dataset = dataset.repeat()
Bu örnek yukarıdakine benzer, ancak Map yerine ParallelMap kullanır. Burada (1) Iterator::ParallelMap
olaylarının uzun olduğunu, ancak (2) girdi olaylarının Iterator::FlatMap
(ParallelMap eşzamansız olduğundan farklı bir Iterator::FlatMap
olan) kısa olduğunu fark Iterator::FlatMap
. Bu, ParallelMap dönüşümünün darboğaz olduğunu gösterir.
Darboğazı ele almak
Kaynak veri kümeleri
TFRecord dosyalarından okumak gibi darboğaz olarak bir veri kümesi kaynağı tanımladıysanız, veri çıkarmayı paralelleştirerek performansı artırabilirsiniz. Bunu yapmak için, verilerinizin birden çok dosyada tf.data.Dataset.interleave
emin olun ve tf.data.Dataset.interleave
num_parallel_calls
parametresi num_parallel_calls
ayarlanmış şekilde tf.data.AUTOTUNE
. Belirleyicilik programınız için önemli değilse, TF tf.data.Dataset.interleave
itibaren tf.data.Dataset.interleave
deterministic=False
bayrağını ayarlayarak performansı daha da artırabilirsiniz. Örneğin, TFRecords'tan okuyorsanız, aşağıdakileri yapabilirsiniz:
dataset = tf.data.Dataset.from_tensor_slices(filenames)
dataset = dataset.interleave(tf.data.TFRecordDataset,
num_parallel_calls=tf.data.AUTOTUNE,
deterministic=False)
Parçalanmış dosyaların, bir dosyayı açmanın ek yükünü amorti etmek için makul ölçüde büyük olması gerektiğini unutmayın. Paralel veri çıkarma hakkında daha fazla ayrıntı için, tf.data
performans kılavuzunun bu bölümüne bakın.
Dönüşüm veri kümeleri
Darboğaz olarak bir ara tf.data
dönüşümü tanımladıysanız, verileriniz belleğe sığıyorsa ve uygunsa, dönüşümü paralelleştirerek veya hesaplamayı önbelleğe alarak bunu ele alabilirsiniz. Map
gibi bazı dönüşümlerin paralel karşılıkları vardır; tf.data
performans kılavuzu bunların nasıl paralelleştirileceğini gösterir . Filter
, Unbatch
ve Batch
gibi diğer dönüştürmeler doğası gereği sıralıdır; bunları "dış paralellik" ile paralel hale getirebilirsiniz. Örneğin, başlangıçta giriş boru hattı varsayarsak ile, aşağıdaki gibi görünüyor Batch
darboğaz olarak:
filenames = tf.data.Dataset.list_files(file_path, shuffle=is_training)
dataset = filenames_to_dataset(filenames)
dataset = dataset.batch(batch_size)
Parçalanmış girdiler üzerinde girdi ardışık düzeninin birden çok kopyasını çalıştırarak ve sonuçları birleştirerek "dış paralellik" sağlayabilirsiniz:
filenames = tf.data.Dataset.list_files(file_path, shuffle=is_training)
def make_dataset(shard_index):
filenames = filenames.shard(NUM_SHARDS, shard_index)
dataset = filenames_to_dataset(filenames)
Return dataset.batch(batch_size)
indices = tf.data.Dataset.range(NUM_SHARDS)
dataset = indices.interleave(make_dataset,
num_parallel_calls=tf.data.AUTOTUNE)
dataset = dataset.prefetch(tf.data.AUTOTUNE)
Ek kaynaklar
- performansın nasıl yazılacağına ilişkin tf.data performans kılavuzu
tf.data
input pipelines - TensorFlow videosunun içi:
tf.data
en iyi uygulamaları - Profil oluşturucu kılavuzu
- Colab ile Profiler öğreticisi