Bu sayfa, Cloud Translation API ile çevrilmiştir.
Switch to English

TF Profiler ile tf.data performansını analiz edin

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 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 .

TensorFlow Trace Viewer

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. İzleme 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?

Girdi ardışık düzeninin TensorFlow programınız için darboğaz olup olmadığını tespit ederek 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 itibariyle) yerine IteratorGetNextAsOptional::DoCompute olaylarını görebileceğinizi IteratorGetNextAsOptional::DoCompute .

image

Çağrılar hızlı bir şekilde geri gelirse (<= 50 bize), bu, verilerinizin istendiğinde kullanılabilir olduğu anlamına gelir. Girdi ardışık düzeni, darboğazınız değildir; Daha genel performans analizi ipuçları için Profiler kılavuzuna bakın.

image

Çağrılar yavaş tf.data , tf.data tüketicinin isteklerine yetişemez. Sonraki bölüme devam edin.

2. Verileri önceden mi getiriyorsunuz?

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 .

image

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 hâlâ darboğazınızsa, performansı daha fazla analiz etmek için bir 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 işleme 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, girdi ardışık düzeninizin verimliliğini (örneğin, gereksiz hesaplamadan kaçınarak) 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ışmalardan sonra bir 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ün adıdır. Her olay, tf.data olayına tıklayarak görebileceğiniz uzun bir 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.

image

Ö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ırılacak kadar 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üştürmelerinden gelen olayları göreceksiniz. Yukarıdaki örnekte, kullanılan tüm dönüşümler 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.

image

Ö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 olacak ve Iterator::Prefetch::BatchV2 uzun adı Iterator::Prefetch::BatchV2 . Bu durumda, tf_data_iterator_resource iş parçacığında yer tf_data_iterator_resource . 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şıncaya 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 .

Genelde 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

image

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ızla 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

image

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ğu için farklı bir iş parçacığında 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.experimental.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.experimental.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; "dış paralelliği" tanıtarak bunları paralelleştirebilirsiniz. Ö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.experimental.AUTOTUNE)
dataset = dataset.prefetch(tf.data.experimental.AUTOTUNE)

Ek kaynaklar