Spec-Zone.ru › TensorFlow

tf.compat.v1.distribute.Strategy

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

tf.compat.v1.distribute.Strategy(
    extended
)

См. руководство для обзора и примеров.

Примечание: Не все tf.distribute.Strategy реализации в настоящее время поддерживают разбиение переменных TensorFlow (где одна переменная разделена между несколькими устройствами).
Атрибуты
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, выполняемого на каждой реплике.

END_OF_DOCUMENT_MARKER

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

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

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, которые не относятся к указанным типам, не поддерживаются.

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

update_config_proto

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

update_config_proto(
    config_proto
)

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

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

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

Аргументы
config_proto Объект tf.ConfigProto.
Возвращаемое значение
Обновлённая копия 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/Strategy

Spec-Zone.ru

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