tf.compat.v1.distribute.OneDeviceStrategy
Стратегия распределения для выполнения на одном устройстве.
Наследуется от: Strategy
tf.compat.v1.distribute.OneDeviceStrategy(
device
)
Использование этой стратегии разместит все переменные, созданные в ее области видимости, на указанном устройстве. Данные, распределенные через эту стратегию, будут предварительно загружены на указанное устройство. Кроме того, любые функции, вызываемые через strategy.run также будут размещены на указанном устройстве.
Типичное использование этой стратегии — тестирование кода с API tf.distribute.Strategy перед переключением на другие стратегии, которые фактически распределяют вычисления по нескольким устройствам/машинам.
Например:
tf.enable_eager_execution() strategy = tf.distribute.OneDeviceStrategy(device="/gpu:0") with strategy.scope(): v = tf.Variable(1.0) print(v.device) # /job:localhost/replica:0/task:0/device:GPU:0 def step_fn(x): return x * 2 result = 0 for i in range(10): result += strategy.run(step_fn, args=(i,)) print(result) # 90
| Аргументы | |
|---|---|
device | Идентификатор строки устройства, на котором должны быть размещены переменные. См. документацию класса для получения более подробной информации о том, как используется устройство. Примеры: "/cpu:0", "/gpu:0", "/device:CPU:0", "/device:GPU:0" |
| Атрибуты | |
|---|---|
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 будет вызываться на процессоре CPU каждого из рабочих узлов, и каждый из них создает набор данных, в котором каждая реплика на этом рабочем узле будет извлекать одну партию входов (т. е. если рабочий узел имеет две реплики, две партии будут извлекаться из Dataset на каждом шаге).
Этот метод может использоваться для нескольких целей. Во-первых, он позволяет указать собственную логику разбивки на пакеты и фрагментацию. (В отличие от tf.distribute.experimental_distribute_dataset, который выполняет разбивку на пакеты и фрагментацию за вас.) Например, где experimental_distribute_dataset не может разбить входные файлы, этот метод может использоваться для ручного разбиения набора данных (избегая медленного поведения по умолчанию в experimental_distribute_dataset). В случаях, когда набор данных бесконечен, эта фрагментация может выполняться путем создания реплик набора данных, которые отличаются только своим случайным начальным значением.
Функция dataset_fn должна принимать экземпляр tf.distribute.InputContext, где можно получить информацию о разбивке на пакеты и репликации входов.
Вы можете использовать свойство element_spec возвращаемого этим API tf.distribute.DistributedDataset, чтобы запросить 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 в новый размер пакета, равный глобальному размеру пакета, деленному на количество реплик в синхронизации. Мы перебираем его с помощью цикла for в стиле Python. 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(), 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. Пожалуйста, переключитесь на run.
При включённом режиме выполнения 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.
УСТАРЕЛО: Этот метод недоступен в TF 2.x.
Данные из заданного набора данных будут распределяться равномерно по всем вычислительным репликам. Мы будем предполагать, что входной набор данных сгруппирован по общему размеру пакета. С этим предположением мы будем прилагать все усилия для разделения каждого пакета по всем репликам (один или несколько рабочих узлов). Если эти усилия не увенчаются успехом, будет выброшено исключение, и пользователь должен вместо этого использовать 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
)
Возвращает итератор, разделённый по репликам, созданный из функции входных данных.
УСТАРЕЛО: Этот метод недоступен в 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() или получить следующее значение для передачи в 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 с 2 графическими процессорами:
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, это ЦП каждого работника.
Существует ряд различных API tf.distribute для сведения значений по репликам:
-
tf.distribute.ReplicaContext.all_reduce: Отличается отStrategy.reduceтем, что предназначен для контекста реплики и не копирует результаты на устройство хоста.all_reduceобычно используется для вычислений внутри шага обучения, таких как градиенты. -
tf.distribute.StrategyExtended.reduce_toиtf.distribute.StrategyExtended.batch_reduce_to: Эти API являются более расширенными версиямиStrategy.reduce, поскольку они позволяют настраивать место назначения результата. Они также вызываются в контексте межрепличного взаимодействия.
Каким должен быть ось?
Учитывая значение на реплику, возвращенное run, например, потерю на пример, пакет будет разделен между всеми репликами. Эта функция позволяет агрегировать по репликам и по желанию по элементам пакета, указав параметр оси соответственно.
Например, если у вас есть глобальный размер пакета 8 и 2 реплики, значения для примеров [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, чтобы свести только по репликам (например, если тензор не имеет размерности пакета). |
| Возвращаемое значение | |
|---|---|
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 должны быть либо Python-значениями вложенной структуры тензоров, например, список тензоров, в этом случае args и kwargs будут переданы в fn, вызываемый на каждой реплике. Либо args или kwargs могут быть tf.distribute.DistributedValues, содержащими тензоры или составные тензоры, т.е. tf.compat.v1.TensorInfo.CompositeTensor, в этом случае каждый вызов fn получит компонент tf.distribute.DistributedValues, соответствующий его реплике.
Пример использования:
- Входной тензор с константой.
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. Его элемент может быть Python-значением, тензором или tf.distribute.DistributedValues. |
kwargs | Необязательные ключевые аргументы для fn. Его элемент может быть Python-значением, тензором или 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для явного распределения вычисления. См. пример в руководстве по пользовательским циклам обучения.
Что должно быть в области действия, а что — вне её?
Существует ряд требований к тому, что должно происходить внутри области действия. Однако в тех местах, где у нас есть информация о используемой стратегии, мы часто входим в область действия за пользователя, чтобы ему не приходилось делать это явно (т.е. вызов как внутри, так и вне области действия допустим).
- Все, что создает переменные, которые должны быть распределенными переменными, должно быть в
strategy.scope. Это можно сделать, либо непосредственно поместив его в область действия, либо используя другой API, например,strategy.runилиmodel.fit, чтобы он вошел в него за вас. Любая переменная, созданная вне области действия, не будет распределена и может иметь последствия для производительности. Общие вещи, создающие переменные в TF: модели, оптимизаторы, метрики. Они всегда должны создаваться внутри области действия. Другим источником создания переменных может быть восстановление контрольной точки — когда переменные создаются лениво. Обратите внимание, что любая переменная, созданная внутри стратегии, сохраняет информацию о стратегии. Таким образом, чтение и запись в эти переменные внеstrategy.scopeтакже могут работать без проблем, без необходимости ввода пользователя в область действия. - Некоторые API стратегий (например,
strategy.runиstrategy.reduce) которые требуют находиться в области действия стратегии, автоматически входят в область действия, что означает, что при использовании этих API вам не нужно входить в область действия самостоятельно. - Когда
tf.keras.Modelсоздается внутриstrategy.scope, мы сохраняем эту информацию. Когда высокоуровневые методы обучения, такие как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 с изменениями для использования с данной стратегией.
УСТАРЕЛО: Этот метод недоступен в 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/r2.4/api_docs/python/tf/compat/v1/distribute/OneDeviceStrategy