tf.compat.v1.distribute.StrategyExtended
Дополнительные API для алгоритмов, которым необходимо учитывать распределение.
Наследуется от: StrategyExtended
tf.compat.v1.distribute.StrategyExtended(
container_strategy
)
Примечание: В большинстве случаев использования tf.distribute.Strategy вызывать эти методы не требуется, поскольку библиотеки TensorFlow (например, оптимизаторы) при необходимости вызывают их за вас.
Некоторые распространённые сценарии использования функций на этой странице:
- Локальность
tf.distribute.DistributedValues может иметь ту же локальность, что и распределённая переменная, благодаря чему зеркальное значение размещается на тех же устройствах, что и переменная (а не на вычислительных устройствах). Такие значения можно передать в вызов tf.distribute.StrategyExtended.update для обновления значения переменной. Чтобы задать переменной ту же локальность, что и у другой переменной, можно использовать tf.distribute.StrategyExtended.colocate_vars_with. Преобразовать значение «PerReplica» к локальности переменной можно с помощью tf.distribute.StrategyExtended.reduce_to или tf.distribute.StrategyExtended.batch_reduce_to.
- Обновление распределённой переменной
Распределённая переменная — это переменная, созданная на нескольких устройствах. Как описано в глоссарии, зеркальная переменная и переменная SyncOnRead — два примера таких переменных. Стандартный порядок обновления распределённых переменных:
- В функции, переданной в
tf.distribute.Strategy.run, вычислите список пар (обновление, переменная). Например, обновлением может быть градиент функции потерь относительно переменной. - Перейдите в режим между репликами, вызвав
tf.distribute.get_replica_context().merge_call()и передав обновления и переменные в качестве аргументов. - Вызовите
tf.distribute.StrategyExtended.reduce_to(VariableAggregation.SUM, t, v)(для одной переменной) илиtf.distribute.StrategyExtended.batch_reduce_to(для списка переменных), чтобы суммировать обновления. - Вызовите
tf.distribute.StrategyExtended.update(v)для каждой переменной, чтобы обновить её значение.
Шаги 2–4 автоматически выполняются классом tf.keras.optimizers.Optimizer, если вызвать его метод tf.keras.optimizers.Optimizer.apply_gradients в контексте реплики.
На самом деле, для обновления распределённой переменной можно воспользоваться решением более высокого уровня: вызвать assign для переменной, как для обычной tf.Variable. Этот метод можно вызывать как в контексте реплики, так и в контексте между репликами. Для зеркальной переменной вызов assign в контексте реплики требует указать тип aggregation в конструкторе переменной. В этом случае переключение контекста и синхронизация, описанные в шагах 2–4, выполняются автоматически. Если вызвать assign для зеркальной переменной в контексте между репликами, можно присвоить только одно значение либо значения из другой зеркальной переменной или зеркального объекта tf.distribute.DistributedValues. Для переменной SyncOnRead в контексте реплики достаточно вызвать для неё assign; при этом агрегирование не выполняется автоматически. В контексте между репликами переменной SyncOnRead можно присвоить только одно значение. Например, при восстановлении из контрольной точки: если тип aggregation переменной — tf.VariableAggregation.SUM, предполагается, что значения реплик были сложены перед созданием контрольной точки. Поэтому при восстановлении значение делится на число реплик, а затем присваивается каждой реплике; если тип aggregation — tf.VariableAggregation.MEAN, значение напрямую присваивается каждой реплике.
| Атрибуты | |
|---|---|
experimental_between_graph | Использует ли стратегия репликацию между графами. Ожидается, что возвращается постоянное значение, которое не меняется в течение всего жизненного цикла. |
experimental_require_static_shapes | Возвращает True, если требуется статическая форма; в противном случае — False. |
experimental_should_init | Требуется ли инициализация. |
parameter_devices | Возвращает кортеж всех устройств, используемых для размещения переменных. |
should_checkpoint | Требуется ли создание контрольных точек. |
should_save_summary | Требуется ли сохранение сводок. |
worker_devices | Возвращает кортеж всех устройств, используемых для выполнения вычислений на репликах. |
Методы
batch_reduce_to
batch_reduce_to(
reduce_op, value_destination_pairs, options=None
)
Объединяет несколько вызовов reduce_to в один для более быстрого выполнения.
Аналогично reduce_to, но принимает список пар (значение, назначения). Это эффективнее, чем отдельно сводить каждое значение.
В настоящее время этот API можно вызывать только в контексте между репликами. Для сведения значений между репликами предусмотрены следующие альтернативные варианты:
-
tf.distribute.StrategyExtended.reduce_to: версия этого API без пакетной обработки. -
tf.distribute.ReplicaContext.all_reduce: аналог этого API в контексте реплики. Поддерживает как пакетное, так и непакетное выполнение операции all-reduce. -
tf.distribute.Strategy.reduce: более удобный метод для редукции на хосте в межрепличном контексте.
Дополнительную информацию см. в reduce_to.
@tf.function def step_fn(var):
def merge_fn(strategy, value, var): # All-reduce the value. Note that value here is a # tf.distribute.DistributedValues. reduced = strategy.extended.batch_reduce_to( tf.distribute.ReduceOp.SUM, [(value, var)])[0] strategy.extended.update(var, lambda var, value: var.assign(value), args=(reduced,))
value = tf.identity(1.) tf.distribute.get_replica_context().merge_call(merge_fn, args=(value, var))
def run(strategy): with strategy.scope(): v = tf.Variable(0.) strategy.run(step_fn, args=(v,)) return v
run(tf.distribute.MirroredStrategy(["GPU:0", "GPU:1"])) MirroredVariable:{ 0:
| Аргументы | |
|---|---|
reduce_op | значение tf.distribute.ReduceOp, определяющее способ объединения значений. Допускается строковое представление перечисления, например "SUM" или "MEAN". |
value_destination_pairs | последовательность пар (значение, целевые объекты). Описание см. в tf.distribute.Strategy.reduce_to. |
options | объект tf.distribute.experimental.CommunicationOptions. Параметры для выполнения коллективных операций. Они переопределяют параметры по умолчанию, если tf.distribute.Strategy принимает их в конструкторе. Подробнее о параметрах см. в разделе tf.distribute.experimental.CommunicationOptions. |
| Возвращает | |
|---|---|
Список редуцированных значений — по одному для каждой пары в value_destination_pairs. |
broadcast_to
broadcast_to(
tensor, destinations
)
Копирует тензор с одного устройства на все устройства рабочих узлов.
| Аргументы | |
|---|---|
tensor | Значение Tensor для широковещательной рассылки. |
destinations | Зеркальная переменная или строка с именем устройства, определяющая целевые устройства, на которые следует скопировать tensor. |
| Возвращает | |
|---|---|
Значение, зеркально отображённое на устройствах destinations. |
call_for_each_replica
call_for_each_replica(
fn, args=(), kwargs=None
)
Запускает fn один раз для каждой реплики.
fn может вызывать tf.get_replica_context() для доступа к таким методам, как replica_id_in_sync_group и merge_call().
merge_call() используется для обмена данными между репликами и возвращения в межрепличный контекст. Все реплики приостанавливают выполнение, встретив вызов merge_call(). Затем выполняется функция merge_fn. Её результаты распаковываются и возвращаются в вызов каждой реплики. После этого выполнение продолжается, пока fn не завершится или не встретит ещё один вызов merge_call(). Пример:
# Called once in "cross-replica" context. def merge_fn(distribution, three_plus_replica_id): # sum the values across replicas return sum(distribution.experimental_local_results(three_plus_replica_id)) # Called once per replica in `distribution`, in a "replica" context. def fn(three): replica_ctx = tf.get_replica_context() v = three + replica_ctx.replica_id_in_sync_group # Computes the sum of the `v` values across all replicas. s = replica_ctx.merge_call(merge_fn, args=(v,)) return s + v with distribution.scope(): # in "cross-replica" context ... merged_results = distribution.run(fn, args=[3]) # merged_results has the values from every replica execution of `fn`. # This statement prints a list: print(distribution.experimental_local_results(merged_results))
| Аргументы | |
|---|---|
fn | Функция для запуска (будет запущена один раз для каждой реплики). |
args | Кортеж или список позиционных аргументов для fn. |
kwargs | Словарь именованных аргументов для fn. |
| Возвращает | |
|---|---|
Объединённое возвращаемое значение fn для всех реплик. |
colocate_vars_with
colocate_vars_with(
colocate_with_variable
)
Область видимости, определяющая, на каких устройствах будут создаваться переменные.
Внутри этой области видимости не следует добавлять операции в граф; её нужно использовать только при создании переменных (некоторые реализации изменяют процесс создания переменных, другие используют область видимости tf.compat.v1.colocate_with()).
Её можно использовать только внутри self.scope().
Пример использования:
with strategy.scope():
var1 = tf.Variable(...)
with strategy.extended.colocate_vars_with(var1):
# var2 and var3 will be created on the same device(s) as var1
var2 = tf.Variable(...)
var3 = tf.Variable(...)
def fn(v1, v2, v3):
# operates on v1 from var1, v2 from var2, and v3 from var3
# `fn` runs on every device `var1` is on, `var2` and `var3` will be there
# too.
strategy.extended.update(var1, fn, args=(var2, var3))
| Аргументы | |
|---|---|
colocate_with_variable | Переменная, созданная в scope() этой стратегии. Переменные, созданные в возвращаемом менеджере контекста, будут размещены на том же наборе устройств, что и colocate_with_variable. |
| Возвращает | |
|---|---|
| Менеджер контекста. |
experimental_make_numpy_dataset
experimental_make_numpy_dataset(
numpy_input, session=None
)
Создаёт набор данных для входных данных, переданных в виде массива NumPy.
Это позволяет не добавлять numpy_input в граф в качестве большой константы и копирует данные на компьютер или компьютеры, которые будут обрабатывать входные данные.
| Аргументы | |
|---|---|
numpy_input | Вложенный набор входных массивов NumPy, который будет равномерно распределен между всеми репликами. Обратите внимание: списки массивов NumPy объединяются в тензоры, что является стандартным поведением tf.data.Dataset. |
session | (Только для выполнения графов TensorFlow v1.x) Сеанс, используемый для инициализации. |
| Возвращает | |
|---|---|
Объект tf.data.Dataset, представляющий numpy_input. |
experimental_run_steps_on_iterator
experimental_run_steps_on_iterator(
fn, iterator, iterations=1, initial_loop_values=None
)
Выполняет fn с входными данными из iterator в течение iterations итераций.
Этот метод можно использовать для многократного выполнения функции шага обучения с использованием входных данных из набора данных.
| Аргументы | |
|---|---|
fn | функция, выполняемая с использованием этой стратегии распределения. Функция должна иметь следующую сигнатуру: def fn(context, inputs). context — это экземпляр MultiStepContext, который будет передан при выполнении fn. context можно использовать, чтобы указать выходные данные, возвращаемые из fn, вызвав context.set_last_step_output. Его также можно использовать для сохранения выходных данных, не являющихся тензорами, с помощью context.set_non_tensor_output. Дополнительные сведения см. в документации MultiStepContext. inputs будет иметь тот же тип и структуру, что и iterator.get_next(). Как правило, fn использует метод call_for_each_replica стратегии для распределения вычислений между несколькими репликами. |
iterator | Итератор набора данных, представляющего входные данные для fn. Вызывающая сторона отвечает за инициализацию итератора по мере необходимости. |
iterations | (Необязательно) Количество итераций, в течение которых должно выполняться fn. По умолчанию — 1. |
initial_loop_values | (Необязательно) Начальные значения, передаваемые в цикл, выполняющий fn. По умолчанию — None. аргумент initial_loop_values, когда у нас будет механизм для определения выходных данных fn. |
| Возвращает | |
|---|---|
Возвращает объект MultiStepContext, обладающий, помимо прочего, следующими свойствами:
|
non_slot_devices
non_slot_devices(
var_list
)
Устройство или устройства для переменных без слотов.
Этот метод возвращает устройства без слотов, на которых размещаются переменные без слотов. Пользователи могут создавать переменные без слотов на этих устройствах, используя блок:
with tf.distribute.StrategyExtended.colocate_vars_with(tf.distribute.StrategyExtended.non_slot_devices(...)): ...
| Аргументы | |
|---|---|
var_list | Список оптимизируемых переменных, необходимый при использовании стратегии по умолчанию tf.distribute.Strategy. |
| Возвращает | |
|---|---|
| Последовательность устройств для переменных без слотов. |
read_var
read_var(
v
)
Считывает значение переменной.
Возвращает агрегированное значение локальной для реплики переменной или значение любой другой переменной (только для чтения).
| Аргументы | |
|---|---|
v | Переменная, выделенная в области действия этой стратегии tf.distribute.Strategy. |
| Возвращает | |
|---|---|
Тензор, представляющий значение v, агрегированное по репликам, если это необходимо. |
reduce_to
reduce_to(
reduce_op, value, destinations, options=None
)
Объединяет значения по репликам (например, с помощью суммирования или вычисления среднего).
reduce_to агрегирует tf.distribute.DistributedValues и распределенные переменные. Поддерживаются как плотные значения, так и tf.IndexedSlices.
В настоящее время этот API можно вызывать только в контексте между репликами. Другие варианты агрегирования значений по репликам:
-
tf.distribute.StrategyExtended.batch_reduce_to: пакетная версия этого API. -
tf.distribute.ReplicaContext.all_reduce: аналог этого API в контексте реплики. Поддерживает пакетное и непакетное агрегирование всех значений. -
tf.distribute.Strategy.reduce: более удобный метод агрегирования на главном устройстве в контексте между репликами.
destinations задает, куда следует агрегировать значение, например "GPU:0". Можно также передать Tensor; в этом случае целевым устройством будет устройство этого тензора. Для агрегирования всех значений передайте одинаковые значения в value и destinations.
Его можно использовать в tf.distribute.ReplicaContext.merge_call, чтобы написать код, работающий для всех tf.distribute.Strategy.
@tf.function def step_fn(var):
def merge_fn(strategy, value, var): # All-reduce the value. Note that value here is a # tf.distribute.DistributedValues. reduced = strategy.extended.reduce_to(tf.distribute.ReduceOp.SUM, value, destinations=var) strategy.extended.update(var, lambda var, value: var.assign(value), args=(reduced,))
value = tf.identity(1.) tf.distribute.get_replica_context().merge_call(merge_fn, args=(value, var))
def run(strategy): with strategy.scope(): v = tf.Variable(0.) strategy.run(step_fn, args=(v,)) return v
run(tf.distribute.MirroredStrategy(["GPU:0", "GPU:1"])) MirroredVariable:{ 0:
| Аргументы | |
|---|---|
reduce_op | значение tf.distribute.ReduceOp, указывающее, как следует объединять значения. Можно использовать строковое представление перечисления, например "SUM" или "MEAN". |
value | tf.distribute.DistributedValues или объект, подобный tf.Tensor. |
destinations | tf.distribute.DistributedValues, tf.Variable, объект, подобный tf.Tensor, или строка с именем устройства. Указывает устройства, на которые нужно выполнить редукцию. Чтобы выполнить all-reduce, передайте одинаковые значения в value и destinations. Обратите внимание: если это tf.Variable, значение редуцируется на устройствах этой переменной, но данный метод не обновляет переменную. |
options | tf.distribute.experimental.CommunicationOptions. Параметры для выполнения коллективных операций. Они переопределяют параметры по умолчанию, если tf.distribute.Strategy принимает их в конструкторе. Подробное описание параметров см. в разделе tf.distribute.experimental.CommunicationOptions. |
| Возвращает | |
|---|---|
Тензор или значение, редуцированное до destinations. |
update
update(
var, fn, args=(), kwargs=None, group=True
)
Выполняет fn для обновления var с использованием входных данных, зеркально распределённых по тем же устройствам.
tf.distribute.StrategyExtended.update принимает распределённую переменную var для обновления, функцию обновления fn, а также args и kwargs для fn. Метод применяет fn к каждой компонентной переменной var и передаёт соответствующие значения из args и kwargs. Ни args, ни kwargs не могут содержать значения для отдельных реплик. Если они содержат зеркально распределённые значения, перед вызовом fn они будут распакованы. Например, fn может быть assign_add, а args — зеркально распределённым объектом DistributedValues, каждый компонент которого содержит значение, которое нужно добавить к этой зеркально распределённой переменной var. Вызов update вызовет assign_add для каждой компонентной переменной var, передав соответствующее значение тензора на этом устройстве.
Пример использования:
strategy = tf.distribute.MirroredStrategy(['GPU:0', 'GPU:1']) # With 2
devices
with strategy.scope():
v = tf.Variable(5.0, aggregation=tf.VariableAggregation.SUM)
def update_fn(v):
return v.assign(1.0)
result = strategy.extended.update(v, update_fn)
# result is
# Mirrored:{
# 0: tf.Tensor(1.0, shape=(), dtype=float32),
# 1: tf.Tensor(1.0, shape=(), dtype=float32)
# }
Если var зеркально распределена между несколькими устройствами, этот метод реализует следующую логику:
results = {}
for device, v in var:
with tf.device(device):
# args and kwargs will be unwrapped if they are mirrored.
results[device] = fn(v, *args, **kwargs)
return merged(results)
В противном случае этот метод возвращает fn(var, *args, **kwargs), размещённый на том же устройстве, что и var.
| Аргументы | |
|---|---|
var | Переменная, возможно, зеркально распределённая между несколькими устройствами, над которой нужно выполнить операцию. |
fn | Вызываемая функция. Переменная должна быть её первым аргументом. |
args | Кортеж или список. Дополнительные позиционные аргументы, передаваемые в fn(). |
kwargs | Словарь с именованными аргументами, передаваемыми в fn(). |
group | Логическое значение. По умолчанию — True. Если значение False, возвращаемое значение будет распаковано. |
| Возвращает | |
|---|---|
По умолчанию — объединённое возвращаемое значение fn для всех реплик. Объединённый результат имеет зависимости, обеспечивающие выполнение побочных эффектов (обновлений) на каждой реплике, если результат вычисляется. Если же указано "group=False", эта функция возвращает вложенную структуру списков, в каждом из которых есть элемент для каждой реплики; вызывающий код отвечает за то, чтобы все элементы были выполнены. |
update_non_slot
update_non_slot(
colocate_with, fn, args=(), kwargs=None, group=True
)
Выполняет fn(*args, **kwargs) на устройствах colocate_with.
Используется для обновления переменных, не относящихся к слотам.
| Аргументы | |
|---|---|
colocate_with | Устройства, возвращаемые методом non_slot_devices(). |
fn | Функция для выполнения. |
args | Кортеж или список. Позиционные аргументы, передаваемые в fn(). |
kwargs | Словарь с именованными аргументами, передаваемыми в fn(). |
group | Логическое значение. По умолчанию — True. Если значение False, возвращаемое значение будет распаковано. |
| Возвращает | |
|---|---|
Возвращаемое значение fn, возможно, объединённое на нескольких устройствах. |
value_container
value_container(
value
)
Возвращает контейнер, которому принадлежит эта реплицируемая копия value.
| Аргументы | |
|---|---|
value | Значение, возвращённое run(), или переменная, созданная в scope(). |
| Возвращает | |
|---|---|
Контейнер, которому принадлежит value. Если значение не принадлежит ни одному контейнеру (в том числе если контейнер был уничтожен), возвращается само значение. value in experimental_local_results(value_container(value)) всегда будет иметь значение True. |
variable_created_in_scope
variable_created_in_scope(
v
)
Проверяет, была ли v создана при активной области видимости этой стратегии.
Переменные, созданные в области видимости стратегии, принадлежат ей:
strategy = tf.distribute.MirroredStrategy() with strategy.scope(): v = tf.Variable(1.) strategy.extended.variable_created_in_scope(v) True
Переменные, созданные вне стратегии, ей не принадлежат:
strategy = tf.distribute.MirroredStrategy() v = tf.Variable(1.) strategy.extended.variable_created_in_scope(v) False
| Аргументы | |
|---|---|
v | Экземпляр tf.Variable. |
| Возвращает | |
|---|---|
True, если v создана в области видимости, и False в противном случае. |
© 2022 The TensorFlow Authors. All rights reserved.
Licensed under the Creative Commons Attribution License 4.0.
Code samples licensed under the Apache 2.0 License.
https://www.tensorflow.org/api_docs/python/tf/compat/v1/distribute/StrategyExtended