Spec-Zone.ru › TensorFlow 2.4

tf.compat.v1.distribute.experimental.CentralStorageStrategy

Стратегия для одной машины, которая размещает все переменные на одном устройстве.

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

tf.compat.v1.distribute.experimental.CentralStorageStrategy(
    compute_devices=None, parameter_device=None
)

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

Пример:

strategy = tf.distribute.experimental.CentralStorageStrategy()
# Create a dataset
ds = tf.data.Dataset.range(5).batch(2)
# Distribute that dataset
dist_dataset = strategy.experimental_distribute_dataset(ds)

with strategy.scope():
  @tf.function
  def train_step(val):
    return val + 1

  # Iterate over the distributed dataset
  for x in dist_dataset:
    # process dataset elements
    strategy.run(train_step, args=(x,))
Атрибуты
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 в новый размер пакета, равный глобальному размеру пакета, деленному на количество реплик в синхронизации. Мы итерируемся по нему с помощью цикла Python for. x — это tf.distribute.DistributedValues, содержащий данные для всех реплик, и каждая реплика получает данные нового размера пакета. tf.distribute.Strategy.run позаботится о подаче правильных данных на реплику в x правильным replica_fn на каждой реплике.

Разделение включает автоматическое разделение по нескольким рабочим узлам и внутри каждого рабочего узла. Во-первых, при распределённом обучении на нескольких рабочих узлах (т. е. когда вы используете tf.distribute.experimental.MultiWorkerMirroredStrategy или tf.distribute.TPUStrategy), автоматическое разделение набора данных по рабочим узлам означает, что каждому рабочему узлу назначается подмножество всего набора данных (если установлен соответствующий tf.data.experimental.AutoShardPolicy). Это гарантирует, что на каждом шаге глобальный размер пакета неперекрывающихся элементов набора данных будет обрабатываться каждым рабочим узлом. Автоматическое разделение имеет несколько вариантов, которые можно указать с помощью tf.data.experimental.DistributeOptions. Затем разделение внутри каждого рабочего узла означает, что метод разделит данные между всеми устройствами рабочего узла (если их несколько). Это произойдёт независимо от автоматического разделения набора данных на нескольких рабочих узлах.

END_OF_DOCUMENT_MARKER
Примечание: для автоматического фрагментирования по нескольким рабочим процессам, по умолчанию используется режим 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 вместо этого.

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

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

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

Ключевая точка: В зависимости от реализации tf.distribute.Strategy, используемой, и от того, включен ли режим выполнения операций, 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 GPU:

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

Ключевая информация: В зависимости от реализации 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>
}
  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 для явного распределения вычислений. Смотрите пример в обучающем руководстве по созданию пользовательских циклов обучения custom training loop tutorial.

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

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

  • Всё, что создаёт переменные, которые должны быть распределёнными переменными, должно находиться в 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 distributed keras tutorial. Обратите внимание, что вызов model(..) не затронут - только API высокоуровневых обучающих фреймворков. model.compile, model.fit, model.evaluate, model.predict и model.save могут вызываться внутри или вне области.
  • Следующие вещи могут быть как внутри, так и вне области:
    • Создание наборов входных данных
    • Определение tf.functions, представляющих ваш шаг обучения
    • 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/CentralStorageStrategy

Spec-Zone.ru

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