Spec-Zone.ru › TensorFlow

tf.compat.v1.distribute.OneDeviceStrategy

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

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

tf.compat.v1.distribute.OneDeviceStrategy(
    device
)

Использование этой стратегии разместит все созданные в её области видимости переменные на указанном устройстве. Входные данные, распределённые через эту стратегию, будут предварительно загружены на указанное устройство. Кроме того, любые функции, вызываемые через strategy.run, также будут размещены на указанном устройстве.

Типичное использование этой стратегии — тестирование вашего кода с API tf.distribute.Strategy перед переходом к другим стратегиям, которые фактически распределяют вычисления по нескольким устройствам/машинам.

Например:

tf.enable_eager_execution()
strategy = tf.distribute.OneDeviceStrategy(device="/gpu:0")

with strategy.scope():
  v = tf.Variable(1.0)
  print(v.device)  # /job:localhost/replica:0/task:0/device:GPU:0

def step_fn(x):
  return x * 2

result = 0
for i in range(10):
  result += strategy.run(step_fn, args=(i,))
print(result)  # 90
Аргументы
device Идентификатор строки устройства, на котором должны быть размещены переменные. См. документацию класса для получения более подробной информации о том, как используется устройство. Примеры: "/cpu:0", "/gpu:0", "/device:CPU:0", "/device:GPU:0"
Атрибуты
cluster_resolver Возвращает решатель кластера, связанный с этой стратегией.

В общем случае, при использовании многоузловой 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(), 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 и 2-мя графическими процессорами:

strategy = tf.distribute.MirroredStrategy(devices=["GPU:0", "GPU:1"])
def step_fn():
  i = tf.distribute.get_replica_context().replica_id_in_sync_group
  return tf.identity(i)

per_replica_result = strategy.run(step_fn)
# Check devices on which per replica result is:
strategy.experimental_local_results(per_replica_result)[0].device
# /job:localhost/replica:0/task:0/device:GPU:0
strategy.experimental_local_results(per_replica_result)[1].device
# /job:localhost/replica:0/task:0/device:GPU:1

total = strategy.reduce("SUM", per_replica_result, axis=None)
# Check device on which reduced result is:
total.device
# /job:localhost/replica:0/task:0/device:CPU:0

Этот API обычно используется для агрегирования результатов, возвращаемых различными репликами, для отчётов и т. д. Например, вычисленная потеря с разных реплик может быть усреднена с помощью этого API перед печатью.

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

Существует ряд различных API tf.distribute для сокращения значений по репликам:

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

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

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

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

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

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

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

Если есть последний частичный пакет, вам нужно указать ось, чтобы форма результата была согласованной между репликами. Так, если последний пакет имеет размер 6 и разделён на [0, 1, 2, 3] и [4, 5], у вас будет несоответствие формы, если не указать axis=0. Если вы укажете tf.distribute.ReduceOp.MEAN, используя axis=0, будет использоваться правильный знаменатель 6. В отличие от вычисления reduce_mean, чтобы получить скалярное значение на каждой реплике, и этой функции для усреднения этих средних значений, что будет взвешивать некоторые значения 1/8, а другие 1/4.

Аргументы
reduce_op Значение tf.distribute.ReduceOp, указывающее, как следует комбинировать значения. Разрешает использование строкового представления перечисления, например "SUM", "MEAN".
value Объект tf.distribute.DistributedValues, например, возвращаемый Strategy.run, который нужно объединить в один тензор. Он также может быть обычным тензором при использовании с OneDeviceStrategy или стратегией по умолчанию.
axis Указывает размерность для сокращения вдоль тензора каждой реплики. Обычно следует устанавливать в размерность пакета или None, чтобы сокращать только по репликам (например, если тензор не имеет размерности пакета).
Возвращаемое значение
Объект Tensor.

run

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

run(
    fn, args=(), kwargs=None, options=None
)

Вызывает fn на каждой реплике с заданными аргументами.

Этот метод является основным способом распределения вычислений с объектом tf.distribute. Он вызывает fn на каждой реплике. Если args или kwargs имеют tf.distribute.DistributedValues, такие как те, которые создаются tf.distribute.DistributedDataset из tf.distribute.Strategy.experimental_distribute_dataset или tf.distribute.Strategy.distribute_datasets_from_function, когда fn выполняется на конкретной реплике, она будет выполняться с компонентом tf.distribute.DistributedValues, соответствующим этой реплике.

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

Все аргументы в args или kwargs могут быть вложенной структурой тензоров, например списком тензоров, в этом случае args и kwargs будут переданы в вызываемую fn на каждой реплике. Или args или kwargs могут быть tf.distribute.DistributedValues содержащими тензоры или составные тензоры, т. е. tf.compat.v1.TensorInfo.CompositeTensor, в этом случае каждый вызов fn получит компонент tf.distribute.DistributedValues, соответствующий его реплике. Обратите внимание, что произвольные значения Python, которые не являются перечисленными выше типов, не поддерживаются.

END_OF_DOCUMENT_MARKER
Важно: В зависимости от реализации 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 для allreduce значений.

    strategy = tf.distribute.MirroredStrategy(["gpu:0", "gpu:1"])
    @tf.function
    def run():
       def value_fn(value_context):
         return tf.constant(value_context.replica_id_in_sync_group)
       distributed_values = (
           strategy.experimental_distribute_values_from_function(
               value_fn))
       def replica_fn(input):
         return tf.distribute.get_replica_context().all_reduce(
             "sum", input)
       return strategy.run(replica_fn, args=(distributed_values,))
    result = run()
    result
        PerReplica:{
          0: <tf.Tensor: shape=(), dtype=int32, numpy=1>,
          1: <tf.Tensor: shape=(), dtype=int32, numpy=1>
        }
        
Аргументы
fn Функция, которая будет выполняться на каждой реплике.
args Необязательные позиционные аргументы для fn. Его элементы могут быть тензором, вложенной структурой тензоров или tf.distribute.DistributedValues.
kwargs Необязательные именованные аргументы для fn. Его элементы могут быть тензором, вложенной структурой тензоров или tf.distribute.DistributedValues.
options Необязательный экземпляр tf.distribute.RunOptions, задающий параметры для запуска fn.
Возвращаемое значение
Объединенное возвращаемое значение fn по всем репликам. Структура возвращаемого значения совпадает со структурой возвращаемого значения от fn. Каждый элемент в структуре может быть tf.distribute.DistributedValues, объектами Tensor или тензорами Tensor (например, при запуске на одной реплике).

scope

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

scope()

Менеджер контекста для установки стратегии в текущее состояние и распределения переменных.

Этот метод возвращает менеджер контекста и используется следующим образом:

strategy = tf.distribute.MirroredStrategy(["GPU:0", "GPU:1"])
# Variable created inside scope:
with strategy.scope():
  mirrored_variable = tf.Variable(1.)
mirrored_variable
MirroredVariable:{
  0: <tf.Variable 'Variable:0' shape=() dtype=float32, numpy=1.0>,
  1: <tf.Variable 'Variable/replica_1:0' shape=() dtype=float32, numpy=1.0>
}
# Variable created outside scope:
regular_variable = tf.Variable(1.)
regular_variable
<tf.Variable 'Variable:0' shape=() dtype=float32, numpy=1.0>

Что происходит при входе в область действия Strategy.scope?

  • strategy устанавливается в глобальном контексте в качестве "текущей" стратегии. Внутри этой области действия, tf.distribute.get_strategy() теперь вернет эту стратегию. Вне этой области действия, он возвращает стратегию по умолчанию (без действий).
  • Вход в область действия также входит в "межрепликационный контекст". Смотрите tf.distribute.StrategyExtended для объяснения межрепликационных и реплицированных контекстов.
  • Создание переменных внутри scope перехватывается стратегией. Каждая стратегия определяет, как она должна влиять на создание переменных. Синхронные стратегии, такие как MirroredStrategy, TPUStrategy и MultiWorkerMiroredStrategy, создают переменные, дублированные на каждой реплике, в то время как ParameterServerStrategy создаёт переменные на серверах параметров. Это делается с помощью пользовательского tf.variable_creator_scope.
  • В некоторых стратегиях также может быть введена область действия по умолчанию устройства: в MultiWorkerMiroredStrategy вводится область действия устройства по умолчанию "/CPU:0" на каждом рабочем узле.
Примечание: Вход в область действия не автоматически распределяет вычисление, за исключением случаев использования высокоуровневых обучающих фреймворков, таких как keras model.fit. Если вы не используете model.fit, необходимо использовать API strategy.run, чтобы явно распределить это вычисление. Смотрите пример в учебнике по пользовательскому циклу обучения.

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

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

  • Любые операции, создающие переменные, которые должны быть распределенными переменными, должны вызываться в strategy.scope. Это можно сделать, либо непосредственно вызвав функцию создания переменных внутри контекста области действия, либо используя другой API, например, strategy.run или keras.Model.fit, чтобы он автоматически вошёл в неё для вас. Любые переменные, созданные вне области действия, не будут распределены и могут повлиять на производительность. Объекты, которые часто создают переменные в TF, — это Models, Optimizers, Metrics. Такие объекты всегда должны инициализироваться в области действия, и любые функции, которые могут создавать переменные лениво (например, 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/OneDeviceStrategy

Spec-Zone.ru

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