tf.compat.v1.distribute.Strategy
Список устройств с политикой распределения состояния и вычислений.
tf.compat.v1.distribute.Strategy(
extended
)
Обзор и примеры см. в руководстве.
Примечание: В настоящее время не все реализации tf.distribute.Strategy поддерживают разделяемые переменные TensorFlow (когда одна переменная распределена между несколькими устройствами).
| Атрибуты | |
|---|---|
cluster_resolver | Возвращает преобразователь кластера, связанный с этой стратегией. Как правило, при использовании стратегии Стратегии, для которых предполагается наличие связанного Стратегии с одним рабочим узлом обычно не имеют
os.environ['TF_CONFIG'] = json.dumps({
'cluster': {
'worker': ["localhost:12345", "localhost:23456"],
'ps': ["localhost:34567"]
},
'task': {'type': 'worker', 'index': 0}
})
# This implicitly uses TF_CONFIG for the cluster and current task info.
strategy = tf.distribute.experimental.MultiWorkerMirroredStrategy()
...
if strategy.cluster_resolver.task_type == 'worker':
# Perform something that's only applicable on workers. Since we set this
# as a worker above, this block will run on this particular instance.
elif strategy.cluster_resolver.task_type == 'ps':
# Perform something that's only applicable on parameter servers. Since we
# set this as a worker above, this block will not run on this particular
# instance.
Дополнительную информацию см. в строке документации API для |
extended | tf.distribute.StrategyExtended с дополнительными методами. |
num_replicas_in_sync | Возвращает количество реплик, между которыми агрегируются градиенты. |
Методы
distribute_datasets_from_function
distribute_datasets_from_function(
dataset_fn, options=None
)
Распределяет экземпляры tf.data.Dataset, создаваемые вызовами dataset_fn.
Аргумент dataset_fn, передаваемый пользователями, — это функция ввода, которая принимает аргумент tf.distribute.InputContext и возвращает экземпляр tf.data.Dataset. Предполагается, что возвращаемый функцией dataset_fn набор данных уже разбит на пакеты размером с пакет для каждой реплики (то есть глобальный размер пакета, делённый на число синхронизированных реплик) и разделён на шарды. tf.distribute.Strategy.distribute_datasets_from_function не разбивает на пакеты и шарды экземпляр tf.data.Dataset, возвращённый функцией ввода. dataset_fn будет вызвана на устройстве ЦП каждого рабочего узла, и каждая из них создаст набор данных, из которого каждая реплика на этом рабочем узле будет извлекать один пакет входных данных (то есть, если у рабочего узла две реплики, на каждом шаге из Dataset будут извлечены два пакета).
Этот метод можно использовать для разных целей. Во-первых, он позволяет указать собственную логику разбиения на пакеты и шарды. (В отличие от этого, tf.distribute.experimental_distribute_dataset выполняет разбиение на пакеты и шарды за вас.) Например, если experimental_distribute_dataset не может разделить входные файлы на шарды, этот метод можно использовать для ручного разделения набора данных на шарды (чтобы избежать медленного резервного поведения в experimental_distribute_dataset). Если набор данных бесконечен, такое разделение на шарды можно выполнить, создав реплики набора данных, различающиеся только случайным начальным значением.
Функция dataset_fn должна принимать экземпляр tf.distribute.InputContext, предоставляющий сведения о разбиении на пакеты и репликации входных данных.
С помощью свойства element_spec объекта tf.distribute.DistributedDataset, возвращаемого этим API, можно запросить tf.TypeSpec элементов, возвращаемых итератором. Это можно использовать для задания свойства input_signature объекта tf.function. Пример см. в разделе tf.distribute.DistributedDataset.element_spec.
Примечание: При использовании TPUStrategy порядок обработки данных рабочими узлами при использованииtf.distribute.Strategy.experimental_distribute_datasetилиtf.distribute.Strategy.distribute_datasets_from_functionне гарантируется. Обычно это требуется при использованииtf.distributeдля масштабирования предсказаний. Однако можно добавить индекс каждому элементу пакета и упорядочить выходные данные соответствующим образом. Пример упорядочивания выходных данных см. в этом фрагменте.
Примечание: Преобразования наборов данных с состоянием в настоящее время не поддерживаются дляtf.distribute.experimental_distribute_datasetилиtf.distribute.distribute_datasets_from_function. Любые операции с состоянием, которые могут присутствовать в наборе данных, сейчас игнорируются. Например, если в наборе данных естьmap_fn, использующийtf.random.uniformдля поворота изображения, то граф набора данных зависит от состояния (то есть от случайного начального значения) на локальном компьютере, где выполняется процесс Python.
Руководство с дополнительными сведениями об использовании и свойствах этого метода см. в руководстве по распределённому вводу). Сведения об обработке последнего неполного пакета см. в этом разделе.
| Аргументы | |
|---|---|
dataset_fn | Функция, принимающая экземпляр tf.distribute.InputContext и возвращающая tf.data.Dataset. |
options | tf.distribute.InputOptions, используемый для управления параметрами распределения этого набора данных. |
| Возвращает | |
|---|---|
Объект tf.distribute.DistributedDataset. |
experimental_distribute_dataset
experimental_distribute_dataset(
dataset, options=None
)
Создаёт tf.distribute.DistributedDataset из tf.data.Dataset.
Возвращаемый объект tf.distribute.DistributedDataset можно перебирать так же, как обычные наборы данных. ПРИМЕЧАНИЕ: пользователь не может добавлять преобразования к объекту tf.distribute.DistributedDataset. Можно только создать итератор или проверить tf.TypeSpec данных, генерируемых им. Дополнительные сведения см. в документации API для tf.distribute.DistributedDataset.
Пример:
global_batch_size = 2
# Passing the devices is optional.
strategy = tf.distribute.MirroredStrategy(devices=["GPU:0", "GPU:1"])
# Create a dataset
dataset = tf.data.Dataset.range(4).batch(global_batch_size)
# Distribute that dataset
dist_dataset = strategy.experimental_distribute_dataset(dataset)
@tf.function
def replica_fn(input):
return input*2
result = []
# Iterate over the `tf.distribute.DistributedDataset`
for x in dist_dataset:
# process dataset elements
result.append(strategy.run(replica_fn, args=(x,)))
print(result)
[PerReplica:{
0: <tf.Tensor: shape=(1,), dtype=int64, numpy=array([0])>,
1: <tf.Tensor: shape=(1,), dtype=int64, numpy=array([2])>
}, PerReplica:{
0: <tf.Tensor: shape=(1,), dtype=int64, numpy=array([4])>,
1: <tf.Tensor: shape=(1,), dtype=int64, numpy=array([6])>
}]Этот метод выполняет три ключевые операции: разбиение на пакеты, разделение на шарды и предварительную выборку.
В приведённом выше фрагменте кода dataset разбивается на пакеты с помощью global_batch_size, а вызов experimental_distribute_dataset для него повторно разбивает dataset на пакеты нового размера, равного глобальному размеру пакета, делённому на число синхронизированных реплик. Перебор выполняется с помощью цикла Python for. x — это tf.distribute.DistributedValues, содержащий данные для всех реплик, и каждая реплика получает данные нового размера пакета. tf.distribute.Strategy.run передаст нужные данные для каждой реплики из x нужному объекту replica_fn, выполняемому на каждой реплике.
Разделение на шарды включает автоматическое разделение между несколькими рабочими узлами и внутри каждого рабочего узла. Во-первых, при распределённом обучении с несколькими рабочими узлами (то есть при использовании tf.distribute.experimental.MultiWorkerMirroredStrategy или tf.distribute.TPUStrategy) автоматическое разделение набора данных между рабочими узлами означает, что каждому рабочему узлу назначается подмножество всего набора данных (если задана соответствующая tf.data.experimental.AutoShardPolicy). Это необходимо для того, чтобы на каждом шаге каждый рабочий узел обрабатывал глобальный пакет элементов набора данных без пересечений. Для автоматического разделения на шарды предусмотрено несколько параметров, которые можно задать с помощью tf.data.experimental.DistributeOptions. Затем данные внутри каждого рабочего узла разделяются между всеми устройствами этого рабочего узла (если их больше одного). Это происходит независимо от автоматического разделения между несколькими рабочими узлами.
Примечание: Режим автоматического разделения на шарды между несколькими рабочими узлами по умолчанию —tf.data.experimental.AutoShardPolicy.AUTO. В этом режиме предпринимается попытка разделить входной набор данных по файлам, если он создан из наборов данных-ридеров (например,tf.data.TFRecordDataset,tf.data.TextLineDatasetи т. д.); в противном случае набор данных разделяется по элементам: каждый рабочий узел считывает весь набор данных, но обрабатывает только назначенный ему шард. Однако, если на каждый рабочий узел приходится менее одного входного файла, рекомендуется отключить автоматическое разделение набора данных между рабочими узлами, задав для параметраtf.data.experimental.DistributeOptions.auto_shard_policyзначениеtf.data.experimental.AutoShardPolicy.OFF.
По умолчанию этот метод добавляет преобразование предварительной выборки в конец предоставленного пользователем экземпляра tf.data.Dataset. Аргумент преобразования предварительной выборки, то есть buffer_size, равен числу синхронизированных реплик.
Если описанная выше логика разделения пакетов и наборов данных на шарды вам не подходит, используйте вместо неё tf.distribute.Strategy.distribute_datasets_from_function, который не выполняет автоматическое разбиение на пакеты или шарды.
Примечание: При использовании TPUStrategy порядок обработки данных рабочими узлами при использованииtf.distribute.Strategy.experimental_distribute_datasetилиtf.distribute.Strategy.distribute_datasets_from_functionне гарантируется. Обычно это требуется при использованииtf.distributeдля масштабирования предсказаний. Однако можно добавить индекс каждому элементу пакета и упорядочить выходные данные соответствующим образом. Пример упорядочивания выходных данных см. в этом фрагменте.
Примечание: Преобразования наборов данных с состоянием в настоящее время не поддерживаются дляtf.distribute.experimental_distribute_datasetилиtf.distribute.distribute_datasets_from_function. Любые операции с состоянием, которые могут присутствовать в наборе данных, сейчас игнорируются. Например, если в наборе данных естьmap_fn, использующийtf.random.uniformдля поворота изображения, то граф набора данных зависит от состояния (то есть от случайного начального значения) на локальном компьютере, где выполняется процесс Python.
Руководство с дополнительными сведениями об использовании и свойствах этого метода см. в руководстве по распределённому вводу. Сведения об обработке последнего неполного пакета см. в этом разделе.
| Аргументы | |
|---|---|
dataset | tf.data.Dataset, который будет разделён между всеми репликами согласно описанным выше правилам. |
options | tf.distribute.InputOptions, используемый для управления параметрами распределения этого набора данных. |
| Возвращает | |
|---|---|
Объект tf.distribute.DistributedDataset. |
experimental_local_results
experimental_local_results(
value
)
Возвращает список всех локальных значений для каждой реплики, содержащихся в value.
Примечание: Возвращаются только значения рабочего узла, с которого инициирован вызов этим клиентом. При использованииtf.distribute.Strategy, напримерtf.distribute.experimental.MultiWorkerMirroredStrategy, каждый рабочий узел является отдельным клиентом, и эта функция возвращает только значения, вычисленные на этом рабочем узле.
| Аргументы | |
|---|---|
value | Значение, возвращённое вызовом experimental_run(), run(), or a variable created inscope`. |
| Возвращает | |
|---|---|
Кортеж значений, содержащихся в value, где i-й элемент соответствует i-й реплике. Если 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. (Устарел)
Если включено eager-выполнение, выполняет операции, заданные в fn, для каждой реплики. В противном случае создаёт граф для выполнения операций на каждой реплике.
Каждая реплика получает отдельный входной элемент из входных данных, предоставленных одним вызовом get_next итератора ввода.
fn может вызывать tf.distribute.get_replica_context() для доступа к таким членам, как replica_id_in_sync_group.
| Аргументы | |
|---|---|
fn | Функция для выполнения. Входные данные функции должны соответствовать выходным данным input_iterator.get_next(). Выходное значение должно представлять собой tf.nest из объектов Tensor. |
input_iterator | (Необязательно) Итератор ввода, из которого берутся входные данные. |
| Возвращает | |
|---|---|
Объединённое возвращаемое значение fn для всех реплик. Структура возвращаемого значения совпадает со структурой значения, возвращаемого fn. Каждый элемент структуры может быть PerReplica (если значения не синхронизированы), Mirrored (если значения синхронизированы) или Tensor (если выполняется на одной реплике). |
make_dataset_iterator
make_dataset_iterator(
dataset
)
Создаёт итератор для входных данных, переданных через dataset.
Данные из указанного набора данных будут равномерно распределены между всеми вычислительными репликами. Предполагается, что входной набор данных разбит на пакеты размером с глобальный пакет. Исходя из этого предположения, будет предпринята попытка разделить каждый пакет между всеми репликами (на одном или нескольких рабочих узлах). Если это не удастся, будет выдана ошибка; в таком случае вместо этого следует использовать make_input_fn_iterator, который предоставляет пользователю больше возможностей управления и не пытается разделять пакет между репликами.
Если пользователь хочет настроить, какие входные данные передаются каким репликам или рабочим узлам и т. д., можно также использовать 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
)
Возвращает итератор, распределённый между репликами и созданный на основе функции ввода.
Функция 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)
Возвращаемый функцией input_fn набор данных tf.data.Dataset должен иметь размер пакета для одной реплики, который можно вычислить с помощью 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 между репликами и возвращает результат на текущем устройстве.
strategy = tf.distribute.MirroredStrategy(["GPU:0", "GPU:1"])
def step_fn():
i = tf.distribute.get_replica_context().replica_id_in_sync_group
return tf.identity(i)
per_replica_result = strategy.run(step_fn)
total = strategy.reduce("SUM", per_replica_result, axis=None)
total
<tf.Tensor: shape=(), dtype=int32, numpy=1>Чтобы увидеть, как это будет выглядеть при нескольких репликах, рассмотрим тот же пример с MirroredStrategy и двумя графическими процессорами:
strategy = tf.distribute.MirroredStrategy(devices=["GPU:0", "GPU:1"])
def step_fn():
i = tf.distribute.get_replica_context().replica_id_in_sync_group
return tf.identity(i)
per_replica_result = strategy.run(step_fn)
# Check devices on which per replica result is:
strategy.experimental_local_results(per_replica_result)[0].device
# /job:localhost/replica:0/task:0/device:GPU:0
strategy.experimental_local_results(per_replica_result)[1].device
# /job:localhost/replica:0/task:0/device:GPU:1
total = strategy.reduce("SUM", per_replica_result, axis=None)
# Check device on which reduced result is:
total.device
# /job:localhost/replica:0/task:0/device:CPU:0
Этот API обычно используется для агрегирования результатов, возвращаемых разными репликами, например для их вывода. Например, потери, вычисленные разными репликами, можно усреднить с помощью этого API перед выводом.
Примечание: Результат копируется на «текущее» устройство, которым обычно является ЦП рабочего узла, на котором выполняется программа. ДляTPUStrategyэто первый хост TPU. Для многоклиентскогоMultiWorkerMirroredStrategyэто ЦП каждого рабочего узла.
В tf.distribute предусмотрено несколько API для сведения значений между репликами:
-
tf.distribute.ReplicaContext.all_reduce: В отличие отStrategy.reduce, этот метод предназначен для контекста реплики и не копирует результаты на устройство хоста. Обычноall_reduceследует использовать для сведения данных внутри шага обучения, например градиентов. -
tf.distribute.StrategyExtended.reduce_toиtf.distribute.StrategyExtended.batch_reduce_to: эти API представляют собой более сложные версииStrategy.reduce, поскольку позволяют настраивать устройство назначения результата. Они также вызываются в контексте между репликами.
Каким должно быть значение axis?
Значение для одной реплики, возвращаемое run, например потери для каждого примера, означает, что пакет будет распределён между всеми репликами. Эта функция позволяет агрегировать данные между репликами, а при необходимости — также между элементами пакета, задав соответствующий параметр axis.
Например, если глобальный размер пакета равен 8, а реплик две, значения для примеров [0, 1, 2, 3] будут находиться на реплике 0, а [4, 5, 6, 7] — на реплике 1. При значении axis=None параметра reduce агрегирование выполняется только между репликами, и возвращается [0+4, 1+5, 2+6, 3+7]. Это полезно, когда каждая реплика вычисляет скаляр или другое значение без измерения «пакета» (например, градиент или потери).
strategy.reduce("sum", per_replica_result, axis=None)
Иногда требуется выполнить агрегирование и по глобальному пакету, и по всем репликам. Для этого задайте измерение пакета в качестве axis, обычно axis=0. В этом случае будет возвращён скаляр 0+1+2+3+4+5+6+7.
strategy.reduce("sum", per_replica_result, axis=0)
Если последний пакет неполный, необходимо указать ось, чтобы результирующая форма была согласованной для всех реплик. Например, если последний пакет содержит 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, указывающее, как следует объединять значения. Допускается использовать строковое представление элемента перечисления, например "SUM" или "MEAN". |
value | Экземпляр tf.distribute.DistributedValues, например возвращённый вызовом Strategy.run, который требуется объединить в один тензор. При использовании с OneDeviceStrategy или стратегией по умолчанию также может быть обычным тензором. |
axis | Задаёт измерение, по которому выполняется сведение тензора каждой реплики. Обычно следует задать измерение пакета или None, чтобы выполнять сведение только между репликами (например, если у тензора нет измерения пакета). |
| Возвращаемое значение | |
|---|---|
A Tensor. |
run
run(
fn, args=(), kwargs=None, options=None
)
Вызывает fn на каждой реплике с заданными аргументами.
Этот метод — основной способ распределения вычислений с помощью объекта tf.distribute. Он вызывает fn на каждой реплике. Если args или kwargs имеют tf.distribute.DistributedValues, например созданные с помощью tf.distribute.DistributedDataset из tf.distribute.Strategy.experimental_distribute_dataset или tf.distribute.Strategy.distribute_datasets_from_function, то при выполнении fn на определённой реплике будет использоваться компонент tf.distribute.DistributedValues, соответствующий этой реплике.
fn вызывается в контексте реплики. fn может вызывать tf.distribute.get_replica_context() для доступа к таким элементам, как all_reduce. Описание понятия контекста реплики см. в документации модуля tf.distribute.
Все аргументы в args или kwargs могут представлять собой вложенную структуру тензоров, например список тензоров. В этом случае args и kwargs будут переданы в fn, вызываемый на каждой реплике. Кроме того, args или kwargs могут быть объектами tf.distribute.DistributedValues, содержащими тензоры или составные тензоры, то есть tf.compat.v1.TensorInfo.CompositeTensor. В этом случае каждый вызов fn получит компонент tf.distribute.DistributedValues, соответствующий своей реплике. Обратите внимание: произвольные значения Python, не относящиеся к указанным выше типам, не поддерживаются.
Примеры использования:
-
Входной тензор-константа.
strategy = tf.distribute.MirroredStrategy(["GPU:0", "GPU:1"]) tensor_input = tf.constant(3.0) @tf.function def replica_fn(input): return input*2.0 result = strategy.run(replica_fn, args=(tensor_input,)) result PerReplica:{ 0: <tf.Tensor: shape=(), dtype=float32, numpy=6.0>, 1: <tf.Tensor: shape=(), dtype=float32, numpy=6.0> } -
Входные данные DistributedValues.
strategy = tf.distribute.MirroredStrategy(["GPU:0", "GPU:1"]) @tf.function def run(): def value_fn(value_context): return value_context.num_replicas_in_sync distributed_values = ( strategy.experimental_distribute_values_from_function( value_fn)) def replica_fn2(input): return input*2 return strategy.run(replica_fn2, args=(distributed_values,)) result = run() result <tf.Tensor: shape=(), dtype=int32, numpy=4> -
Используйте
tf.distribute.ReplicaContextдля выполнения allreduce значений.strategy = tf.distribute.MirroredStrategy(["gpu:0", "gpu:1"]) @tf.function def run(): def value_fn(value_context): return tf.constant(value_context.replica_id_in_sync_group) distributed_values = ( strategy.experimental_distribute_values_from_function( value_fn)) def replica_fn(input): return tf.distribute.get_replica_context().all_reduce( "sum", input) return strategy.run(replica_fn, args=(distributed_values,)) result = run() result PerReplica:{ 0: <tf.Tensor: shape=(), dtype=int32, numpy=1>, 1: <tf.Tensor: shape=(), dtype=int32, numpy=1> }
| Аргументы | |
|---|---|
fn | Функция, выполняемая на каждой реплике. |
args | Необязательные позиционные аргументы для fn. Элемент может быть тензором, вложенной структурой тензоров или tf.distribute.DistributedValues. |
kwargs | Необязательные именованные аргументы для fn. Элемент может быть тензором, вложенной структурой тензоров или tf.distribute.DistributedValues. |
options | Необязательный экземпляр tf.distribute.RunOptions, задающий параметры выполнения fn. |
| Возвращаемое значение | |
|---|---|
Объединённое возвращаемое значение fn для всех реплик. Структура возвращаемого значения совпадает со структурой значения, возвращаемого fn. Каждый элемент структуры может быть объектом tf.distribute.DistributedValues, объектом Tensor или Tensor (например, при выполнении на одной реплике). |
scope
scope()
Менеджер контекста, который устанавливает стратегию в качестве текущей и распределяет переменные.
Этот метод возвращает менеджер контекста и используется следующим образом:
strategy = tf.distribute.MirroredStrategy(["GPU:0", "GPU:1"])
# Variable created inside scope:
with strategy.scope():
mirrored_variable = tf.Variable(1.)
mirrored_variable
MirroredVariable:{
0: <tf.Variable 'Variable:0' shape=() dtype=float32, numpy=1.0>,
1: <tf.Variable 'Variable/replica_1:0' shape=() dtype=float32, numpy=1.0>
}
# Variable created outside scope:
regular_variable = tf.Variable(1.)
regular_variable
<tf.Variable 'Variable:0' shape=() dtype=float32, numpy=1.0>Что происходит при входе в Strategy.scope?
-
strategyустанавливается в глобальном контексте как «текущая» стратегия. В этой области вызовtf.distribute.get_strategy()теперь будет возвращать эту стратегию. За пределами этой области он возвращает стратегию по умолчанию, ничего не выполняющую. - При входе в область также активируется «контекст между репликами». Объяснение контекстов между репликами и реплик см. в разделе
tf.distribute.StrategyExtended. - Создание переменных внутри
scopeперехватывается стратегией. Каждая стратегия определяет, как именно она влияет на создание переменных. Синхронные стратегии, такие какMirroredStrategy,TPUStrategyиMultiWorkerMiroredStrategy, создают переменные, реплицированные на каждой реплике, тогда какParameterServerStrategyсоздаёт переменные на серверах параметров. Это реализуется с помощью пользовательскогоtf.variable_creator_scope. - В некоторых стратегиях также может активироваться область устройства по умолчанию: в
MultiWorkerMiroredStrategyдля каждого рабочего процесса активируется область устройства по умолчанию «/CPU:0».
Примечание: Вход в область не приводит к автоматическому распределению вычислений, за исключением случаев использования высокоуровневой платформы обучения, например kerasmodel.fit. Если вы не используетеmodel.fit, для явного распределения вычислений необходимо использовать APIstrategy.run. Пример см. в руководстве по циклу пользовательского обучения.
Что должно находиться внутри области, а что — за её пределами?
Существуют некоторые требования к действиям, которые необходимо выполнять внутри области. Однако в тех случаях, когда нам известно, какая стратегия используется, мы часто активируем область за пользователя, чтобы ему не приходилось делать это явно (то есть вызовы этих API допустимы как внутри, так и вне области).
- Всё, что создаёт переменные, которые должны быть распределёнными, необходимо вызывать внутри
strategy.scope. Для этого можно либо напрямую вызвать функцию создания переменной в контексте области, либо воспользоваться другим API, напримерstrategy.runилиkeras.Model.fit, который активирует область автоматически. Переменные, созданные вне области, не будут распределены, что может повлиять на производительность. В TF переменные создают, например, модели, оптимизаторы и метрики. Такие объекты всегда следует инициализировать в области, а функции, которые могут создавать переменные отложенно (например,Model.call(), трассировкаtf.functionи т. д.), также следует вызывать внутри области. Ещё одним источником создания переменных может быть восстановление контрольной точки, если переменные создаются отложенно. Обратите внимание: любая переменная, созданная внутри стратегии, сохраняет информацию о стратегии. Поэтому чтение и запись таких переменных внеstrategy.scopeтакже могут выполняться без проблем, и пользователю не нужно входить в область. - Некоторые API стратегии (например,
strategy.runиstrategy.reduce), требующие нахождения в области стратегии, активируют эту область автоматически. Это означает, что при использовании этих API вам не нужно явно входить в область. - Если
tf.keras.Modelсоздаётся внутриstrategy.scope, объект Model сохраняет информацию об области. При вызове высокоуровневых методов платформы обучения, таких какmodel.compile,model.fitи т. д., сохранённая область будет активирована автоматически, а связанная с ней стратегия будет использоваться для распределённого обучения и других задач. Подробный пример см. в руководстве по распределённому обучению с keras. ПРЕДУПРЕЖДЕНИЕ: простой вызовmodel(..)не активирует сохранённую область автоматически — такое поведение поддерживается только высокоуровневыми API платформы обучения:model.compile,model.fit,model.evaluate,model.predictиmodel.saveможно вызывать как внутри, так и вне области. - Следующие действия можно выполнять как внутри области, так и вне её:
- Создание входных наборов данных
- Определение
tf.function, представляющих шаг обучения - API сохранения, такие как
tf.saved_model.save. При загрузке создаются переменные, поэтому её следует выполнять внутри области, если вы хотите обучать модель распределённым способом. - Сохранение контрольных точек. Как упоминалось выше, иногда
checkpoint.restoreнеобходимо выполнять внутри области, если при этом создаются переменные.
| Возвращаемое значение | |
|---|---|
| Менеджер контекста. |
update_config_proto
update_config_proto(
config_proto
)
Возвращает копию config_proto, изменённую для использования с этой стратегией.
Обновлённая конфигурация содержит необходимые для работы стратегии параметры, например конфигурацию для выполнения коллективных операций или фильтры устройств, повышающие производительность распределённого обучения.
| Аргументы | |
|---|---|
config_proto | объект tf.ConfigProto. |
| Возвращаемое значение | |
|---|---|
Обновлённая копия config_proto. |
© 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/Strategy