Spec-Zone.ru › TensorFlow

tf.compat.v1.distribute.experimental.ParameterServerStrategy

Асинхронная многоузловая стратегия параметрического сервера tf.distribute.

Наследуется от: Strategy

tf.compat.v1.distribute.experimental.ParameterServerStrategy(
    cluster_resolver=None
)

Эта стратегия требует двух ролей: рабочие узлы и параметрические серверы. Переменные и обновления этих переменных будут назначены параметрическим серверам, а другие операции – рабочим узлам.

Когда на каждом рабочем узле используется более одного GPU, операции будут дублироваться на всех GPU. Несмотря на то, что операции могут дублироваться, переменные нет, и каждый рабочий узел разделяет общее представление того, какому параметрическому серверу назначена переменная.

По умолчанию он использует TFConfigClusterResolver для обнаружения конфигураций для многоузловой тренировки. Это требует переменной окружения 'TF_CONFIG', и 'TF_CONFIG' должна содержать спецификацию кластера.

Этот класс предполагает, что каждый рабочий узел выполняет код независимо, но параметрические серверы работают как стандартные серверы. Это означает, что в то время как каждый рабочий узел синхронно вычисляет одно обновление градиента на всех GPU, обновления между рабочими узлами выполняются асинхронно. Операции, которые выполняются только на первой реплике (например, увеличение глобального шага), будут выполняться на первой реплике каждого рабочего узла.

Ожидается, что вы вызовете call_for_each_replica(fn, ...) для любых операций, которые потенциально могут быть дублированы на нескольких репликах (т. е. нескольких GPU), даже если есть только CPU или один GPU. При определении fn необходимо соблюдать особую осторожность:

1) Обычно не рекомендуется открывать область устройства в области действия стратегии. Область устройства (т. е. вызов tf.device) будет объединена или переопределена устройством для операций, но не изменит устройство для переменных.

2) Также не рекомендуется открывать область совместного размещения (т. е. вызов tf.compat.v1.colocate_with) в области действия стратегии. Для совместного размещения переменных используйте strategy.extended.colocate_vars_with вместо этого. Совместное размещение операций может привести к конфликтам в назначении устройства.

Примечание: Эта стратегия работает только с API Estimator. Передайте экземпляр этой стратегии в аргумент experimental_distribute при создании RunConfig. Этот экземпляр RunConfig должен затем передаваться в экземпляр Estimator, на котором вызывается train_and_evaluate.

Пример:

strategy = tf.distribute.experimental.ParameterServerStrategy()
run_config = tf.estimator.RunConfig(
    experimental_distribute.train_distribute=strategy)
estimator = tf.estimator.Estimator(config=run_config)
tf.estimator.train_and_evaluate(estimator,...)
Аргументы
cluster_resolver Дополнительный объект tf.distribute.cluster_resolver.ClusterResolver. По умолчанию используется tf.distribute.cluster_resolver.TFConfigClusterResolver.
Атрибуты
cluster_resolver Возвращает решатель кластера, связанный с этой стратегией.

В целом, при использовании многоузловой стратегии tf.distribute, такой как tf.distribute.experimental.MultiWorkerMirroredStrategy или tf.distribute.TPUStrategy(), существует связанный tf.distribute.cluster_resolver.ClusterResolver, и такой экземпляр возвращается этим свойством.

Стратегии, которые намерены иметь связанный tf.distribute.cluster_resolver.ClusterResolver, должны установить соответствующий атрибут или переопределить это свойство; в противном случае, по умолчанию возвращается None. Эти стратегии также должны предоставить информацию о том, что возвращается этим свойством.

Стратегии одноузловых вычислений обычно не имеют tf.distribute.cluster_resolver.ClusterResolver, и в этих случаях это свойство вернёт None.

Решатель tf.distribute.cluster_resolver.ClusterResolver может быть полезен, когда пользователю нужно получить доступ к информации, такой как спецификация кластера, тип задачи или идентификатор задачи. Например,

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 tf.distribute.cluster_resolver.ClusterResolver.

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, чтобы увидеть пример.

Важно: tf.data.Dataset, возвращаемый dataset_fn, должен иметь размер пакета на реплику, в отличие от experimental_distribute_dataset, который использует глобальный размер пакета. Это можно вычислить, используя input_context.get_per_replica_batch_size.
Примечание: Если вы используете 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(), 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 1.x) Сессия, используемая для инициализации.
Возвращаемое значение
tf.data.Dataset, представляющий numpy_input.

experimental_run

Просмотреть исходный код

experimental_run(
    fn, input_iterator=None
)

Выполняет операции в fn на каждой реплике с входными данными из input_iterator. (Устарело)

Устарело: ЭТА ФУНКЦИЯ УСТАРЕЛА. Она будет удалена в будущей версии. Инструкции по обновлению: Этот метод недоступен в TF 2.x. Используйте вместо него run.
Устаревшее: Этот метод недоступен в TF 2.x. Пожалуйста, переключитесь на использование run вместо него.

При включенном режиме выполнения eager, выполняет операции, указанные в fn на каждой реплике. В противном случае, строит граф для выполнения операций на каждой реплике.

Каждая реплика получит один, отличающийся вход из входов, предоставленных одним вызовом get_next на итераторе ввода.

fn может вызвать tf.distribute.get_replica_context(), чтобы получить доступ к членам, таким как replica_id_in_sync_group.

Важно: В зависимости от реализации tf.distribute.Strategy, используемой и включён ли режим eager выполнения, fn может быть вызван один или несколько раз (по одному разу для каждой реплики).
Аргументы
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(), или можно использовать 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 с 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=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 могут быть вложенной структурой тензоров, например, списком тензоров, в этом случае args и kwargs будут переданы вызываемому fn на каждой реплике. Или args или kwargs могут быть tf.distribute.DistributedValues, содержащими тензоры или составные тензоры, т.е. tf.compat.v1.TensorInfo.CompositeTensor, в этом случае каждый вызов fn получит компонент tf.distribute.DistributedValues, соответствующий его реплике. Обратите внимание, что произвольные значения Python, которые не являются указанных типов, не поддерживаются.

Важно: В зависимости от реализации tf.distribute.Strategy и от того, включено ли выполнение eager, fn может быть вызван один или несколько раз. Если fn анотирован с tf.function или tf.distribute.Strategy.run вызывается внутри tf.function (eager-выполнение отключено внутри tf.function по умолчанию), fn вызывается один раз на реплику для создания графа Tensorflow, который затем будет повторно использован для выполнения с новыми входными данными. В противном случае, если eager-выполнение включено, fn будет вызываться один раз на реплику на каждом шаге, как и обычный Python-код.

Пример использования:

  1. Ввод постоянного тензора.

    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>
        }
        
  2. Вход 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>
        
  3. Используйте 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".
Примечание: Вход в область не автоматически распределяет вычисления, за исключением случаев использования высокоуровневых фреймворков обучения, таких как Keras model.fit. Если вы не используете model.fit, вам нужно использовать API strategy.run для явного распределения этих вычислений. См. пример в учебном пособии по пользовательскому циклу обучения https://www.tensorflow.org/tutorials/distribute/custom_training.

Что должно быть в области, а что вне?

Существует ряд требований к тому, что должно происходить внутри области. Однако в тех местах, где у нас есть информация о используемой стратегии, мы часто входим в область для пользователя, чтобы он не должен был делать это явно (т.е. вызов внутри или вне области приемлем).

  • Всё, что создаёт переменные, которые должны быть распределёнными переменными, должно вызываться в области 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.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.
END_OF_DOCUMENT_MARKER
Возвращает
Обновлённая копия 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/experimental/ParameterServerStrategy

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API