Re[12]: volatile bool vs std::atomic_flag vs std::atomic<bool>
От: B0FEE664  
Дата: 01.09.15 17:00
Оценка:
Здравствуйте, uzhas, Вы писали:

U>так вот же стандарт:

U>

U>29.3 Order and Consistency [atomics.order]
U>...
U>11 Atomic read-modify-write operations shall always read the last value (in the modification order) written
U>before the write associated with the read-modify-write operation.


Это они хорошо спрятали — аж в другом разделе. Но мой взгляд это прямо противоречит тому, что

29.3/(1.1) — memory_order_relaxed: no operation orders memory.

И каждый день — без права на ошибку...
Re[13]: volatile bool vs std::atomic_flag vs std::atomic<bool>
От: B0FEE664  
Дата: 01.09.15 17:02
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Вильямс походу не в курсе о получении актуального значения через release/acquire : http://stackoverflow.com/questions/8819095/concurrency-atomic-and-volatile-in-c11-memory-model

U>

U>In the absence of any additional synchronization, if one thread writes a value to ai then there is nothing that guarantees that another thread will see the value in any given time period. The standard specifies that it should be visible "in a reasonable period of time", but any given access may return a stale value.


Ниже он пишет:

The only way to guarantee you have the "latest" value is to use a read-modify-write operation such as exchange(), compare_exchange_strong() or fetch_add(). Read-modify-write operations have an additional constraint that they always operate on the "latest" value, so a sequence of ai.fetch_add(1) operations by a series of threads will return a sequence of values with no duplicates or gaps. In the absence of additional constraints, there's still no guarantee which threads will see which values though.

И каждый день — без права на ошибку...
Re[13]: volatile bool vs std::atomic_flag vs std::atomic<bool>
От: uzhas Ниоткуда  
Дата: 03.09.15 07:10
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Но мой взгляд это прямо противоречит тому, что


BFE>

BFE>29.3/(1.1) — memory_order_relaxed: no operation orders memory.


я не вижу противоречия, т.к. первая цитата о видимости, а вторая о переупорядочивании, а это разные вещи
Re[14]: volatile bool vs std::atomic_flag vs std::atomic<boo
От: uzhas Ниоткуда  
Дата: 03.09.15 07:12
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Ниже он пишет:

BFE>

BFE>The only way to guarantee you have the "latest" value is to use a read-modify-write operation such as exchange(), compare_exchange_strong() or fetch_add(). Read-modify-write operations have an additional constraint that they always operate on the "latest" value, so a sequence of ai.fetch_add(1) operations by a series of threads will return a sequence of values with no duplicates or gaps. In the absence of additional constraints, there's still no guarantee which threads will see which values though.


все правильно он пишет, тебя что-то здесь смущает?
Отредактировано 03.09.2015 9:12 uzhas . Предыдущая версия .
Re[15]: volatile bool vs std::atomic_flag vs std::atomic<bool>
От: B0FEE664  
Дата: 03.09.15 08:44
Оценка:
Здравствуйте, uzhas, Вы писали:

U>все правильно он пишет, тебе что-то здесь смущает?


Я до конца так и не разобрался, так что меня многое смущает. Например, ваша фраза:

Вильямс походу не в курсе о получении актуального значения через release/acquire

Что понимается под словосочетанием "актуальное значение"?
И каждый день — без права на ошибку...
Re[16]: volatile bool vs std::atomic_flag vs std::atomic<bool>
От: uzhas Ниоткуда  
Дата: 03.09.15 09:31
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Что понимается под словосочетанием "актуальное значение"?


the last value (in the modification order)

Re[17]: volatile bool vs std::atomic_flag vs std::atomic<bool>
От: B0FEE664  
Дата: 03.09.15 09:53
Оценка:
Здравствуйте, uzhas, Вы писали:

BFE>>Что понимается под словосочетанием "актуальное значение"?


U>

U>the last value (in the modification order)


Но ведь это last value не имеет никакого отношения ко времени, а имеет отношение только к некоторой последовательности. Т.е. полученное значение вовсе не обязано быть последним по времени. Так?
И каждый день — без права на ошибку...
Re[12]: volatile bool vs std::atomic_flag vs std::atomic<bool>
От: B0FEE664  
Дата: 03.09.15 11:16
Оценка:
Здравствуйте, watchmaker, Вы писали:

BFE>>то гарантии, что второй поток когда-либо выйдет из цикла нет.

BFE>>На практике такого не случается, однако это не значит, что такого не может быть согласно стандарту. Представьте себе платформу, где два процессора и где кэши этих процессоров согласуются специальными инструкциями, которые отсутствуют при relaxed операциях.

W>Не надо путать абстрактную машину C++ и реальное аппаратное обеспечение. Если рассмотреть такой компьютер, где для синхронизации нужны особые инструкции, то компилятор бы их всегда и использовал. Даже если в коде требуется лишь memory_order_relaxed. Использовал бы компилятор эти инструкции в частности из-за того, что в противном случае был бы нарушен тот самый пункт о конечности времени на распространение изменений.

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

Вот откуда следует, что писатели компилятора должны вставлять инструкции синхронизации для relaxed операций, если стандарт прямо говорит, что relaxed операции не являются операциями синхронизации?
Более того, для relaxed операций вообще не определён никакой порядок изменений (modification order), кроме sequenced before, который относится только с одной нитке.
И каждый день — без права на ошибку...
Re[13]: volatile bool vs std::atomic_flag vs std::atomic<bool>
От: watchmaker  
Дата: 04.09.15 19:22
Оценка:
Здравствуйте, B0FEE664, Вы писали:

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


BFE>Вот откуда следует, что писатели компилятора должны вставлять инструкции синхронизации для relaxed операций,

Из твоего описания процессора и из уже упомянутого §1.10/28. Если процессор требует ручного указания на распространения изменений из кеша, то компилятору придётся вставлять "инструкции по синхронизации кешей" после relaxed операций чтобы гарантировать что сделанные изменения когда-нибудь будут увидены другие процессорами.
При этом, например, оптимизирующему компилятору разрешено вставлять лишь одну "инструкцию по синхронизации кешей" для блока идущих подряд relaxed операций над разными переменными, так что не придётся вызывать потенциально дорогую "инструкцию по синхронизации кешей" каждый раз. Так что не каждая атомарная операция обязана завершаться командой на распространение изменений из кеша. Но, разумеется, компилятор должен гарантировать, что между записью и началом распространения видимости пройдёт лишь «finite period of time», и поэтому он не сможет унести эту инструкцию слишком далеко.

Если ты знаком с x86, то там есть очень похожая ситуация с инструкциями non-temporal store. Их, конечно, никто не использует для атомарных операций (и без них на x86 с этим всё хорошо), но в остальном их поведение как раз очень похоже на поведение описанного тобой гипотетического компьютера. Если поток выполняет несколько операций non-temporal store, то процессор не только не гарантирует, что эти изменения увидятся другими процессорами в каком-то там порядке, но вообще не гарантирует, что эти изменения будут видимы другими процессорами. Разумеется до тех пор, пока записывающий процессор явно не исполнит инструкцию, которая сделает эти изменения видимыми другим (хотя, опять же не гарантируется порядок, в котором другие процессоры могут наблюдать эти изменения).
И если компилятор самостоятельно решает использовать non-temporal store, то после блока таких записей он вставляет инструкцию по синхронизации памяти (проверь с icc).
Так что не нужно переживать тут за relaxed atomic — если барьеры компилятором не вставляются, то значит с этой моделью памяти они и не нужны, а совсем не значит, что у компилятора с ними какие-то сложности. А там где требуется ручная синхронизация кеша и памяти, как видно на примере icc и non-temporal store, компилятор сам делает всё что нужно. И если будут переносить компилятор на такую гипотетическую машину, то просто заиспользуют повторно эту логику, но уже для более общего набора операций.

BFE>если стандарт прямо говорит, что relaxed операции не являются операциями синхронизации?

А это тут ни при чём.
Синхронизация, атомарность, видимость — это всё разные вещи, зачем их смешивать в одну кучу?


BFE>Более того, для relaxed операций вообще не определён никакой порядок изменений (modification order), кроме sequenced before, который относится только с одной нитке.

Верно. И на практике так бывает. В чём проблема-то? Именно это и позволяет на многих архитектурах реализовать атомарные операции эффективно. Во многих задачах (например, просигнализировать через одиночный булев флаг одному потоку из другого о том, что нужно начинать или заканчивать работу) эти ограничения на порядок видимости никак не влияют на корректность алгоритма. И поэтому быстроработающие relaxed операции использовать предпочтительнее в реализации таких алгоритмов.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.