tf.distribute.StrategyExtended
Дополнительные API для алгоритмов, которые должны учитывать распределение.
tf.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_require_static_shapes | Возвращает True, если статическая форма требуется; False в противном случае. |
parameter_devices | Возвращает кортеж всех устройств, используемых для размещения переменных. |
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 в репликационном контексте. Он поддерживает как пакетное, так и непакетное всеобщее уменьшение. -
tf.distribute.Strategy.reduce: более удобный метод для уменьшения до хоста в межрепликационном контексте.
См. reduce_to для получения дополнительной информации.
@tf.function def step_fn(var):
def merge_fn(strategy, value, var): # Всеобщее уменьшение значения. Обратите внимание, что value здесь — # 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. |
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. |
| Возвращает | |
|---|---|
| Контекстный менеджер. |
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, и назначения будут устройствами этого тензора. Для all-reduce передайте то же самое в value и destinations.
Его можно использовать в tf.distribute.ReplicaContext.merge_call, чтобы написать код, который работает для всех tf.distribute.Strategy.
@tf.function def step_fn(var):
def merge_fn(strategy, value, var): # Всеreduce значение. Обратите внимание, что value здесь — # 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:
| Args | |
|---|---|
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. |
| Returns | |
|---|---|
Тензор или значение, уменьшенное до 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.
| Args | |
|---|---|
var | Переменная, возможно, дублированная на нескольких устройствах, для которой нужно выполнить операцию. |
fn | Функция, которую нужно вызвать. Она должна принимать переменную в качестве первого аргумента. |
args | Кортеж или список. Дополнительные позиционные аргументы для передачи в fn(). |
kwargs | Словарь с ключевыми аргументами для передачи в fn(). |
group | Булево значение. По умолчанию True. Если False, возвращаемое значение будет распаковано. |
| Returns | |
|---|---|
По умолчанию, объединенное возвращаемое значение fn по всем репликам. Объединенный результат имеет зависимости, чтобы гарантировать, что если он вычисляется вообще, побочные эффекты (обновления) произойдут на каждой реплике. Если вместо этого указан "group=False", эта функция вернет вложенный список списков, где каждый список имеет элемент на реплику, и вызывающая сторона отвечает за обеспечение выполнения всех элементов. |
value_container
value_container(
value
)
Возвращает контейнер, к которому принадлежит эта реплицированная value.
| Args | |
|---|---|
value | Значение, возвращаемое run() или переменной, созданной в scope(). |
| Returns | |
|---|---|
Контейнер, к которому принадлежит value. Если значение не принадлежит ни одному контейнеру (включая случай, когда контейнер был уничтожен), возвращает само значение. value in experimental_local_results(value_container(value)) всегда будет истинным. |
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
| Args | |
|---|---|
v | Экземпляр tf.Variable. |
| Returns | |
|---|---|
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/distribute/StrategyExtended