Spec-Zone.ru › TensorFlow 1.15

tf.contrib.distribute.MirroredStrategy

Зеркалирует переменные для распределения по нескольким устройствам и машинам.

Наследуется от: Strategy

tf.contrib.distribute.MirroredStrategy(
    devices=None, num_gpus=None, num_gpus_per_worker=None, cross_device_ops=None,
    auto_shard_dataset=False, cross_tower_ops=None
)

*** версия contrib ***

Эта стратегия использует по одной реплике на устройство и синхронную репликацию для своей версии с несколькими GPU.

Когда cluster_spec предоставляется методом configure, она превращается в многоузловую версию, работающую на нескольких узлах с репликацией в графе. Примечание: configure будет вызываться API более высокого уровня, если выполнение происходит в распределенной среде.

Существует несколько важных понятий для распределенного TensorFlow, например, client, job, task, cluster, in-graph replication и synchronous training, и они уже определены в документации TensorFlow TensorFlow's documentation. Стратегия распределения также наследует эти понятия, а также уточняет несколько дополнительных:

  • Репликация в графе: client создает один tf.Graph, который определяет задачи для устройств на всех узлах. Затем client создаёт клиентскую сессию, которая будет взаимодействовать с сервисом master на worker. Затем master разделит граф и распределит работу по всем участвующим узлам.
  • Узел: Узел — это TensorFlow task, который обычно соответствует одной физической машине. У нас будет несколько worker с разными task индексами. Все они выполняют аналогичные задачи, за исключением того, что один узел выполняет резервное копирование переменных модели, запись сводок и т. д. в дополнение к обычной работе.

Многоузловая версия этого класса сопоставляет одну реплику с одним устройством на узле. Она зеркалирует все переменные модели на всех репликах. Например, если у вас два worker и на каждом worker по 4 GPU, она создаст 8 копий переменных модели на этих 8 GPU. Затем, как и в MirroredStrategy, каждая реплика выполняет свои вычисления со своей копией переменных, за исключением случаев кросс-репликационной модели, где происходит уменьшение переменных или тензоров.

Аргументы
devices список строк устройств.
num_gpus количество GPU. Для локального обучения необходимо указать либо devices, либо num_gpus. При распределенном обучении это количество GPU на каждом узле.
num_gpus_per_worker количество GPU на узел. Это то же, что и num_gpus, и только один из num_gpus и num_gpus_per_worker может быть указан.
cross_device_ops необязательно, потомок CrossDeviceOps. Если это не установлено, метод configure попытается найти лучший.
auto_shard_dataset нужно ли автоматически фрагментировать набор данных при наличии нескольких узлов.
cross_tower_ops устаревшее псевдоним для cross_device_ops.
Атрибуты
extended tf.distribute.StrategyExtended с дополнительными методами.
num_replicas_in_sync Возвращает количество реплик, по которым агрегируются градиенты.

Методы

experimental_distribute_dataset

Просмотреть исходный код

experimental_distribute_dataset(
    dataset
)

Распределяет экземпляр tf.data.Dataset, предоставленный через dataset.

Возвращаемый распределённый набор данных можно перебирать аналогично тому, как это делается с обычными наборами данных. ПРИМЕЧАНИЕ: В настоящее время пользователь не может добавлять дополнительные преобразования к распределённому набору данных.

Вот пример:

strategy = tf.distribute.MirroredStrategy()

# Create a dataset
dataset = dataset_ops.Dataset.TFRecordDataset([
  "/a/1.tfr", "/a/2.tfr", "/a/3.tfr", "/a/4.tfr"])

# Distribute that dataset
dist_dataset = strategy.experimental_distribute_dataset(dataset)
# Iterate over the distributed dataset
for x in dist_dataset:
  # process dataset elements
  strategy.experimental_run_v2(train_step, args=(x,))

Предположим, что входной набор данных сгруппирован по глобальному размеру пакета. При этом мы сделаем всё возможное, чтобы разделить каждый пакет между всеми репликами (один или несколько узлов).

В многоузловой среде мы сначала попытаемся распределить набор данных, попытавшись определить, создается ли он из ReaderDatasets (например, TFRecordDataset, TextLineDataset и т. д.), и, если да, попытаемся разделить входные файлы. Обратите внимание, что на каждом узле должен быть как минимум один входной файл. Если у вас меньше одного входного файла на узел, мы рекомендуем отключить распределение набора данных с помощью метода ниже.

Если эта попытка не удалась (например, набор данных создан из Dataset.range), мы разделим набор данных равномерно в конце, добавив операцию .shard в конец цепочки обработки. Это приведёт к тому, что вся цепочка предобработки всех данных будет запущена на каждом узле, и каждый узел будет выполнять избыточную работу. Мы выведем предупреждение, если этот метод фрагментации будет выбран. В этом случае рассмотрите использование experimental_distribute_datasets_from_function вместо этого.

Вы можете отключить фрагментацию набора данных между узлами, используя опцию auto_shard в tf.data.experimental.DistributeOptions.

Внутри каждого узла мы также разделим данные между всеми устройствами узла (если их несколько), и это произойдёт даже в том случае, если многоузловая фрагментация отключена с помощью вышеупомянутого метода.

Если вышеупомянутая логика разделения пакета и фрагментации набора данных нежелательна, используйте experimental_distribute_datasets_from_function вместо этого, который не выполняет автоматическое разделение или фрагментацию.

Аргументы
dataset tf.data.Dataset, который будет разделен между всеми репликами по вышеуказанным правилам.
Возвращает
«распределенный Dataset», который работает как tf.data.Dataset, за исключением того, что он генерирует значения «по реплике».

experimental_distribute_datasets_from_function

Просмотреть исходный код

experimental_distribute_datasets_from_function(
    dataset_fn
)

Распределяет экземпляры tf.data.Dataset, созданные вызовами dataset_fn.

dataset_fn будет вызываться один раз для каждого узла в стратегии. Каждая реплика на этом узле будет извлекать одну порцию входных данных из локального Dataset (то есть, если на узле две реплики, на каждом шаге из Dataset будет извлечено две порции).

Этот метод может быть использован для различных целей. Например, когда experimental_distribute_dataset не может разбить входные файлы, этот метод может быть использован для ручного разбиения набора данных (избегая медленной отложенной обработки в experimental_distribute_dataset). В случаях, когда набор данных бесконечный, это разбиение можно выполнить, создав копии набора данных, отличающиеся только случайным начальным значением. experimental_distribute_dataset также иногда может не удаться разделить пакет между репликами на узле. В этом случае этот метод может быть использован, где такого ограничения нет.

dataset_fn должен принимать экземпляр tf.distribute.InputContext, где можно получить информацию о пакетной обработке и репликации ввода:

def dataset_fn(input_context):
  batch_size = input_context.get_per_replica_batch_size(global_batch_size)
  d = tf.data.Dataset.from_tensors([[1.]]).repeat().batch(batch_size)
  return d.shard(
      input_context.num_input_pipelines, input_context.input_pipeline_id)

inputs = strategy.experimental_distribute_datasets_from_function(dataset_fn)

for batch in inputs:
  replica_results = strategy.experimental_run_v2(replica_fn, args=(batch,))
Ключевой момент: tf.data.Dataset, возвращаемый dataset_fn, должен иметь размер пакета по реплике, в отличие от experimental_distribute_dataset, который использует глобальный размер пакета. Это может быть вычислено с помощью input_context.get_per_replica_batch_size.
Аргументы
dataset_fn функция, принимающая экземпляр tf.distribute.InputContext и возвращающая tf.data.Dataset.
Возвращает
«распределенный Dataset», который работает как tf.data.Dataset, за исключением того, что он генерирует значения «по реплике».

experimental_local_results

Просмотреть исходный код

experimental_local_results(
    value
)

Возвращает список всех локальных значений по реплике, содержащихся в value.

Примечание: Это возвращает только значения на узле, инициированном этим клиентом. При использовании tf.distribute.Strategy, такого как tf.distribute.experimental.MultiWorkerMirroredStrategy, каждый узел будет своим клиентом, и эта функция вернёт только значения, вычисленные на этом узле.
Аргументы
value Значение, возвращаемое experimental_run(), experimental_run_v2(), extended.call_for_each_replica(), или переменная, созданная в scope.
Возвращает
Кортеж значений, содержащихся в value. Если value представляет единственное значение, возвращается (value,).

experimental_make_numpy_dataset

Просмотреть исходный код

experimental_make_numpy_dataset(
    numpy_input, session=None
)

Создаёт tf.data.Dataset для входных данных, предоставленных в виде массива NumPy.

Это позволяет избежать добавления numpy_input в виде большой константы в граф и копирует данные на машину или машины, которые будут обрабатывать вход.

Обратите внимание, что вам, вероятно, потребуется использовать tf.distribute.Strategy.experimental_distribute_dataset с возвращённым набором данных, чтобы дополнительно распределить его с помощью стратегии.

Пример:

numpy_input = np.ones([10], dtype=np.float32)
dataset = strategy.experimental_make_numpy_dataset(numpy_input)
dist_dataset = strategy.experimental_distribute_dataset(dataset)
Аргументы
numpy_input Вложенный набор массивов NumPy, которые будут преобразованы в набор данных. Обратите внимание, что списки массивов NumPy складываются, так как это обычное tf.data.Dataset поведение.
session (Только для выполнения графа TensorFlow v1.x) Сессия, используемая для инициализации.
Возвращаемое значение
Объект tf.data.Dataset, представляющий numpy_input.

experimental_run

Просмотреть исходный код

experimental_run(
    fn, input_iterator=None
)

Выполняет операции в fn на каждой реплике с входными данными из input_iterator.

УСТЕРЕЖЕННЫЙ метод: Этот метод недоступен в TF 2.x. Пожалуйста, переключитесь на использование experimental_run_v2 вместо этого.

При включённом режиме выполнения Eager выполняет операции, указанные в fn на каждой реплике. В противном случае создаёт граф для выполнения операций на каждой реплике.

Каждая реплика получит один отдельный вход из входов, предоставленных одним вызовом get_next для итератора ввода.

fn может вызвать tf.distribute.get_replica_context() для доступа к членам, таким как replica_id_in_sync_group.

Ключевая информация: В зависимости от используемой реализации tf.distribute.Strategy и включенного режима Eager, fn может быть вызван один или несколько раз (по одному разу для каждой реплики).
Аргументы
fn Функция для выполнения. Входы в функцию должны соответствовать выходам input_iterator.get_next(). Выход должен быть tf.nest из Tensors.
input_iterator (Необязательно) итератор ввода, из которого берутся входы.
Возвращаемое значение
Объединённое возвращаемое значение fn по всем репликам. Структура возвращаемого значения такая же, как и возвращаемое значение из fn. Каждый элемент структуры может быть PerReplica (если значения не синхронизированы), Mirrored (если значения синхронизированы) или Tensor (если выполняется на одной реплике).

experimental_run_v2

Просмотреть исходный код

experimental_run_v2(
    fn, args=(), kwargs=None
)

Выполняет fn на каждой реплике с заданными аргументами.

Выполняет операции, указанные в fn на каждой реплике. Если args или kwargs имеют значения «по реплике», такие как те, которые производятся «распределённым Dataset», при выполнении fn на конкретной реплике, оно будет выполнено с частью этих значений «по реплике», соответствующей этой реплике.

fn может вызвать tf.distribute.get_replica_context() для доступа к членам, таким как all_reduce.

Все аргументы в args или kwargs должны быть либо вложенными тензорами, либо объектами «по реплике», содержащими тензоры или составные тензоры.

Ключевая информация: В зависимости от реализации tf.distribute.Strategy и включенного режима Eager, fn может быть вызван один или несколько раз (по одному разу для каждой реплики).
Аргументы
fn Функция для выполнения. Выход должен быть tf.nest из Tensors.
args (Необязательно) позиционные аргументы для fn.
kwargs (Необязательно) именованные аргументы для fn.
Возвращаемое значение
Объединённое возвращаемое значение fn по всем репликам. Структура возвращаемого значения такая же, как и возвращаемое значение из fn. Каждый элемент структуры может быть объектами «по реплике» Tensor или Tensors (например, при выполнении на одной реплике).

make_dataset_iterator

Просмотреть исходный код

make_dataset_iterator(
    dataset
)

Создаёт итератор для ввода, предоставленного через dataset.

Примечание: Размер пакета аргумента dataset обрабатывается по-другому для этой версии MirroredStrategy из пакета contrib.

Данные из заданного набора данных будут распределены равномерно по всем вычислительным репликам. Мы предположим, что входной набор данных сгруппирован по размеру пакета на реплику.

Пользователь также может использовать make_input_fn_iterator , если они хотят настроить, какой вход подаётся на какую реплику/узел и т.д.

Аргументы
dataset tf.data.Dataset, который будет распределён равномерно по всем репликам.
Возвращаемое значение
Объект итератора tf.distribute.InputIterator, который возвращает входы для каждого шага вычисления. Пользователь должен вызвать initialize на возвращенном итераторе.

make_input_fn_iterator

Просмотреть исходный код

make_input_fn_iterator(
    input_fn, replication_mode=tf.distribute.InputReplicationMode.PER_WORKER
)

Возвращает итератор, разделённый по репликам, созданный из функции ввода.

УСТЕРЕЖЕННЫЙ метод: Этот метод недоступен в TF 2.x.

Функция input_fn должна принимать объект tf.distribute.InputContext, где можно получить информацию о группировании и разделении ввода:

def input_fn(input_context):
  batch_size = input_context.get_per_replica_batch_size(global_batch_size)
  d = tf.data.Dataset.from_tensors([[1.]]).repeat().batch(batch_size)
  return d.shard(input_context.num_input_pipelines,
                 input_context.input_pipeline_id)
with strategy.scope():
  iterator = strategy.make_input_fn_iterator(input_fn)
  replica_results = strategy.experimental_run(replica_fn, iterator)

Возвращаемый tf.data.Dataset объектом input_fn должен иметь размер пакета по реплике, который можно вычислить, используя input_context.get_per_replica_batch_size.

Аргументы
input_fn Функция, принимающая объект tf.distribute.InputContext и возвращающая tf.data.Dataset.
replication_mode Значение перечисления tf.distribute.InputReplicationMode. В настоящее время поддерживается только PER_WORKER , что означает, что вызов input_fn будет выполнен один раз на каждом узле. Реплики будут извлекать элементы из локального tf.data.Dataset на своём узле.
Возвращаемое значение
Объект итератора, который вначале нужно вызвать методом .initialize(). Затем его можно передать в strategy.experimental_run() или вызвать iterator.get_next() для получения следующего значения, которое нужно передать в strategy.extended.call_for_each_replica().

reduce

Просмотреть исходный код

reduce(
    reduce_op, value, axis=None
)

Свести value по всем репликам.

Учитывая значение по реплике, возвращаемое experimental_run_v2, например, потерю на пример, пакет будет разделён по всем репликам. Эта функция позволяет агрегировать по репликам, а также, необязательно, по элементам пакета. Например, если у вас есть общий размер пакета 8 и 2 реплики, значения для примеров [0, 1, 2, 3] будут на реплике 0, а [4, 5, 6, 7] будут на реплике 1. По умолчанию reduce просто агрегирует по репликам, возвращая [0+4, 1+5, 2+6, 3+7]. Это полезно, когда каждая реплика вычисляет скаляр или какое-либо другое значение без «размерности пакета» (например, градиент). Чаще всего вам нужно будет агрегировать по глобальному пакету, что можно сделать, указав размерность пакета как axis, обычно axis=0. В этом случае будет возвращён скаляр 0+1+2+3+4+5+6+7.

Если есть последний частичный пакет, вам необходимо указать ось, чтобы размерность результата была согласована по репликам. Таким образом, если последний пакет имеет размер 6 и разделен на [0, 1, 2, 3] и [4, 5], у вас возникнет несоответствие размеров, если вы не укажете axis=0. Если вы укажете tf.distribute.ReduceOp.MEAN, используя axis=0 будет использован правильный знаменатель 6. В отличие от вычисления reduce_mean для получения скалярного значения на каждой реплике и этой функции для усреднения этих средних значений, которая будет учитывать одни значения 1/8 и другие 1/4.

Аргументы
reduce_op Значение tf.distribute.ReduceOp, определяющее, как следует комбинировать значения.
value Значение "на копию", например, возвращаемое experimental_run_v2 для объединения в один тензор.
axis Указывает размерность для сокращения внутри тензора каждой копии. Обычно следует задавать размерность пакета или None для сокращения только по копиям (например, если тензор не имеет размерности пакета).
Возвращаемое значение
Tensor.

scope

Просмотреть исходный код

scope()

Возвращает менеджер контекста, выбирающий эту стратегию в качестве текущей.

Внутри блока кода with strategy.scope():, эта нить будет использовать создатель переменных, заданный strategy, и войдёт в свой "меж-копийный контекст".

Возвращаемое значение
Менеджер контекста.

update_config_proto

Просмотреть исходный код

update_config_proto(
    config_proto
)

Возвращает копию config_proto, модифицированную для использования с данной стратегией.

УСТАРЕЛО: Этот метод недоступен в TF 2.x.

Обновлённая конфигурация содержит необходимые данные для работы стратегии, например, конфигурацию для запуска коллективных операций или фильтры устройств для повышения производительности распределённого обучения.

Аргументы
config_proto Объект tf.ConfigProto.
Возвращаемое значение
Обновлённая копия config_proto.

© 2020 The TensorFlow Authors. All rights reserved.
Licensed under the Creative Commons Attribution License 3.0.
Code samples licensed under the Apache 2.0 License.
https://www.tensorflow.org/versions/r1.15/api_docs/python/tf/contrib/distribute/MirroredStrategy

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API