tf.КритическаяСекция
| Просмотреть исходный код на GitHub |
Критическая секция.
tf.CriticalSection(
name=None, shared_name=None, critical_section_def=None, import_scope=None
)
Объект CriticalSection — это ресурс в графе, который выполняет подграфы в последовательном порядке. Типичный пример подграфа, который требуется выполнить исключительно, приведён в следующей функции:
v = resource_variable_ops.ResourceVariable(0.0, name="v")
def count():
value = v.read_value()
with tf.control_dependencies([value]):
with tf.control_dependencies([v.assign_add(1)]):
return tf.identity(value)
Здесь, моментальный снимок v сохраняется в value; затем v обновляется. Значение моментального снимка возвращается.
Если несколько рабочих процессов или потоков выполняют count параллельно, нет гарантии, что доступ к переменной v будет атомарным в любой момент во время вычисления count в любом потоке. Фактически, даже реализация атомарного счётчика, гарантирующего, что пользователь увидит каждое значение 0, 1, ...,, в настоящее время невозможна.
Решение заключается в обеспечении того, чтобы любой доступ к базовому ресурсу v обрабатывался только через критическую секцию:
cs = CriticalSection() f1 = cs.execute(count) f2 = cs.execute(count) output = f1 + f2 session.run(output)
Функции f1 и f2 будут выполняться последовательно, а обновления v будут атомарными.
ПРИМЕЧАНИЯ
Все объекты ресурсов, включая критическую секцию и любые захваченные переменные функций, выполняемых в этой критической секции, будут размещены на одном устройстве (хост и cpu/gpu).
При использовании нескольких критических секций для одних и тех же ресурсов нет гарантии исключительного доступа к этим ресурсам. Это поведение по умолчанию запрещено (но см. аргумент exclusive_resource_access).
Например, выполнение одной и той же функции в двух отдельных критических секциях не обеспечит последовательное выполнение:
v = tf.compat.v1.get_variable("v", initializer=0.0, use_resource=True)
def accumulate(up):
x = v.read_value()
with tf.control_dependencies([x]):
with tf.control_dependencies([v.assign_add(up)]):
return tf.identity(x)
ex1 = CriticalSection().execute(
accumulate, 1.0, exclusive_resource_access=False)
ex2 = CriticalSection().execute(
accumulate, 1.0, exclusive_resource_access=False)
bad_sum = ex1 + ex2
sess.run(v.initializer)
sess.run(bad_sum) # May return 0.0
| Атрибуты | |
|---|---|
name | |
Методы
execute
execute(
fn, exclusive_resource_access=True, name=None
)
Выполнение функции fn() внутри критической секции.
fn не должна принимать никаких аргументов. Чтобы добавить дополнительные аргументы при вызове fn в критической секции, создайте лямбда-функцию:
critical_section.execute(lambda: fn(*my_args, **my_kwargs))
| Аргументы | |
|---|---|
fn | Функция для выполнения. Должна возвращать по крайней мере один тензор. |
exclusive_resource_access | Нужно ли, чтобы ресурсы, необходимые для fn, были выделены только для этой CriticalSection. По умолчанию: True. Возможно, стоит установить значение в False, если вы будете получать доступ к ресурсу только для чтения в двух разных CriticalSection. |
name | Имя, которое следует использовать при создании операции выполнения. |
| Возвращаемые значения | |
|---|---|
Тензоры, возвращённые из fn(). |
| Исключения | |
|---|---|
ValueError | Если fn пытается заблокировать эту CriticalSection каким-либо вложенным или ленивым способом, который может привести к тупику. |
ValueError | Если у exclusive_resource_access == True и другой CriticalSection есть запрос на выполнение, требующий тех же ресурсов, что и fn. Note, even ifexclusive_resource_accessisTrue, if another execution in anotherCriticalSectionwas created withoutexclusive_resource_access=True, aValueError` будет поднято. |
© 2020 The TensorFlow Authors. All rights reserved.
Licensed under the Creative Commons Attribution License 3.0.
Code samples licensed under the Apache 2.0 License.
https://www.tensorflow.org/versions/r2.4/api_docs/python/tf/CriticalSection