Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.69/13: Рейтинг темы: голосов - 13, средняя оценка - 4.69
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700

Гарантирует ли стандарт атомарное чтение и запись данных, размер которого не более чем машинное слово?

02.03.2018, 22:16. Показов 3569. Ответов 61
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Насколько я знаю атомарность для чтения и записи данных которые не более чем одно машинное слово, гарантируется на уровне процессора. А со стороны стандарта с++ есть подобные гарантии? Тут речь не про std::atomic, а именно про обычные переменные.
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
02.03.2018, 22:16
Ответы с готовыми решениями:

Найти минимальный элемент, двоичная запись которого заканчивается не более чем двумя нулями
25 задача ЕГЭ Здравствуйте. Дан массив, содержащий 2020 положительных целых чисел, не превышающих 15 000. Необходимо найти...

Вывести слово минимальное по величине столько раз, сколько букв в первом слове, если это слово более чем из
Вывести слово минимальное по величине столько раз, сколько букв в первом слове, если это слово более чем из трех букв. В противном случае...

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

61
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
09.03.2018, 19:04  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от SeqInconsistent Посмотреть сообщение
Ты же понимаешь это как "acquire синхронизируется с release и читает значение".
Ага, только наоборот
Цитата Сообщение от Undisputed Посмотреть сообщение
Атомарная операция store с освобождением (memory_order_release), синхронизируется с загрузкой acquire (memory_order_acquire), которая получает значение, сохраненное при помощи store операции.
Цитата Сообщение от SeqInconsistent Посмотреть сообщение
"and takes its value" — это именно условие синхронизации, что значение должно быть прочитано, чтобы произошла синхронизация.
Перед чтением значения должна произойти синхронизация (а не наоборот), что бы можно было получить значение, сохраненное store-операцией... Иначе сначала было бы чтение, а потом синхронизация и load-acquire получало было не последнее значение на момент чтения, и разницы между load-acquire и load с memory_order_relaxed особо бы и не было. Там даже порядок указан: сначала синхронизация, а потом получение значения.
Цитата Сообщение от SeqInconsistent Посмотреть сообщение
An atomic operation A that performs a release operation on an atomic object M (Шаг №1) -> synchronizes with an atomic operation B that performs an acquire operation on M (Шаг №2) -> and takes its value from any side effect in the release sequence headed by A.
Цитата Сообщение от SeqInconsistent Посмотреть сообщение
Это говорит, что для синхронизации с release operation A надо прочитать либо само значение, записанное операцией, либо любое из последующих в release sequence.
Ядро которое читает одно из изменившихся значений получит соответствующее сообщение и при необходимости может запустить механизм синхронизации для получения этого значения. Вот и все.

Цитата Сообщение от SeqInconsistent Посмотреть сообщение
Зачем написано про любое значение из release sequence, если у нас якобы есть гарантия, что load-acquire (с memory_order ≠ seq_cst) гарантированно читает последнее значение из modification order?
Любое, потому что все операции записи идущие ДО release барьера будут выполнены еще до того как произойдет этот store-release который мы вызываем для атомика, и все эти данные будут сброшены в кэш ядра, которое исполняет этот самый поток. Соответственно читающее ядро получит сообщение об изменении данных, и при необходимости может запустить механизм синхронизации кэшей и прочитать требуемое значение.

Цитата Сообщение от Evg Посмотреть сообщение
В случаях, когда аппаратура позволяет строить обращения по невыровненному адресу (как это имеет место быть на intel'овской системе команд), обычно такие невыровненные обращения НЕ являются атомарными из-за особенностей работы контроллеров памяти.
Да, про требование выравнивания я прочитал после того как опубликовал эту тему.
Цитата Сообщение от Evg Посмотреть сообщение
Просто чисто логически размышляя, стандарт такого не гарантирует, в противном случае не нужно было бы в стандарты вводить std::atomic и прочее
Почему бы и нет. Сам std::atomic ещё хорош тем что он шаблонный и операции над разными объектами (и даже теми, которые превышают размер машинного слова) можно производить атомарно. Просто для пользовательских типов с большим размером как правило вместо атомарных операций процессорного уровня применяется мьютекс.
0
6 / 6 / 2
Регистрация: 27.08.2017
Сообщений: 28
09.03.2018, 19:25
Цитата Сообщение от Undisputed Посмотреть сообщение
Перед чтением значения должна произойти синхронизация (а не наоборот)
Нет никаких "перед". Это одно и то же.
Цитата Сообщение от http://eel.is/c++draft/intro.multithread#intro.races-19.note-1
The value observed by a load of an atomic depends on the “happens before” relation, which depends on the values observed by loads of atomics.
Цитата Сообщение от Undisputed Посмотреть сообщение
An atomic operation A that performs a release operation on an atomic object M (Шаг №1) -> synchronizes with an atomic operation B that performs an acquire operation on M
Ок, давай про Шаг №1. С какой acquire operation синхронизируется release?

Цитата Сообщение от Undisputed Посмотреть сообщение
Ядро которое
Ядер в определении синхронизации тоже никаких нет, как и "перед".

Цитата Сообщение от Undisputed Посмотреть сообщение
Любое, потому что все операции записи идущие ДО release барьера
При чём тут операции до release? Ты точно понимаешь, что такое release sequence?
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
09.03.2018, 20:24  [ТС]
Цитата Сообщение от SeqInconsistent Посмотреть сообщение
Ядер в определении синхронизации тоже никаких нет, как и "перед".
Ага, про ядра в стандарте нет и быть по идее не должно т.к стандарт абстрагирует читателей от машинных деталей на которых и основаны гарантии стандарта. Я говорю про машинные детали.

Цитата Сообщение от SeqInconsistent Посмотреть сообщение
Ты точно понимаешь, что такое release sequence?
Да, понимаю.

В общем случае есть 2 варианта получить значение той или иной переменной из release sequence:
1. Не запускать явную синхронизацию. В таком случае ядро на котором исполняется читающий поток получит измененное значение тогда, когда это ядро "посчитает нужным" забрать его из кэша писателя.
2. Запуск явной синхронизации перед чтением и получение последнего значения.
Выбрать конкретную стратегию позволяют memory_order_*

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

Цитата Сообщение от SeqInconsistent Посмотреть сообщение
Ок, давай про Шаг №1. С какой acquire operation синхронизируется release?
С той, которая была применена в последний раз (при условии, что ядро выполняющее load-acquire получило сообщение о том, что писатель сделал store-release. Это сообщение как правило отправляется сразу после выполнения release).

Цитата Сообщение от Undisputed Посмотреть сообщение
Просто для пользовательских типов с большим размером как правило вместо атомарных операций процессорного уровня применяется мьютекс.
Правильнее было бы сказать, если компилятор не может сгенерировать код с использованием атомарных операций процессорного уровня для конкретного типа T, то будет использован mutex.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//g++  5.4.0
 
#include <iostream>
#include <atomic>
#include <iomanip>
 
class Foo
{
    int n;
};
 
class Baz
{
    long double n1 = 20;
    long long n2;
};
 
int main()
{ 
    std::atomic<Foo> data1;
    std::cout << std::boolalpha << data1.is_lock_free() << '\n';//true
    
    std::atomic<Baz> data2;
    std::cout << data2.is_lock_free() << '\n';//false
    
}
http://rextester.com/ORHV42063
0
6 / 6 / 2
Регистрация: 27.08.2017
Сообщений: 28
09.03.2018, 21:02
Цитата Сообщение от Undisputed Посмотреть сообщение
В общем случае есть 2 варианта получить значение той или иной переменной из release sequence:
ШТО???

Перечитай ещё раз определение http://eel.is/c++draft/intro.r... e_sequence.
release sequence это определённым образом сформированная подпоследовательность из последовательности модификаций для одного атомарного объекта M.

Как из последовательности модификаций одного объекта (переменной) достать значение той или иной переменной?

Цитата Сообщение от Undisputed Посмотреть сообщение
Да, понимаю.
Ага.

Цитата Сообщение от Undisputed Посмотреть сообщение
С той, которая была применена в последний раз
Я ждал этих слов! "(синхронизируется) С той, которая была применена в последний раз" означает, что есть какой-то глобальный порядок операций, который установлен до установления соотношения синхронизации. Иначе как синхронизироваться с последней операцией, не зная предварительно, какая последняя?
Но такой порядок гарантируется для memory_order_seq_cst, а для memory_order_release/acquire нет понятия "(операция) применена в последний раз".

Цитата Сообщение от Undisputed Посмотреть сообщение
То о чем ты говоришь больше похоже на load с memory_order_relaxed
Ну, или на то, что memory_order_relaxed ты "понимаешь" так же, как release sequence.
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
09.03.2018, 21:27
Мало ли, вдруг кому-то пригодится
Std::atomic. Реализация свободного от блокировок стека
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
10.03.2018, 00:00  [ТС]
Цитата Сообщение от SeqInconsistent Посмотреть сообщение
release sequence это определённым образом сформированная подпоследовательность из последовательности модификаций для одного атомарного объекта M.
Да, ты прав относительно release sequence, извиняюсь, я был не прав и перепутал.
У меня в голове почему-то крутился пример только с двумя потоками, где один писатель, а другой читатель.
Говоря про release sequence, имеется ввиду порядок модификации одной и той же атомарной переменной несколькими потоками. Надеюсь теперь мы на одной волне относительно release sequence?

Если так, тогда вернемся к load-acquire.

Теперь попробую описать то, почему я считаю что будет прочитано последнее значение и то, что вообще подразумевается под последним значением. Сначала определимся с тем, что все атомарные процессорные инструкции сопровождаются блокировкой на процессорном уровне.
https://ru.wikipedia.org/wiki/... 0%B8%D1%8F

Это означает, что с данными над которыми производится атомарная процессорная инструкция, в один момент может работать только один поток.

Ты задал вопрос, с каким release-store будет синхронизировано load-acquire. В общем мой ответ таков:
Допустим есть три потока, где два писателя и один читатель.
A и B - писатели, C - читатель и все они предположим что работают с одной и той же атомарной переменной std::atomic.

Потоки A и B пишут некоторое значение в атомарную переменную в определенном порядке. Среди них насколько я знаю - кто первый встал, того и тапки (тот первый захватит лок и запишет свое значение). Но тут возникает вопрос, какое из этих значений будет читать поток C. Ты ведь этот вопрос мне задавал?

Для читающего ядра последним значением я считаю то значение, от которого читатель в последний раз получит сообщение "я записал новое значение". Если поток С запросит чтение сразу после того как поток A запишет свое значение, то он будет синхронизирован с тем что записал поток А. Если же поток С запросит чтение после того как поток B сделает операцию чтения, то поток С будет синхронизирован с значением, записанным потоком B.

Проще говоря, при использовании load-acquire поток пытается прочитать максимально новое (последнее) значение. Каким будет читаемое значение зависит от того, кто и когда будет выполнять свои операции

Вот код, при помощи которого я проводил тесты:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include <atomic>
#include <thread>
 
std::atomic<int> data = ATOMIC_FLAG_INIT;
 
void a()
{
    data.store(1, std::memory_order_release);
}
 
void b()
{
    data.store(2, std::memory_order_release);
}
 
void c()
{
    while (1) {
        int n = data.load(std::memory_order_acquire);
        std::cout << n << ' ';
        if (n == 2) break;
    }
    std::cout << '\n';
}
 
int main()
{
    std::thread tC(c);
    std::thread tA(a);
    std::thread tB(b);
    
    tC.join();
    tA.join();
    tB.join();
}
Значения, полученные в результате запуска - разные. При этом явно видно, что читатель пытается получить максимально новое значение.
Ниже несколько результатов выполнения:
0 1 2
0 1 1 1 2
0 2 //!!!
Обрати внимание на последний результат. Значение, записанное потоком А - отсутствует в читателе.

Есть ли у тебя ещё вопросы, или контрпримеры?
...

Добавлено через 23 минуты
Ниже немного измененный пример. Добавил sleep на 2 секунды в читателе перед load операцией.
За 2 секунды думаю оба потока успеют записать свои значения.
Как результат - мы всегда видим только одно значение.
То есть в результате load-acquire мы прочитали то, что было записано последним.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <atomic>
#include <thread>
#include <chrono>
 
std::atomic<int> data = ATOMIC_FLAG_INIT;
 
void a()
{
    data.store(1, std::memory_order_release);
}
 
void b()
{
    data.store(2, std::memory_order_release);
}
 
void c()
{
    while (1) {
        std::this_thread::sleep_for(std::chrono::seconds(2));
        int n = data.load(std::memory_order_acquire);
        std::cout << n << ' ';
    }
    std::cout << '\n';
}
 
int main()
{
    std::thread tC(c);
    std::thread tA(a);
    std::thread tB(b);
    
    tC.join();
    tA.join();
    tB.join();
}
0
6 / 6 / 2
Регистрация: 27.08.2017
Сообщений: 28
10.03.2018, 00:02
Цитата Сообщение от Undisputed Посмотреть сообщение
Надеюсь теперь мы на одной волне относительно release sequence?
Если так, тогда вернемся к load-acquire.
Да, давай вернёмся к load-acquire. И её взаимодействию с release sequence

А именно:
Цитата Сообщение от http://eel.is/c++draft/atomics#order-2
An atomic operation A that performs a release operation on an atomic object M synchronizes with an atomic operation B that performs an acquire operation on M and takes its value from any side effect in the release sequence headed by A.
Ты утверждаешь, что load-acquire всегда читает последнее значение из modification order.
Как ты тогда ответишь на вопрос, зачем стандарт пишет про получение любого значения из release sequence? Любое-то может быть и не последним...

Цитата Сообщение от Undisputed Посмотреть сообщение
Теперь попробую описать то, почему я считаю что будет прочитано последнее значение и то, что вообще подразумевается под последним значением. Сначала определимся с тем, что все атомарные процессорные инструкции сопровождаются блокировкой на процессорном уровне.
Для того, чтобы показать, что RMW-атомик-операции читают последнее значение из modification order, не нужно определяться с блокировками на процессорном уровне. Это явно написано.
Для того, чтобы показать, что операции над мьютексом происходят в едином для всех потоков порядке и лок мьютекса синхронизируется с последним анлоком (или наоборот, если угодно), не нужно определяться с блокировками на процессорном уровне. Это явно написано.
Что memory_order_seq_cst получает последнее значение, тоже более-менее понятно: там все операции глобально упорядочены и этот порядок согласован с modification order (т.е. последняя операция записи соответствует последнему значению в modification order и т.д.). load читает значение, записанное последним release из глобального порядка, а, значит, это будет последнее значение из modification order. И тут не нужны никакие "сначала определимся"!

А почему для того, чтобы убедиться в том, что load-acquire (с mem. order != seq_cst) видит последнее значение, я должен определяться с блокировками на процессорном уровне? При том, что некоторые словоупотребления в стандарте, типа того, что я привёл выше, говорят явно против "последнего значения".

Цитата Сообщение от Undisputed Посмотреть сообщение
При этом явно видно
Каким образом это видно изнутри самой C++-программы???

Цитата Сообщение от Undisputed Посмотреть сообщение
Обрати внимание на последний результат.
И что это мне должно сказать?

Цитата Сообщение от Undisputed Посмотреть сообщение
Есть ли у тебя ещё вопросы, или контрпримеры?
Ха-ха-ха-ха... Прикольный тон ))

Добавлено через 1 минуту
Цитата Сообщение от Undisputed Посмотреть сообщение
Как результат - мы всегда видим только одно значение.
А можно одним чтением увидеть более одного значения атомарной переменной?
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
10.03.2018, 00:44  [ТС]
Цитата Сообщение от SeqInconsistent Посмотреть сообщение
takes its value from any side effect in the release sequence
Только ты не уточнил, чем именно здесь является side effect.
Мне вот интересно, что здесь есть side effect? Вопрос возникает потому, что есть другие варианты.

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

Цитата Сообщение от SeqInconsistent Посмотреть сообщение
И что это мне должно сказать?
Я просто хотел показать, что процесс синхронизации пытается получить именно что самое свежее значение.

Цитата Сообщение от SeqInconsistent Посмотреть сообщение
А можно одним чтением увидеть более одного значения атомарной переменной?
Смешно... )) В примере вызовы load повторяются...

Цитата Сообщение от SeqInconsistent Посмотреть сообщение
Ха-ха-ха-ха... Прикольный тон ))
Рад что тебе понравилось )
0
6 / 6 / 2
Регистрация: 27.08.2017
Сообщений: 28
10.03.2018, 00:50
Цитата Сообщение от Undisputed Посмотреть сообщение
Вопрос возникает потому, что есть другие варианты.
Озвучивай.

Цитата Сообщение от Undisputed Посмотреть сообщение
Я просто хотел показать, что процесс синхронизации пытается получить именно что самое свежее значение.
И как последний результат это показывает?
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
10.03.2018, 01:04  [ТС]
Цитата Сообщение от SeqInconsistent Посмотреть сообщение
Озвучивай.
Думаю сейчас не нужно отвлекаться на эти вещи. Сначала ты озвучь что ты понимаешь под side effects в данном случае )
Вдруг мне даже не придется говорить об этом, зависит от твоего ответа т.к я не уверен, есть просто некоторые подозрения...
Обрати внимание, в том предложении упомянуто два разных понятия:
1. release sequence
2. side effects
Где стандарт определяет чем является side effects в данном контексте и почему по твоему нельзя было просто обойтись выражением release sequence?

Цитата Сообщение от SeqInconsistent Посмотреть сообщение
И как последний результат это показывает?
Перед load в читателе я поставил sleep на 2 секунды. Думаю за 2 секунды оба писателя успели сохранить свои значения.
Далее load операция всегда извлекает одно и то же значение не смотря на то, что перед load было две операции сохранения. Разве это не говорит о том, что произошла синхронизация, в результате которой было принято одно значение (последнее). Если это не так, то почему?
0
6 / 6 / 2
Регистрация: 27.08.2017
Сообщений: 28
10.03.2018, 01:40
Цитата Сообщение от Undisputed Посмотреть сообщение
Сначала ты озвучь что ты понимаешь под side effects в данном случае
Я понимаю то, что понимается под side effect-ами стандартом: http://eel.is/c++draft/intro.e... de_effects

Цитата Сообщение от Undisputed Посмотреть сообщение
Обрати внимание, в том предложении упомянуто два разных понятия:
1. release sequence
2. side effects
Там упомянуто даже больше двух разных понятий: как минимум ещё "atomic/release/acquire operation", "atomic object", "synchronizes with" в дополнение к тому, что перечислил ты.

Цитата Сообщение от Undisputed Посмотреть сообщение
Где стандарт определяет чем является side effects в данном контексте
http://eel.is/c++draft/intro.e... de_effects

Цитата Сообщение от Undisputed Посмотреть сообщение
почему по твоему нельзя было просто обойтись выражением release sequence?
Меня подобные вопросы ставят в ступор. Ты можешь спросить что-то более содержательное?
А пока на подобный вопрос я могу дать такой ответ: комитет данным предложением хотел сказать что-то, для чего нельзя было обойтись выражением release sequence, т.к. иначе не получилось бы сказать то, что хотели сказать, а получилось бы сказать то, что не хотели.
Могу ещё такой дать: потому что если выкинуть "side effects" — An atomic operation A that performs a release operation on an atomic object M synchronizes with an atomic operation B that performs an acquire operation on M and takes its value from any side effect in the release sequence headed by A — то как-то не звучит.

Цитата Сообщение от Undisputed Посмотреть сообщение
Думаю за 2 секунды оба писателя успели сохранить свои значения.
Возможно.

Цитата Сообщение от Undisputed Посмотреть сообщение
Далее load операция всегда извлекает одно и то же значение не смотря на то, что перед load было две операции сохранения.
load из одной атомарной переменной в одном и том же потоке вполне может читать не-последнее значение из modification order сколько угодно раз подряд. Это допустимо стандартом.

Цитата Сообщение от Undisputed Посмотреть сообщение
Разве это не говорит о том, что произошла синхронизация, в результате которой было принято одно значение (последнее).
Даже если получено последнее значение, как это противоречит тому, что нет гарантии получения последнего значения? Ты путаешь "нет гарантии чтения последнего значения" с "есть гарантия не-получения последнего значения"?
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
10.03.2018, 02:10  [ТС]
Цитата Сообщение от SeqInconsistent Посмотреть сообщение
то как-то не звучит.
Вот об этом я думал, но так и не нашел этому оправдания Можно было бы донести эту мысль без слов side effects...

Цитата Сообщение от SeqInconsistent Посмотреть сообщение
Я понимаю то, что понимается под side effect-ами стандартом:
Насколько я понял тут речь идет о том, что если сохранение атомарной переменной при release имеет какие либо побочные эффекты, то на момент чтения этой переменной при помощи load-acquire все эти сайд эффекты будут завершены... А какие конкретно будут сайд эффекты, видимо зависит от сохраняемых данных...


Цитата Сообщение от SeqInconsistent Посмотреть сообщение
load из одной атомарной переменной в одном и том же потоке вполне может читать не-последнее значение из modification order сколько угодно раз подряд. Это допустимо стандартом.
Если даже допустимо, то все равно 2 секунды для двух операций сохранения это очень много.
И тут скорее всего происходит именно чтение данных из последней записи...

Цитата Сообщение от SeqInconsistent Посмотреть сообщение
Даже если получено последнее значение, как это противоречит тому, что нет гарантии получения последнего значения? Ты путаешь "нет гарантии чтения последнего значения" с "есть гарантия не-получения последнего значения"?
Я не о противоречиях сейчас говорю, а про то что процесс синхронизации как правило пытается взять наиболее свежее значение что и заметно на практике. Иначе толк от синхронизации был бы сомнительным...
0
6 / 6 / 2
Регистрация: 27.08.2017
Сообщений: 28
10.03.2018, 02:28
Цитата Сообщение от Undisputed Посмотреть сообщение
Можно было бы донести эту мысль без слов side effects...
Какую "эту" мысль?

Цитата Сообщение от Undisputed Посмотреть сообщение
Насколько я понял тут речь идет о том, что если сохранение атомарной переменной при release имеет какие либо побочные эффекты, то на момент чтения их при помощи load-acquire все эти сайд эффекты будут завершены...
Там идёт речь о side-эффекте из release sequence.
Мне показалось, мы уже выяснили, что такое release sequence и что она относится к последовательности модификаций атомарного объекта M. Видимо, только показалось.

Цитата Сообщение от Undisputed Посмотреть сообщение
2 секунды для двух операций сохранения это очень много.
define "очень много".

Цитата Сообщение от Undisputed Посмотреть сообщение
скорее всего происходит именно чтение данных из последней записи
Скорее всего, но гарантий нет и как кодом или допущениями о блокировках процессоров можно доказать, что они есть — я до сих пор не пойму.

Цитата Сообщение от Undisputed Посмотреть сообщение
процесс синхронизации как правило пытается взять наиболее свежее значение что и заметно на практике
Может и пытается, но ему никто ничего не обещает, так-то.

Цитата Сообщение от Undisputed Посмотреть сообщение
Иначе толк от синхронизации был бы сомнительным...
Гм. А зачем вообще нужны release/acquire memory order, если у нас есть seq_cst, который весь из себя наиболее свежий?
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
10.03.2018, 02:45  [ТС]
Цитата Сообщение от SeqInconsistent Посмотреть сообщение
Там идёт речь о side-эффекте из release sequence.
Я думаю мысль там такова: store-release синхронизируется с load-acquire, и для читаемого значение потока на момент получения данных любые сайд эффекты сохранения этого значения считаются завершенными (если они были).
То есть если в release sequence было несколько сайд эффектов (например по одному сайд эффекту на каждый store), то читатель увидит действие всех этих побочных эффектов.

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

Цитата Сообщение от SeqInconsistent Посмотреть сообщение
А зачем вообще нужны release/acquire memory order, если у нас есть seq_cst, который весь из себя наиболее свежий?
Ну у каждого типа синхронизации есть свои эффекты. seq_cst требует больше ресурсов для синхронизации т.к является полным барьером. А полные барьеры не всегда нужны. Зачастую достаточно того что предлагает acquire/release семантика.
Так программа работает быстрее т.к нет полных барьеров
0
6 / 6 / 2
Регистрация: 27.08.2017
Сообщений: 28
10.03.2018, 02:54
Цитата Сообщение от Undisputed Посмотреть сообщение
Слово any тут как я понял именно к сайд эффектам при сохранении (т.е любые сайд эффекты будут завершены на момент чтения).
Т.е. "takes its value from any side effect" переводится "любые сайд-эффекты будут завершены"?
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
10.03.2018, 02:58  [ТС]
SeqInconsistent,
Нет... "Берет его значение (его, всмысле store операции), с учётом любых сайд эффектов которые могут быть в release sequence". Я понял это именно так
0
6 / 6 / 2
Регистрация: 27.08.2017
Сообщений: 28
10.03.2018, 03:04
Цитата Сообщение от Undisputed Посмотреть сообщение
с учётом
А какое место там можно перевести как "с учётом"?

Цитата Сообщение от Undisputed Посмотреть сообщение
Я понял это именно так
А почему именно так, а не просто так, как явно написано?
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
10.03.2018, 03:25  [ТС]
SeqInconsistent,
Там any расположено именно что перед side effect, а не перед value...
Это означает что слово любое (any) тут относится именно к сайд эффектам а не к значению(value)....
0
6 / 6 / 2
Регистрация: 27.08.2017
Сообщений: 28
10.03.2018, 03:54
Undisputed, ок, я понял, ты прицепился к
Цитата Сообщение от SeqInconsistent Посмотреть сообщение
получение любого значения из release sequence
Да, более дословный перевод: получение значения от любого сайд-эффекта в release sequence.

Только вот это исправление не сильно тебе помогает. Ты пытаешься доказать, что значение при чтении получается от "последней" записи, а тут выходит, что от любого сайд-эффекта (из release sequence)... Нестыковка. Что делать?
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
10.03.2018, 14:04  [ТС]
Цитата Сообщение от SeqInconsistent Посмотреть сообщение
Только вот это исправление не сильно тебе помогает. Ты пытаешься доказать, что значение при чтении получается от "последней" записи, а тут выходит, что от любого сайд-эффекта (из release sequence)... Нестыковка. Что делать?
Разберемся что из себя представляет acquire. По сути это LoadLoad LoadStore барьер памяти.
LoadLoad LoadStore - acquire (все операции чтения идущие ДО барьера будут выполнены ДО всех операций после барьера)
LoadLoad относится к до, LoadStore к после барьера.
LoadLoad применяются к invalidate queue процессора (заставляет процессор выполнить синхронизацию типа "чтение" с кэшами других процессоров. в эту очередь помещаются сообщения об изменении данных другими ядрами).

Теперь разберемся как вообще заполняется этот самый invalidate queue:
Каждое ядро при изменении у себя данных (тобишь сделав store), шлет специальное сообщение другим ядрам, у которых тоже есть эта переменная. Ядро получив сообщение об изменении этой переменной кладет информацию об этом в invalidate queue что бы произвести синхронизацию либо сразу по требованию через барьер памяти, либо "как карта ляжет" если нет барьера (почему не синхронизируются сразу? да потому что так быстрее ибо в данный момент этому ядру читать сие значение может быть и не нужно и оно может быть занято чем то другим).

Теперь посмотрим чем является atomic load-acquire atomic.load(std::memory_order_acquire)
По сути load-acquire можно представить следующим образом:
C++
1
2
3
int n = data.load(std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_acquire);//LoadLoad LoadStore барьер
//... other operations
То есть тут мы как бы говорим: эй, ядро, все записи которые есть у тебя в invalidate queue нужно применить к твоему кэшу еще до того как ты прочтешь значение int n.
И теперь это самое ядро перед чтением в переменную int n сбрасывает в кэш все что у него есть в invalidate queue.
Потом берет из кэша значение n и записывает в переменную.
Если в очереди было несколько значений из release sequence, то кто был последним сообщившим об изменении нужной переменной, значение того потока и будет последним записано в кэш линию данного ядра (принцип FIFO).

Вот именно по этой причине я и говорил что будет прочитано последнее значение.
Стандарт в свою очередь насколько я понимаю просто требует - запись должна быть синхронизирована с чтением как можно раньше и любая задержка должна быть оправдана.
[29.3/12] Implementations should make atomic stores visible to atomic loads within a reasonable amount of time.
А за сам процесс синхронизации отвечает процессор поэтому вполне резонно то, что такие вещи нужно рассматривать именно с учетом того как вообще процессор осуществляет эту самую синхронизацию. Наш код же процессор выполняет...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
10.03.2018, 14:04

Как увеличить размер загружаемого файла более чем 100М ?
До 5 гигов?!

Определить существует ли кандидат, за которого проголосовало более чем половина избирателей
Сэм i Юра участвуют в выборах. Но это им показалось слишком скучным, i они опросили всех избирателей, за кого они голосовали. Известно, что...

Тип данных запись: Найти багаж, средний вес одной вещи в котором отличается не более, чем на 0,3 кг от общего среднего веса одной вещи
Найти багаж, средний вес одной вещи в котором отличается не более, чем на 0,3 кг от общего среднего веса одной вещи. Программу надо...

Чтение чисел из двух и более файлов и запись в векторы
В общем моя задача такова: Есть 2 и более файла, каждый из которых наполнен столбцом чисел. Мне нужно прочесть числа из каждого файла и...

Вывод более чем 1 запись по значению
Добрый день. Имеется таблица T1(id,name,primmark,tran),T2(id,crd,date) Как вывести данные из таблицы у которых в таблице T1 по полю...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
Как надо было делать правильно - вообще не слушать ИИ, его дело - текст.
Hrethgir 15.07.2026
А вообще надо было делать не так, чтобы не исправлять ошибку https:/ / www. cyberforum. ru/ blogs/ 223907/ 10996. html , правильно было : удалил кнопку, а потом добавил её. Всё это стресс конечно. Почему?. . .
Знаете, от чего появляется стресс?
kumehtar 15.07.2026
Стресс появляется оттого, что вы, зная как поступить правильно, делаете наоборот. Ларри Уингет
Нас бьют, а мы крепчаем? Какая чушь!
kumehtar 15.07.2026
Вот это вот бытующее мнение, что человек меняется только под действием проблем, всегда считал вредоносным. Поверь, от проблем у людей появляются не изменения, а нервное расстройство и ПТСР. А. . .
сукцессия 29. Переход от одних деревьев на другие делать более или менее вероятностным?
anaschu 12.07.2026
Насколько смена типов микоризы — исключительное событие в двухвековой сукцессии? Оценка вероятности в пространстве параметров В текущей версии модели успешно реализован ключевой механизм. . .
сукцессия 27. Думаю, как переделывать уже написанную статью с планами на сукцессию.
anaschu 12.07.2026
Анализ соответствия модели требованиям Реализованные компоненты: Механизм закисления почвы через протонную помпу Конкуренция между типами микориз pH как триггер сукцессии C/ P соотношение. . .
Сукцессия 26. Мат модель создана.
anaschu 12.07.2026
Модель смены растительных сукцессий посредством управления грибами работает внутри небольшой ячейки почвы, восстанавливающейся после пожара, где ненадолго бывшее царство хвойных снова захватили. . .
Решил проблему с ошибкой пагинации сообщений с сервера на алгоритме обхода дерева "Эстафета хвоста".
Hrethgir 12.07.2026
Проблема была в том, что удалялась именно новая кнопка, а не старая. Ни один ИИ не обнаружил это, а сам я смог только когда с работой стало попроще и когда заставил работать будущее автономное. . .
сукцессия 25. Хронология ошибок
anaschu 12.07.2026
# От 50-тонного гриба до устойчивого леса: хроника ошибок при построении модели вековой сукцессии микоризы ## О чём эта статья В процессе построения ОДУ-модели (система дифференциальных. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru