این صفحه به‌وسیله ‏Cloud Translation API‏ ترجمه شده است.
Switch to English

ورودی توزیع شده

مشاهده در TensorFlow.org در Google Colab اجرا کنید مشاهده منبع در GitHub بارگیری نوت بوک

API های tf.distribute روشی آسان برای کاربران فراهم می کند تا آموزش های خود را از یک دستگاه واحد تا چندین ماشین اندازه گیری کنند. کاربران هنگام مقیاس بندی مدل خود ، کاربران نیز مجبورند توزیع ورودی خود را در چندین دستگاه پخش کنند. tf.distribute API را فراهم می کند که با استفاده از آنها می توانید ورودی خود را به طور خودکار در دستگاه ها توزیع کنید.

این راهنما روشهای مختلفی را نشان می دهد که با استفاده از API های tf.distribute می توانید مجموعه داده توزیع شده و تکرار tf.distribute ها را ایجاد کنید. علاوه بر این ، موضوعات زیر پوشش داده می شود:

این راهنما استفاده از ورودی توزیع شده با API های Keras را پوشش نمی دهد.

مجموعه داده های توزیع شده

برای استفاده از API های tf.distribute برای مقیاس ، توصیه می شود کاربران از tf.data.Dataset برای نشان دادن ورودی خود استفاده کنند. tf.distribute برای کارآمد با tf.data.Dataset (برای مثال ، پیش نمایش خودکار داده ها بر روی هر دستگاه شتاب دهنده) با بهینه سازی عملکرد به طور منظم در پیاده سازی قرار می گیرد. اگر یک مورد استفاده برای استفاده از چیزی غیر از tf.data.Dataset دارید ، لطفاً به بخش بعدی در این راهنما مراجعه کنید. در یک حلقه آموزشی غیر توزیع ، کاربران ابتدا یک نمونه tf.data.Dataset ایجاد می کنند و سپس بر روی عناصر تکرار می کنند. مثلا:

 import tensorflow as tf

# Helper libraries
import numpy as np
import os

print(tf.__version__)
 
2.3.0

 global_batch_size = 16
# Create a tf.data.Dataset object.
dataset = tf.data.Dataset.from_tensors(([1.], [1.])).repeat(100).batch(global_batch_size)

@tf.function
def train_step(inputs):
  features, labels = inputs
  return labels - 0.3 * features

# Iterate over the dataset using the for..in construct.
for inputs in dataset:
  print(train_step(inputs))

 
tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(4, 1), dtype=float32)

برای اینکه کاربران بتوانند از استراتژی tf.distribute با حداقل تغییر در کد موجود کاربر استفاده کنند ، دو API معرفی شدند که یک نمونه tf.data.Dataset را توزیع می tf.data.Dataset و یک شیء داده داده توزیع شده را باز می گردانند. سپس کاربر می تواند بیش از این نمونه داده های توزیع شده تکرار شود و مانند گذشته مدل خود را آموزش دهد. بگذارید اکنون به دو API نگاه کنیم - tf.distribute.Strategy.experimental_distribute_dataset و tf.distribute.Strategy.experimental_distribute_datasets_from_function با جزئیات بیشتر:

tf.distribute.Strategy.experimental_distribute_dataset

طریقه استفاده

این API یک نمونه tf.data.Dataset به عنوان ورودی در نظر می گیرد و نمونه tf.distribute.DistributedDataset برمی گرداند. شما باید مجموعه داده ورودی را با مقداری برابر با اندازه جهانی جهانی انجام دهید. این اندازه دسته جهانی تعداد نمونه هایی است که می خواهید در 1 مرحله در کلیه دستگاه ها پردازش کنید. می توانید بیش از این مجموعه داده توزیع شده با روشی Pythonic تکرار کنید یا با استفاده از iter یک iterator ایجاد کنید. شی مورد بازگشت نمونه ای از tf.data.Dataset نیست و از هیچ API دیگری که tf.data.Dataset به هر شکلی تبدیل یا بازرسی کند ، پشتیبانی نمی کند. این API پیشنهادی است اگر شما روش های خاصی ندارید که بخواهید ورودی خود را از ماکت های مختلف جدا کنید.

 global_batch_size = 16
mirrored_strategy = tf.distribute.MirroredStrategy()

dataset = tf.data.Dataset.from_tensors(([1.], [1.])).repeat(100).batch(global_batch_size)
# Distribute input using the `experimental_distribute_dataset`.
dist_dataset = mirrored_strategy.experimental_distribute_dataset(dataset)
# 1 global batch of data fed to the model in 1 step.
print(next(iter(dist_dataset)))
 
INFO:tensorflow:Using MirroredStrategy with devices ('/job:localhost/replica:0/task:0/device:GPU:0',)
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/data/ops/multi_device_iterator_ops.py:601: get_next_as_optional (from tensorflow.python.data.ops.iterator_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Use `tf.data.Iterator.get_next_as_optional()` instead.
(<tf.Tensor: shape=(16, 1), dtype=float32, numpy=
array([[1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.]], dtype=float32)>, <tf.Tensor: shape=(16, 1), dtype=float32, numpy=
array([[1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.]], dtype=float32)>)

خصوصیات

دسته بندی

tf.distribute دوباره با ورودی tf.data.Dataset ورودی با اندازه دسته جدید برابر است با اندازه دسته جهانی برابر با تعداد ماکت ها در همگام سازی. تعداد ماکت ها در همگام سازی برابر با تعداد دستگاه هایی است که در طول آموزش در گرادیان گرادیان شرکت می کنند. وقتی یک کاربر با تکرار توزیع شده next تماس می گیرد ، اندازه هر دسته از داده ها در هر ماکت برمی گردد. کاردینالیت مجموعه داده rebatched همیشه تعداد مکرر از تعداد تکرارها خواهد بود. در اینجا چند نمونه آورده شده است:

  • tf.data.Dataset.range(6).batch(4, drop_remainder=False)

    بدون توزیع:

    دسته 1: [0 ، 1 ، 2 ، 3]

    دسته 2: [4 ، 5]

    با توزیع بیش از 2 تکرار:

    دسته 1: Replica 1: [0، 1] Replica 2: [2، 3]

    دسته 2: ماکت 2: [4] ماکت 2: [5]

    آخرین دسته ([4 ، 5]) بین 2 تکرار تقسیم می شود.

  • tf.data.Dataset.range(4).batch(4)

    بدون توزیع:

    دسته 1: [[0] ، [1] ، [2] ، [3]]

    با توزیع بیش از 5 تکرار:

    دسته 1: ماکت 1: [0] ماکت 2: [1] ماکت 3: [2] ماکت 4: [3] ماکت 5: []

  • tf.data.Dataset.range(8).batch(4)

    بدون توزیع:

    دسته 1: [0 ، 1 ، 2 ، 3]

    دسته 2: [4 ، 5 ، 6 ، 7]

    با توزیع بیش از 3 تکرار:

    دسته 1: Replica 1: [0، 1] Replica 2: [2، 3] Replica 3: []

    دسته 2: ماکت 1: [4 ، 5] ماکت 2: [6 ، 7] ماکت 3: []

Rebatching مجموعه داده دارای یک پیچیدگی فضایی است که به صورت خطی با تعداد ماکت ها افزایش می یابد. این بدان معنی است که برای مورد استفاده از آموزش چند کارگر ، خط لوله ورودی می تواند خطاهای OOM را اجرا کند.

خرد کردن

tf.distribute همچنین داده های ورودی را در آموزش چند کارگر ذخیره می کند. هر مجموعه داده بر روی دستگاه CPU کارگر ایجاد می شود. به اشتراک گذاشتن مجموعه داده از روی مجموعه ای از کارگران به این معنی است که به هر کارگر یک زیر مجموعه از کل مجموعه داده ها اختصاص داده می شود (در صورت تنظیم مناسب tf.data.experimental.AutoShardPolicy ). این امر برای اطمینان از اینكه در هر مرحله ، اندازه جهانی دسته ای از عناصر داده غیر همپوشانی توسط هر كارگر پردازش می شود. Autoshading چندین گزینه مختلف دارد که می توان با استفاده از tf.data.experimental.DistributeOptions مشخص tf.data.experimental.DistributeOptions .

 dataset = tf.data.Dataset.from_tensors(([1.],[1.])).repeat(64).batch(16)
options = tf.data.Options()
options.experimental_distribute.auto_shard_policy = tf.data.experimental.AutoShardPolicy.DATA
dataset = dataset.with_options(options)
 

سه گزینه مختلف وجود دارد که می توانید برای tf.data.experimental.AutoShardPolicy :

  • AUTO: این گزینه پیش فرض است و این بدان معنی است که سعی خواهد شد FILE از آن استفاده شود. در صورت عدم شناسایی مجموعه داده های مبتنی بر پرونده ، تلاش برای shard کردن توسط FILE انجام می شود. tf.distribute سپس توسط DATA به برش خورده باز می گردد. توجه داشته باشید که اگر مجموعه داده ورودی مبتنی بر پرونده است اما تعداد پرونده ها از تعداد کارگران کمتر است ، خطایی ایجاد می شود.
  • FILE: اگر می خواهید پرونده های ورودی را بر روی همه کارگران خرد کنید. اگر تعداد پرونده ها از تعداد کارگران کمتر باشد ، خطایی ایجاد می شود. اگر تعداد پرونده های ورودی بسیار بیشتر از تعداد کارگران است و داده های موجود در پرونده ها به طور مساوی توزیع شده است ، باید از این گزینه استفاده کنید. اگر داده های موجود در پرونده ها به طور مساوی توزیع نشود ، نکته منفی این کار در کارگران بیکار است. به عنوان مثال ، اجازه دهید ما 2 پرونده را در 2 کارگر با هر یک ماکت توزیع کنیم. پرونده 1 شامل [0 ، 1 ، 2 ، 3 ، 4 ، 5] است و پرونده 2 شامل [6 ، 7 ، 8 ، 9 ، 10 ، 11] است. بگذارید تعداد کل ماکت ها در همگام سازی 2 و اندازه دسته جهانی 4 باشد.

    • کارگر 0:

    دسته 1 = ماکت 1: [0 ، 1]

    دسته 2 = ماکت 1: [2 ، 3]

    دسته 3 = ماکت 1: [4]

    دسته 4 = ماکت 1: [5]

    • کارگر 1:

    دسته 1 = ماکت 2: [6 ، 7]

    دسته 2 = ماکت 2: [8 ، 9]

    دسته 3 = ماکت 2: [10]

    دسته 4 = ماکت 2: [11]

  • DATA: این عناصر را در بین همه کارگران تکمیل می کند. هر یک از کارگران کل مجموعه داده ها را می خوانند و فقط تکه های اختصاص داده شده به آن را پردازش می کنند. تمام بندهای دیگر دور ریخته می شوند. این به طور کلی استفاده می شود اگر تعداد پرونده های ورودی کمتر از تعداد کارگران باشد و شما می خواهید به اشتراک گذاری داده ها در همه کارگران بهتر شود. نکته منفی این است که کل مجموعه داده ها روی هر کارگر خوانده می شود. به عنوان مثال ، اجازه دهید ما 1 پرونده را در 2 کارگر توزیع کنیم. پرونده 1 شامل [0 ، 1 ، 2 ، 3 ، 4 ، 5 ، 6 ، 7 ، 8 ، 9 ، 10 ، 11] است. بگذارید تعداد کل ماکت ها در همگام سازی 2 باشد.

    • کارگر 0:

    دسته 1 = ماکت 1: [0 ، 1]

    دسته 2 = ماکت 1: [4 ، 5]

    دسته 3 = ماکت 1: [8 ، 9]

    • کارگر 1:

    دسته 1 = ماکت 2: [2 ، 3]

    دسته 2 = ماکت 2: [6 ، 7]

    دسته 3 = ماکت 2: [10 ، 11]

  • خاموش: اگر تأسیس خودکار را خاموش کنید ، هر کارگر تمام داده ها را پردازش می کند. به عنوان مثال ، اجازه دهید ما 1 پرونده را در 2 کارگر توزیع کنیم. پرونده 1 شامل [0 ، 1 ، 2 ، 3 ، 4 ، 5 ، 6 ، 7 ، 8 ، 9 ، 10 ، 11] است. بگذارید تعداد کل ماکت ها در همگام سازی 2 باشد. سپس هر کارگر توزیع زیر را مشاهده می کند:

    • کارگر 0:

    دسته 1 = ماکت 1: [0 ، 1]

    دسته 2 = ماکت 1: [2 ، 3]

    دسته 3 = ماکت 1: [4 ، 5]

    دسته 4 = ماکت 1: [6 ، 7]

    دسته 5 = ماکت 1: [8 ، 9]

    دسته 6 = ماکت 1: [10 ، 11]

    • کارگر 1:

    دسته 1 = ماکت 2: [0 ، 1]

    دسته 2 = ماکت 2: [2 ، 3]

    دسته 3 = ماکت 2: [4 ، 5]

    دسته 4 = ماکت 2: [6 ، 7]

    دسته 5 = ماکت 2: [8 ، 9]

    دسته 6 = ماکت 2: [10 ، 11]

مقدمه

به طور پیش فرض ، tf.distribute در انتهای کاربر ارائه شده به عنوان مثال tf.data.Dataset ، یک تغییر پیش tf.distribute اضافه می کند. آرگومان مربوط به تحول prefetch که buffer_size است برابر با تعداد ماکت ها در همگام سازی است.

tf.distribute.Strategy.experimental_distribute_datasets_from_function

طریقه استفاده

این API یک تابع ورودی را گرفته و یک نمونه tf.distribute.DistributedDataset برمی گرداند. عملکرد ورودی که کاربران از آن عبور می کنند دارای یک آرگومان tf.distribute.InputContext است و باید یک نمونه tf.data.Dataset . با استفاده از این API ، tf.distribute هیچ تغییری در نمونه tf.data.Dataset کاربر از عملکرد ورودی برگردانده است. این وظیفه کاربر است که مجموعه داده ها را مرتب و مرتب کند. tf.distribute تابع ورودی را بر روی دستگاه CPU هر یک از کارگران فراخوانی می کند. جدا از اینکه به کاربران اجازه می دهد منطق دسته بندی و سایه زنی خود را مشخص کنند ، این API مقیاس پذیری و عملکرد بهتری را در مقایسه با tf.distribute.Strategy.experimental_distribute_dataset نشان می دهد. tf.distribute.Strategy.experimental_distribute_dataset هنگام استفاده برای آموزش چند کارگر.

 mirrored_strategy = tf.distribute.MirroredStrategy()

def dataset_fn(input_context):
  batch_size = input_context.get_per_replica_batch_size(global_batch_size)
  dataset = tf.data.Dataset.from_tensors(([1.],[1.])).repeat(64).batch(16)
  dataset = dataset.shard(
    input_context.num_input_pipelines, input_context.input_pipeline_id)
  dataset = dataset.batch(batch_size)
  dataset = dataset.prefetch(2) # This prefetches 2 batches per device.
  return dataset

dist_dataset = mirrored_strategy.experimental_distribute_datasets_from_function(dataset_fn)
 
INFO:tensorflow:Using MirroredStrategy with devices ('/job:localhost/replica:0/task:0/device:GPU:0',)

خصوصیات

دسته بندی

نمونه tf.data.Dataset که مقدار برگشتی عملکرد ورودی است باید با استفاده از اندازه دسته هر ماکت دسته بندی شود. اندازه هر مجموعه ماکت اندازه گروه جهانی است که با تعداد ماکت هایی که در آموزش همگام سازی شرکت می کنند تقسیم شده است. این امر به این دلیل است که tf.distribute تابع ورودی را روی دستگاه CPU هر یک از کارگران فراخوانی می کند. مجموعه داده ای که برای یک کارگر معین ایجاد شده است باید برای استفاده از همه ماکت های مربوط به آن کارگر آماده باشد.

خرد کردن

هدف tf.distribute.InputContext که بطور ضمنی به عنوان آرگومان به عملکرد ورودی کاربر منتقل می شود توسط tf.distribute در زیر کاپوت ایجاد می شود. این اطلاعات در مورد تعداد کارگران ، شناسه فعلی کارگر و غیره است. این عملکرد ورودی می تواند مطابق با خط مشی های تعیین شده توسط کاربر با استفاده از این خصوصیات که جزئی از شیء tf.distribute.InputContext است tf.distribute.InputContext شود.

مقدمه

tf.distribute در انتهای tf.data.Dataset که توسط تابع ورودی ارائه شده توسط کاربر ارائه شده است ، یک تغییر پیش تنظیم اضافه نمی کند.

Iterators توزیع شده است

مشابه به غیر توزیع tf.data.Dataset موارد، شما نیاز به ایجاد یک تکرارکننده در tf.distribute.DistributedDataset موارد به تکرار بیش از آن و دسترسی عناصر در tf.distribute.DistributedDataset . موارد زیر روش هایی است که می توانید tf.distribute.DistributedIterator ایجاد tf.distribute.DistributedIterator و از آن برای آموزش مدل خود استفاده کنید:

موارد استفاده

برای ساخت حلقه از Pythonic استفاده کنید

برای تکرار از tf.distribute.DistributedDataset می توانید از حلقه Pythonic سازگار با کاربر استفاده کنید. عناصر برگشت یافته از tf.distribute.DistributedIterator می تواند یک tf.Tensor یا یک tf.distribute.DistributedValues که شامل یک مقدار در هر ماکت است. قرار دادن حلقه در داخل یک tf.function باعث افزایش عملکرد خواهد شد. اما اگر حلقه در داخل یک tf.function قرار گرفته باشد break و return پشتیبانی نمی شوند. ما همچنین از قرار دادن حلقه در داخل یک tf.function هنگام استفاده از استراتژی های چند کارگر مانند tf.distribute.experimental.MultiWorkerMirroredStrategy و tf.distribute.TPUStrategy . قرار دادن حلقه در داخل tf.function برای تک کارگر tf.distribute.TPUStrategy کار می tf.distribute.TPUStrategy اما هنگام استفاده از غلاف TPU کار نمی کند.

 global_batch_size = 16
mirrored_strategy = tf.distribute.MirroredStrategy()

dataset = tf.data.Dataset.from_tensors(([1.],[1.])).repeat(100).batch(global_batch_size)
dist_dataset = mirrored_strategy.experimental_distribute_dataset(dataset)

@tf.function
def train_step(inputs):
  features, labels = inputs
  return labels - 0.3 * features

for x in dist_dataset:
  # train_step trains the model using the dataset elements
  loss = mirrored_strategy.run(train_step, args=(x,))
  print("Loss is ", loss)
 
INFO:tensorflow:Using MirroredStrategy with devices ('/job:localhost/replica:0/task:0/device:GPU:0',)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(4, 1), dtype=float32)

برای ایجاد یک تکرار صریح از iter استفاده کنید

برای تکرار این عناصر در یک نمونه tf.distribute.DistributedDataset ، می توانید با استفاده از API iter روی آن ، یک tf.distribute.DistributedIterator ایجاد کنید. با یک تکرار صریح ، می توانید برای تعداد مشخصی از مراحل تکرار کنید. به منظور دریافت عنصر بعدی از tf.distribute.DistributedIterator مثال dist_iterator ، شما می توانید پاسخ next(dist_iterator) ، dist_iterator.get_next() ، و یا dist_iterator.get_next_as_optional() . دو مورد در اصل یکسان هستند:

 num_epochs = 10
steps_per_epoch = 5
for epoch in range(num_epochs):
  dist_iterator = iter(dist_dataset)
  for step in range(steps_per_epoch):
    # train_step trains the model using the dataset elements
    loss = mirrored_strategy.run(train_step, args=(next(dist_iterator),))
    # which is the same as
    # loss = mirrored_strategy.run(train_step, args=(dist_iterator.get_next(),))
    print("Loss is ", loss)
 
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)
Loss is  tf.Tensor(
[[0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]
 [0.7]], shape=(16, 1), dtype=float32)

با استفاده از next() یا tf.distribute.DistributedIterator.get_next() ، اگر tf.distribute.DistributedIterator به انتهای خود رسیده باشد ، خطای OutOfRange پرتاب خواهد شد. مشتری می تواند خطای موجود در سمت پایتون را بدست آورد و به انجام کارهای دیگر از قبیل بازرسی و ارزیابی ادامه دهد. با این وجود ، اگر از حلقه آموزش میزبان استفاده می کنید (مثلاً انجام چندین مرحله در هر tf.function ) ، به نظر می رسد:

 @tf.function
def train_fn(iterator):
  for _ in tf.range(steps_per_loop):
    strategy.run(step_fn, args=(next(iterator),))
 

train_fn شامل چندین مرحله را طی قرار دادن بدن مرحله در داخل یک tf.range . در این حالت ، تکرارهای مختلف در حلقه بدون وابستگی به موازات شروع می شود ، بنابراین می توان خطای OutOfRange را در تکرارهای بعدی ایجاد کرد تا محاسبه تکرارهای قبلی انجام شود. هنگامی که خطای OutOfRange پرتاب شد ، تمام گزینه های موجود در عملکرد بلافاصله خاتمه می یابد. اگر این موردی است که شما می خواهید از آن جلوگیری کنید ، گزینه دیگری که خطای OutOfRange را برطرف نمی کند tf.distribute.DistributedIterator.get_next_as_optional() . get_next_as_optional یک tf.experimental.Optional که حاوی عنصر بعدی یا هیچ مقداری است اگر tf.distribute.DistributedIterator به پایان رسیده باشد.

 # You can break the loop with get_next_as_optional by checking if the Optional contains value
global_batch_size = 4
steps_per_loop = 5
strategy = tf.distribute.MirroredStrategy(devices=["GPU:0", "CPU:0"])

dataset = tf.data.Dataset.range(9).batch(global_batch_size)
distributed_iterator = iter(strategy.experimental_distribute_dataset(dataset))

@tf.function
def train_fn(distributed_iterator):
  for _ in tf.range(steps_per_loop):
    optional_data = distributed_iterator.get_next_as_optional()
    if not optional_data.has_value():
      break
    per_replica_results = strategy.run(lambda x:x, args=(optional_data.get_value(),))
    tf.print(strategy.experimental_local_results(per_replica_results))
train_fn(distributed_iterator)
 
WARNING:tensorflow:There are non-GPU devices in `tf.distribute.Strategy`, not using nccl allreduce.
INFO:tensorflow:Using MirroredStrategy with devices ('/job:localhost/replica:0/task:0/device:GPU:0', '/job:localhost/replica:0/task:0/device:CPU:0')
([0 1], [2 3])
([4 5], [6 7])
([8], [])

با استفاده از خاصیت element_spec

اگر شما از عناصر یک مجموعه داده های توزیع شده به tf.function و می خواهید یک tf.TypeSpec تضمین، شما می توانید مشخص کنید input_signature استدلال از tf.function . خروجی مجموعه داده توزیع شده tf.distribute.DistributedValues که می تواند ورودی یک دستگاه واحد یا چندین دستگاه را نشان دهد. برای به دست آوردن tf.TypeSpec متناسب با این مقدار توزیع شده ، می توانید از خاصیت element_spec مجموعه داده توزیع شده یا شیء تکرار توزیع شده استفاده کنید.

 global_batch_size = 16
epochs = 5
steps_per_epoch = 5
mirrored_strategy = tf.distribute.MirroredStrategy()

dataset = tf.data.Dataset.from_tensors(([1.],[1.])).repeat(100).batch(global_batch_size)
dist_dataset = mirrored_strategy.experimental_distribute_dataset(dataset)

@tf.function(input_signature=[dist_dataset.element_spec])
def train_step(per_replica_inputs):
  def step_fn(inputs):
    return 2 * inputs
  
  return mirrored_strategy.run(step_fn, args=(per_replica_inputs,))

for _ in range(epochs):
  iterator = iter(dist_dataset)
  for _ in range(steps_per_epoch):
    output = train_step(next(iterator))
    tf.print(output)
 
INFO:tensorflow:Using MirroredStrategy with devices ('/job:localhost/replica:0/task:0/device:GPU:0',)
([[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]])
([[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]])
([[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]])
([[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]])
([[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]])
([[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]])
([[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]])
([[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]])
([[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]])
([[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]])
([[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]])
([[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]])
([[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]])
([[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]])
([[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]])
([[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]])
([[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]])
([[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]])
([[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]])
([[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]])
([[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]])
([[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]])
([[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]])
([[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]])
([[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]], [[1]
 [1]
 [1]
 ...
 [1]
 [1]
 [1]])

دسته های جزئی

دسته های جزئی وقتی اتفاق می tf.data.Dataset که موارد tf.data.Dataset که کاربران ایجاد می کنند ممکن است دارای اندازه دسته ای باشد که به طور مساوی با تعداد ماکت ها تقسیم نمی شود یا وقتی کاردینال بودن نمونه مجموعه داده قابل تقسیم نیست. این بدان معنی است که وقتی مجموعه داده روی چندین تکرار توزیع می شود ، تماس next برای برخی از تکرار کنندگان منجر به OutOfRangeError خواهد شد. برای رسیدگی به این مورد استفاده ، tf.distribute دسته های ساختگی اندازه گروه 0 را در ماکت هایی که اطلاعات بیشتری برای پردازش tf.distribute ، برمی گرداند.

در مورد مورد کارگر مجرد ، اگر داده ها توسط تماس next در iterator برگردانده نشوند ، دسته های ساختگی به اندازه 0 دسته ای ایجاد می شوند و به همراه داده های واقعی در مجموعه داده استفاده می شوند. در مورد دسته های جزئی ، آخرین دسته جهانی داده ها داده های واقعی را در کنار دسته های ساختگی داده ها قرار می دهند. شرط توقف پردازش داده ها در صورت وجود هر یک از ماکت ها داده را بررسی می کند. اگر داده ای در مورد هر یک از ماکت ها وجود نداشته باشد ، خطای OutOfRange پرتاب می شود.

برای پرونده چند کارگر ، مقدار boolean نمایانگر حضور داده در مورد هر یک از کارگران است که با استفاده از ارتباطات متقابل کپی جمع می شود و این برای شناسایی اینکه آیا تمام کارگران پردازش داده های توزیع شده را به پایان رسانده اند ، جمع می شوند. از آنجا که این مستلزم ارتباط متقابل کارگر است ، مجازات عملکردی نیز درگیر است.

هشدارها

  • کاربران هنگام استفاده از API های tf.distribute.Strategy.experimental_distribute_dataset با یک کارگر چند tf.distribute.Strategy.experimental_distribute_dataset ، کاربران یک tf.data.Dataset که از پرونده ها می خواند ، عبور می دهند. اگر tf.data.experimental.AutoShardPolicy روی AUTO یا FILE ، اندازه واقعی در هر مرحله ممکن است از اندازه دسته جهانی تعریف شده توسط کاربر کوچکتر باشد. این می تواند زمانی اتفاق بیفتد که عناصر باقیمانده در پرونده کمتر از اندازه دسته جهانی باشد. کاربران می توانند بدون توجه به تعداد مراحل اجرای برنامه یا تنظیم tf.data.experimental.AutoShardPolicy روی DATA tf.data.experimental.AutoShardPolicy را tf.data.experimental.AutoShardPolicy کنند تا در اطراف آن کار کنند.

  • دگرگونی های مجموعه داده های دولت در حال حاضر با tf.distribute پشتیبانی نمی شوند و هر گزینه گزینه ای که ممکن است مجموعه داده در حال حاضر نادیده گرفته شود ، پشتیبانی نمی شود. به عنوان مثال ، اگر مجموعه داده شما دارای یک map_fn که از tf.random.uniform برای چرخاندن یک تصویر استفاده می کند ، در این صورت باید یک نمودار داده ای داشته باشید که به دستگاه (به عنوان مثال بذر تصادفی) در دستگاه محلی که فرایند پیتون در آن اجرا می شود بستگی دارد.

  • tf.data.experimental.OptimizationOptions که به طور پیش فرض غیرفعال شده اند می توانند در برخی زمینه ها - مانند زمانی که همراه با tf.distribute استفاده می شوند - باعث کاهش عملکرد شوند. شما باید فقط پس از تأیید اعتبار آنها از عملکرد بار کاری شما در یک توزیع توزیع ، آنها را فعال کنید.

  • ترتیب پردازش داده ها توسط کارگران هنگام استفاده از tf.distribute.experimental_distribute_dataset یا tf.distribute.experimental_distribute_datasets_from_function تضمین نمی شود. این معمولاً در صورت استفاده از tf.distribute برای پیش بینی مقیاس مورد نیاز است. با این وجود می توانید برای هر عنصر یک فهرست در دسته بندی قرار دهید و بر این اساس خروجی ها را ترتیب دهید. قطعه زیر نمونه ای از نحوه سفارش خروجی ها است.

 mirrored_strategy = tf.distribute.MirroredStrategy()
dataset_size = 24
batch_size = 6
dataset = tf.data.Dataset.range(dataset_size).enumerate().batch(batch_size)
dist_dataset = mirrored_strategy.experimental_distribute_dataset(dataset)

def predict(index, inputs):
  outputs = 2 * inputs
  return index, outputs

result = {}
for index, inputs in dist_dataset:
  output_index, outputs = mirrored_strategy.run(predict, args=(index, inputs))
  indices = list(mirrored_strategy.experimental_local_results(output_index))
  rindices = []
  for a in indices:
    rindices.extend(a.numpy())
  outputs = list(mirrored_strategy.experimental_local_results(outputs))
  routputs = []
  for a in outputs:
    routputs.extend(a.numpy())
  for i, value in zip(rindices, routputs):
    result[i] = value

print(result)
 
INFO:tensorflow:Using MirroredStrategy with devices ('/job:localhost/replica:0/task:0/device:GPU:0',)
WARNING:tensorflow:Using MirroredStrategy eagerly has significant overhead currently. We will be working on improving this in the future, but for now please wrap `call_for_each_replica` or `experimental_run` or `experimental_run_v2` inside a tf.function to get the best performance.
WARNING:tensorflow:Using MirroredStrategy eagerly has significant overhead currently. We will be working on improving this in the future, but for now please wrap `call_for_each_replica` or `experimental_run` or `experimental_run_v2` inside a tf.function to get the best performance.
WARNING:tensorflow:Using MirroredStrategy eagerly has significant overhead currently. We will be working on improving this in the future, but for now please wrap `call_for_each_replica` or `experimental_run` or `experimental_run_v2` inside a tf.function to get the best performance.
WARNING:tensorflow:Using MirroredStrategy eagerly has significant overhead currently. We will be working on improving this in the future, but for now please wrap `call_for_each_replica` or `experimental_run` or `experimental_run_v2` inside a tf.function to get the best performance.
{0: 0, 1: 2, 2: 4, 3: 6, 4: 8, 5: 10, 6: 12, 7: 14, 8: 16, 9: 18, 10: 20, 11: 22, 12: 24, 13: 26, 14: 28, 15: 30, 16: 32, 17: 34, 18: 36, 19: 38, 20: 40, 21: 42, 22: 44, 23: 46}

در صورت عدم استفاده از نمونه معمولی tf.data.Dataset چگونه می توانم داده های خود را توزیع کنم؟

بعضی اوقات کاربران نمی توانند از tf.data.Dataset برای نشان دادن ورودی خود و متعاقباً API های فوق الذکر برای توزیع داده در چندین دستگاه استفاده کنند. در چنین مواقعی می توانید از یک تانکر خام یا ورودی از یک ژنراتور استفاده کنید.

از ورودی های تجربی_distribute_values_from_funks برای ورودی های تانسور دلخواه استفاده کنید

strategy.run tf.distribute.DistributedValues را قبول می کند که خروجی next(iterator) . برای عبور از مقادیر تنسور ، برای ساخت tf.distribute.DistributedValues از tf.distribute.DistributedValues خام ، از experimental_distribute_values_from_function استفاده کنید.

 mirrored_strategy = tf.distribute.MirroredStrategy()
worker_devices = mirrored_strategy.extended.worker_devices

def value_fn(ctx):
  return tf.constant(1.0)

distributed_values = mirrored_strategy.experimental_distribute_values_from_function(value_fn)
for _ in range(4):
  result = mirrored_strategy.run(lambda x:x, args=(distributed_values,))
  print(result)
 
INFO:tensorflow:Using MirroredStrategy with devices ('/job:localhost/replica:0/task:0/device:GPU:0',)
WARNING:tensorflow:Using MirroredStrategy eagerly has significant overhead currently. We will be working on improving this in the future, but for now please wrap `call_for_each_replica` or `experimental_run` or `experimental_run_v2` inside a tf.function to get the best performance.
tf.Tensor(1.0, shape=(), dtype=float32)
tf.Tensor(1.0, shape=(), dtype=float32)
tf.Tensor(1.0, shape=(), dtype=float32)
tf.Tensor(1.0, shape=(), dtype=float32)

اگر ورودی شما از یک ژنراتور است از tf.data.Dataset.from_generator استفاده کنید

اگر یک تابع ژنراتور را دارید که می خواهید از آن استفاده کنید ، می توانید با استفاده از API from_generator یک نمونه tf.data.Dataset ایجاد کنید.

 mirrored_strategy = tf.distribute.MirroredStrategy()
def input_gen():
  while True:
    yield np.random.rand(4)

# use Dataset.from_generator
dataset = tf.data.Dataset.from_generator(
    input_gen, output_types=(tf.float32), output_shapes=tf.TensorShape([4]))
dist_dataset = mirrored_strategy.experimental_distribute_dataset(dataset)
iterator = iter(dist_dataset)
for _ in range(4):
  mirrored_strategy.run(lambda x:x, args=(next(iterator),))
 
INFO:tensorflow:Using MirroredStrategy with devices ('/job:localhost/replica:0/task:0/device:GPU:0',)