Russian Qt Forum
Ноябрь 22, 2024, 11:00 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2 3   Вниз
  Печать  
Автор Тема: memory_order  (Прочитано 19775 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Май 24, 2019, 07:11 »

Добрый день

Увидел эту ссылку и решил "почитать" Улыбающийся

Цитировать
Relaxed ordering

Atomic operations tagged memory_order_relaxed are not synchronization operations; they do not impose an order among concurrent memory accesses. They only guarantee atomicity and modification order consistency.
Ну вроде ясно - записанное данной ниткой значение видно ей самой, а для остальных ничего не гарантируется (если сами не позаботятся - могут и не увидеть новое значение). А под "atomicity" наверно имеется ввиду "атомарность присваивания/модификации" (т.е. только целиком, не по кускам)

Дальше там идет вполне понятный пример, а потом вот эта фраза - ее я уже не понял
Цитировать
Typical use for relaxed memory ordering is incrementing counters, such as the reference counters of std::shared_ptr, since this only requires atomicity, but not ordering or synchronization (note that decrementing the shared_ptr counters requires acquire-release synchronization with the destructor)
Это как же "not ordering"? Если одна нитка напр увеличила счетчик и он стал = 1, и эти изменения никому не видны, то другая, увидев старый 0, тоже может поставить 1. Или как?

Прошу пояснить. Спасибо
« Последнее редактирование: Май 24, 2019, 07:13 от Igors » Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #1 : Май 24, 2019, 08:40 »

Ну вроде ясно - записанное данной ниткой значение видно ей самой, а для остальных ничего не гарантируется (если сами не позаботятся - могут и не увидеть новое значение). А под "atomicity" наверно имеется ввиду "атомарность присваивания/модификации" (т.е. только целиком, не по кускам)
Не ясно. Улыбающийся
Модели памяти и ордеренги это больше про перестановки операций доступа к памяти, а не просто атомарность присвоения.
Relax говорит компилятору, что операцию можно перемешивать с другими операциями доступа к памяти как угодно, т.к. эта операция не используется для синхронизации между потоками, а просто изменят счетчик.
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #2 : Май 24, 2019, 08:53 »

Relax говорит компилятору

процессору
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #3 : Май 24, 2019, 09:23 »

процессору
Компилятору, точнее его оптимизатору, который и решает какие операции с какими можно переставить, а какие нельзя (и они должны выполняться строго в этой последовательности).
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #4 : Май 24, 2019, 11:26 »

Компилятору, точнее его оптимизатору, который и решает какие операции с какими можно переставить, а какие нельзя (и они должны выполняться строго в этой последовательности).


facepalm.jpg

Вы можете скомпилировать программу, вставив барьер компилятора, глазками посмотреть что порядок инструкций правильный и все равно схлопотать реордер даже на x86.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #5 : Май 24, 2019, 12:01 »

Вы можете скомпилировать программу, вставив барьер компилятора, глазками посмотреть что порядок инструкций правильный и все равно схлопотать реордер даже на x86.
Хорошо, пусть будет так: ... говорит компилятору, который генерит код, который говорит процессору... Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Май 24, 2019, 12:48 »

Посмотрел еще раз пример

Цитировать
For example, with x and y initially zero,

// Thread 1:
r1 = y.load(std::memory_order_relaxed); // A
x.store(r1, std::memory_order_relaxed); // B
// Thread 2:
r2 = x.load(std::memory_order_relaxed); // C
y.store(42, std::memory_order_relaxed); // D

is allowed to produce r1 == r2 == 42 because, although A is sequenced-before B within thread 1 and C is sequenced before D within thread 2, nothing prevents D from appearing before A in the modification order of y, and B from appearing before C in the modification order of x. The side-effect of D on y could be visible to the load A in thread 1 while the side effect of B on x could be visible to the load C in thread 2. In particular, this may occur if D is completed before C in thread 2, either due to compiler reordering or at runtime.
Т.к. никаких указаний/блокировок нет, то остается полагать что порядок выполнения AB / CD - любой. Но видимость в др. нитке срабатывает, то есть если Thread 1(B) прорвется первой и установит x - он будет видим в Thread 2. Оказывается если пишем relaxed - то записанное значение будет верно relaxed-прочитано в др нитке (конечно если оно не перекрыто опять). Однако про "всю память до того" ничего не говорится.

Разгорающаяся полемика о том кто там чего "переставляет" на мой взгляд не стоит свеч, т.к. это уже следствие "кто кого видит". Из последней фразы
Цитировать
either due to compiler reordering or at runtime
можно заключить что этим грязным делом занимаются все кому не лень  Улыбающийся
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #7 : Май 24, 2019, 13:12 »

Хорошо, пусть будет так: ... говорит компилятору, который генерит код, который говорит процессору... Улыбающийся

Никто процессору ничего не говорит, он _сам_ выбирает порядок, в котором выполняются инструкции так, чтобы использовать ресурсы процессора по максимуму.
Если сейчас идет запись в кэш, то нет смысла выполнять следующую инструкцию записи, а можно выполнить инструкцию сложения или умножения.
Главное, чтобы не было зависимости по данным - если мы читаем ячейку Х и ее же складываем, то переупорядочить не выйдет. А если пишем в Х а складываем с Y, то не важно, в каком порядке выполнять инструкции.
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #8 : Май 24, 2019, 13:16 »

можно заключить что этим грязным делом занимаются все кому не лень  Улыбающийся

Этим занимается в основном ARM.
На x86 только один случай возможен, который и рассмотрен в статье:
Код:
Memory ordering on x86 is actually really strong compared to others. 
You've picked the one example of when x86 //is// allowed to reorder memory operations: StoreLoad.

The rest of the cases {StoreStore, LoadLoad, LoadStore} are ordered.

Т.е. на арме достаточно двух переменных (нужно, чтобы не было зависимости по данным), чтобы поймать reorder, а на x86 надо аж 4. В более простых случаях такого не будет.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #9 : Май 24, 2019, 13:32 »

Никто процессору ничего не говорит, он _сам_ выбирает порядок, в котором выполняются инструкции так, чтобы использовать ресурсы процессора по максимуму.
Если сейчас идет запись в кэш, то нет смысла выполнять следующую инструкцию записи, а можно выполнить инструкцию сложения или умножения.
Главное, чтобы не было зависимости по данным - если мы читаем ячейку Х и ее же складываем, то переупорядочить не выйдет. А если пишем в Х а складываем с Y, то не важно, в каком порядке выполнять инструкции.
Да ладно. Улыбающийся
Для организации барьеров (разговор с процессором) компилятор использует специальные инструкции. Для x86-64 это LOCK и MFENCE.
А по ссылке для всяких разных платформ: https://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #10 : Май 24, 2019, 13:51 »

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

Всё-таки процессор выполняет программу, созданную компилятором. Так что изначально компилятор говорит процессору всё Улыбающийся, это уже потом процессор может своевольничать и переставлять команды по своему усмотрению. А все эти relaxed и прочие - это попытки со стороны компилятора заставить процессор выполнять инструкции в нужном порядке, насколько я понимаю.
« Последнее редактирование: Май 24, 2019, 14:45 от ViTech » Записан

Пока сам не сделаешь...
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #11 : Май 24, 2019, 14:29 »

Да ладно. Улыбающийся

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

Для организации барьеров (разговор с процессором) компилятор использует специальные инструкции. Для x86-64 это LOCK и MFENCE.

Компилятор сам ничего не делает, он просто собирает тот код, который написан в атомике=) А там уже ассемблерные вставки в зависмоcти от флажков.
Да, барьер памяти - это специальная команда.
Вот только причем тут
Цитировать
Компилятору, точнее его оптимизатору, который и решает какие операции с какими можно переставить, а какие нельзя
Если кто не в курсе, то оптимизации делаются задолго до всяких MFENCE=) Они делаются на промежуточном представлении, чтобы не быть завязанным на конкретную архитектуру (точнее, делаются и там и там, но большинство - на промежуточном уровне)
« Последнее редактирование: Май 24, 2019, 14:35 от Авварон » Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #12 : Май 24, 2019, 14:32 »

Собери пример из стати хоть Подмигивающий Посмотри в дизассемлер и скажи как же возможен случай 0, 0 на выходе без перестановки команд процессором.
Мы что сейчас обсуждаем? Улыбающийся
Вы не согласны, что компилятор может говорить процессору, как выполнять тот или иной блок команд? Так в вашей статье это разбирается.
С чем вы спорите? Улыбающийся
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #13 : Май 24, 2019, 14:36 »

С чем вы спорите? Улыбающийся

С вашим утверждением, которое я процитировал - см выше.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #14 : Май 24, 2019, 14:38 »

С вашим утверждением, которое я процитировал - см выше.
Компилятор разбирает исходник и в зависимости от типа барьера может генерировать разный код для процессора. Вы не согласны? Улыбающийся
Записан
Страниц: [1] 2 3   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.083 секунд. Запросов: 23.