Spec-Zone.ru › TensorFlow 2.4

tf.compat.v1.distribute.experimental.ParameterServerStrategy

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

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

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

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

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

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

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

Ожидается вызов call_for_each_replica(fn, ...) для любых операций, которые потенциально могут быть дублированы на нескольких репликах (т. е. нескольких графических процессорах), даже если есть только процессор или один графический процессор. При определении 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. 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.

Ключевой момент: В зависимости от используемой реализации tf.distribute.Strategy и от того, включён ли режим выполнения Eager, fn может быть вызван один или несколько раз (по одному разу для каждой реплики).
Аргументы
fn Функция для выполнения. Входные данные функции должны соответствовать выходным данным input_iterator.get_next(). Выходные данные должны быть вложенным tf.nest Tensors.
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 для возвращенного итератора.

data-text="make_input_fn_iterator" id="make_input_fn_iterator">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() с помощью iterator.get_next().

data-text="reduce" id="reduce">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, например, потерю на пример, пакет будет разделён по всем репликам. Эта функция позволяет агрегировать по репликам и, необязательно, по элементам пакета, указав параметр axis.

Например, если у вас есть глобальный размер пакета 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.

data-text="run" id="run">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, соответствующий его реплике.

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

data-text="Example usage:" id="example_usage">Пример использования:

  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>
}
  1. Входные данные 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>
  1. Используйте 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" вводится на каждом узле.
Примечание: Вход в область видимости не приводит к автоматическому распределению вычислений, за исключением случаев использования высокоуровневых фреймворков обучения, таких как Keras model.fit. Если вы не используете model.fit, вам необходимо использовать API strategy.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/experimental/ParameterServerStrategy

Spec-Zone.ru

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