Spec-Zone.ru › TensorFlow

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 вызывается на устройстве ЦП каждого рабочего узла; каждый вызов создаёт набор данных, из которого каждая реплика на этом рабочем узле извлекает один пакет входных данных (то есть, если у рабочего узла две реплики, на каждом шаге из Dataset извлекаются два пакета).

Этот метод можно использовать для нескольких целей. Во-первых, он позволяет задавать собственную логику разбиения на пакеты и сегментации. (В отличие от этого, tf.distribute.experimental_distribute_dataset выполняет разбиение на пакеты и сегментацию за вас.) Например, если experimental_distribute_dataset не может сегментировать входные файлы, этот метод можно использовать для сегментации набора данных вручную (избегая медленного резервного поведения в experimental_distribute_dataset). Если набор данных бесконечен, сегментацию можно выполнить, создав реплики набора данных, различающиеся только случайным начальным значением.

Функция dataset_fn должна принимать экземпляр tf.distribute.InputContext, содержащий сведения о разбиении на пакеты и репликации входных данных.

С помощью свойства element_spec объекта tf.distribute.DistributedDataset, возвращаемого этим API, можно узнать tf.TypeSpec элементов, возвращаемых итератором. Это можно использовать для задания свойства input_signature объекта tf.function. Пример см. в разделе tf.distribute.DistributedDataset.element_spec.

Важно: Размер пакета на реплику у объекта 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 v1.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 и двумя графическими процессорами:

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 обычно используется для агрегирования результатов, возвращаемых разными репликами, например для формирования отчётов. Например, с его помощью можно усреднить значения потерь, вычисленные разными репликами, прежде чем вывести их.

Примечание: Результат копируется на «текущее» устройство — обычно это ЦП рабочего узла, на котором выполняется программа. Для TPUStrategy это первый хост TPU. Для много-клиентского MultiWorkerMirroredStrategy это ЦП каждого рабочего узла.

В tf.distribute предусмотрено несколько API для сведения значений между репликами:

  • tf.distribute.ReplicaContext.all_reduce: Отличается от Strategy.reduce тем, что работает в контексте реплики и не копирует результаты на хост-устройство. Обычно all_reduce следует использовать для сведения данных внутри шага обучения, например градиентов.
  • tf.distribute.StrategyExtended.reduce_to и tf.distribute.StrategyExtended.batch_reduce_to: Эти API являются более продвинутыми версиями Strategy.reduce, поскольку позволяют настраивать место назначения результата. Они также вызываются в контексте между репликами.

Каким должно быть значение axis?

Значение для каждой реплики, возвращаемое run, например потери для каждого примера, будет разделено между всеми репликами. Эта функция позволяет агрегировать значения между репликами и, при необходимости, между элементами пакета, задав соответствующее значение параметра axis.

Например, если глобальный размер пакета равен 8, а реплик две, значения для примеров [0, 1, 2, 3] будут находиться на реплике 0, а [4, 5, 6, 7] — на реплике 1. При использовании axis=None, reduce будет агрегировать значения только между репликами и вернёт [0+4, 1+5, 2+6, 3+7]. Это полезно, когда каждая реплика вычисляет скаляр или другое значение без измерения «пакет» (например, градиент или значение потерь).

strategy.reduce("sum", per_replica_result, axis=None)

Иногда требуется агрегировать значения и по всему глобальному пакету, и по всем репликам. Такое поведение можно получить, указав измерение пакета в качестве axis, обычно axis=0. В этом случае функция вернёт скаляр 0+1+2+3+4+5+6+7.

strategy.reduce("sum", per_replica_result, axis=0)

Если последний пакет неполный, необходимо указать axis, чтобы форма результата была одинаковой для всех реплик. Например, если последний пакет содержит 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 и от того, включено ли нетерпеливое выполнение, fn может вызываться один или несколько раз. Если fn аннотирована с помощью tf.function или tf.distribute.Strategy.run вызывается внутри tf.function (нетерпеливое выполнение по умолчанию отключено внутри tf.function), fn вызывается один раз для каждой реплики для создания графа TensorFlow, который затем повторно используется при выполнении с новыми входными данными. В противном случае, если нетерпеливое выполнение включено, 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 для выполнения all-reduce над значениями.

    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. Пример см. в руководстве по пользовательскому циклу обучения.

Что должно находиться внутри области действия, а что — за ее пределами?

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

  • Любая функция, создающая переменные, которые должны быть распределенными, должна вызываться в strategy.scope. Это можно сделать, вызвав функцию создания переменных непосредственно в контексте области действия или воспользовавшись другим API, например strategy.run или keras.Model.fit, который войдет в нее автоматически. Переменные, созданные за пределами области действия, не будут распределенными, что может сказаться на производительности. В TF переменные часто создают такие объекты, как модели, оптимизаторы и метрики. Такие объекты всегда следует инициализировать в области действия; функции, которые могут создавать переменные отложенно (например, Model.call(), трассировка tf.function и т. д.), также следует вызывать внутри области действия. Другой причиной создания переменных может быть восстановление из контрольной точки — если переменные создаются отложенно. Обратите внимание, что любая переменная, созданная внутри стратегии, сохраняет информацию о стратегии. Поэтому чтение и запись этих переменных за пределами strategy.scope также могут выполняться без проблем, и пользователю не нужно входить в область действия.
  • Некоторые API стратегии (например, strategy.run и strategy.reduce), требующие нахождения в области действия стратегии, входят в нее автоматически. Поэтому при использовании этих API не нужно явно входить в область действия.
  • Когда tf.keras.Model создается внутри strategy.scope, объект Model сохраняет информацию об области действия. При вызове высокоуровневых методов обучающей платформы, таких как model.compile, model.fit и т. д., сохраненная область действия будет активирована автоматически, а связанная с ней стратегия будет использоваться для распределенного обучения и т. д. Подробный пример см. в руководстве по распределенному обучению с помощью Keras. ПРЕДУПРЕЖДЕНИЕ: простой вызов model(..) не активирует сохраненную область действия автоматически — такое поведение поддерживают только высокоуровневые API обучающих платформ: model.compile, model.fit, model.evaluate, model.predict и model.save можно вызывать как внутри, так и за пределами области действия.
  • Следующие операции можно выполнять как внутри, так и за пределами области действия:
    • Создание входных наборов данных
    • Определение tf.function, представляющих шаг обучения
    • API сохранения, такие как tf.saved_model.save. При загрузке создаются переменные, поэтому ее следует выполнять внутри области действия, если вы хотите обучать модель распределенным способом.
    • Сохранение контрольных точек. Как упоминалось выше, checkpoint.restore иногда нужно выполнять внутри области действия, если при этом создаются переменные.
Возвращает
Менеджер контекста.

update_config_proto

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

update_config_proto(
    config_proto
)

Возвращает копию config_proto, измененную для использования с этой стратегией.

Устарело: Этот метод недоступен в TF 2.x.

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

Аргументы
config_proto объект tf.ConfigProto.
Возвращает
Обновленную копию config_proto.

© 2022 The TensorFlow Authors. All rights reserved.
Licensed under the Creative Commons Attribution License 4.0.
Code samples licensed under the Apache 2.0 License.
https://www.tensorflow.org/api_docs/python/tf/compat/v1/distribute/experimental/CentralStorageStrategy

Spec-Zone.ru

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