tf.distribute.StrategyExtended
| Просмотреть исходный код на GitHub |
Дополнительные 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 в контексте реплики. Он поддерживает как пакетное, так и непакетное 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: <tf.Variable 'Variable:0' shape=() dtype=float32, numpy=2.0>,
1: <tf.Variable 'Variable/replica_1:0' shape=() dtype=float32, numpy=2.0>
}
run(tf.distribute.experimental.CentralStorageStrategy(
compute_devices=["GPU:0", "GPU:1"], parameter_device="CPU:0"))
<tf.Variable 'Variable:0' shape=() dtype=float32, numpy=2.0>
run(tf.distribute.OneDeviceStrategy("GPU:0"))
<tf.Variable 'Variable:0' shape=() dtype=float32, numpy=1.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 в контексте реплики. Он поддерживает как пакетное, так и непакетное all-reduce. -
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):
# 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: <tf.Variable 'Variable:0' shape=() dtype=float32, numpy=2.0>,
1: <tf.Variable 'Variable/replica_1:0' shape=() dtype=float32, numpy=2.0>
}
run(tf.distribute.experimental.CentralStorageStrategy(
compute_devices=["GPU:0", "GPU:1"], parameter_device="CPU:0"))
<tf.Variable 'Variable:0' shape=() dtype=float32, numpy=2.0>
run(tf.distribute.OneDeviceStrategy("GPU:0"))
<tf.Variable 'Variable:0' shape=() dtype=float32, numpy=1.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", эта функция вернёт вложенный список списков, где каждый список содержит элемент на реплику, и вызывающая сторона отвечает за обеспечение выполнения всех элементов. |
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 — в противном случае. |
© 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/r2.4/api_docs/python/tf/distribute/StrategyExtended