Re[3]: Memory barrier не могу понять что это
От: samius Япония http://sams-tricks.blogspot.com
Дата: 04.04.23 04:11
Оценка:
Здравствуйте, Codealot, Вы писали:

C>Здравствуйте, samius, Вы писали:


S>>Это инструкция, запрещающая перенос инструкций через себя при переупорядочивании.


C>Не только. Барьеры также касаются синхронизации кэшей разных ядер.

соглашусь с формулировкой "регламентируют поведение", которое кэши (железо) и модель памяти должны обеспечивать.
Re: Memory barrier не могу понять что это
От: vsb Казахстан  
Дата: 05.04.23 00:16
Оценка: 10 (1) +2
Здравствуйте, dsalodki, Вы писали:

D>Поясните пожалуйста самым простым способом, я гуглю, но что-то не понятно. Толи это позволяет отменить кеширование переменно, толи ещё что-то


Суть решаемой проблемы:

У нас есть многопроцессорный компьютер с общей памятью. У каждого процессора имеются кеши. Когда несколько процессоров работают с одним адресом памяти, содержимое этой памяти находится в нескольких кешах у каждого процессора. Каждый процессор может обновлять эту память. При этом обновляется кеш у этого процессора и позже будет обновлена сама память. Также процессоры по определённому протоколу синхронизируют кеши между ядрами. Но вообще этот процесс небыстрый.

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

Барьеры памяти это специальные инструкции для процессора, которые позволяют управлять этим процессом синхронизации. К примеру остановить работу процессора, пока не будут обновлены кеши у всех остальных процессоров, соответствующие данном адресу памяти.

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

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

PS то, что я называю процессорами, в современном оборудовании чаще называется ядрами, но суть не меняется.
Отредактировано 05.04.2023 0:19 vsb . Предыдущая версия .
Re[4]: Memory barrier не могу понять что это
От: paradok  
Дата: 05.04.23 07:26
Оценка:
Здравствуйте, Sharowarsheg, Вы писали:

S>Здравствуйте, paradok, Вы писали:


P>>а в реальности что бывает

P>>a=5
P>>b=10
S>a > b=true

S>Да, если a=5 b = 10 выполняется на одном процессоре, а сравнение на другом.


не-е-е-е, если вы намерено не запрограммировали и не выполнили сравнение в другом потоке или нити никогда не будет.



покажите плиз работающий пример кода где такое происходит без преднамеренного програминга сравнения в другом потоке или нити или процессе!
Re[2]: Memory barrier не могу понять что это
От: paradok  
Дата: 05.04.23 07:34
Оценка:
Здравствуйте, vsb, Вы писали:



vsb>Суть решаемой проблемы:


vsb>У нас есть многопроцессорный компьютер с общей памятью.


>>Когда несколько процессоров работают с одним адресом памяти

это надо специально запрграммировать... сама по себе такая ситуация не может возникнуть... или давайте пример кода!
ведь изначально код был такой
a=5
b=10
a>b=true


если же вы сами запрограммировали создание шаред мемори и сами ее меняете из разных процессов то и сами должны позаботиться о синхронизации и никакие барьеры вам не нужны
Re: Memory barrier не могу понять что это
От: fdn721  
Дата: 05.04.23 09:00
Оценка:
Ох уж эти объясняторы...

На самом деле ни кто ни чего не переупорядочивает. Это всего лишь следствие того как разные ядра скидывают свой локальный кэш в ОЗУ.

Вот к примеру есть три переменные A, B, С.

A = C + 1;
B = C + 1;

Чтобы выполнить эти присваивания, Ядро процессора №1 выполняет следующие действия.
1) Загружает переменную C из ОЗУ в Кэш ядра.
...
5) Загружает переменную C из Кэша в Регистр.
6) Увеличивает значение в Регистре на 1.
7) Запишет значение из Регистра в Кэш.
8) Увеличивает значение в Регистре на 1
7) Запишет значение из Регистра в Кэш.
...
20) Вытолкнет из Кэша значение переменной B в ОЗУ.
...
25) Вытолкнет из Кэша значение переменной A в ОЗУ.


Ядра №2,3,4,..N при этом ни чего не знают про значение в Кэше Ядра №1, они видит только ОЗУ. И для них с начало изменится переменная B, а потом через некоторое время переменная А.


Соответствен если вставить барьерную инструкцию, то это заставит Ядро 1 вытолкнуть значение переменно A из Кэша в ОЗУ, до переменной B.

A = C + 1;
memory_barrier();
B = C + 1;


PS Это справедливо для абстрактного процессора в вакууме. Все(кроме NUMA) процессоры с архитектура x86/x64 сделаны так, что все ядра знают про кэши соседних ядер, и соответственно ни каких барьеров памяти в них нет.
Отредактировано 05.04.2023 9:02 fdn721 . Предыдущая версия . Еще …
Отредактировано 05.04.2023 9:02 fdn721 . Предыдущая версия .
Re[2]: Memory barrier не могу понять что это
От: snaphold  
Дата: 05.04.23 11:36
Оценка: 6 (1)
Здравствуйте, Pzz, Вы писали:

Pzz>Здравствуйте, dsalodki, Вы писали:


D>>Поясните пожалуйста самым простым способом, я гуглю, но что-то не понятно. Толи это позволяет отменить кеширование переменно, толи ещё что-то


Pzz>Вот смотри, ты пишешь:


Pzz>
Pzz>a = 5;
Pzz>b = 10;
Pzz>


Pzz>И рассчитываешь, что если в b уже 10, то в a точно 5.


Pzz>Однако процессор может, по разным причинам, исполнить эти команды в другом порядке. В частности потому, что доступ в память, он не так уж и просто устроен, до одних мест может оказаться в данный момент быстрее дотянуться, до других — наоборот.



а законченный код тут с тем какая проблема может быть есть возможность написать? сейчас вроде любой код может выполнять на разных ядрах и поэтому не совсем ясна проблемная область
Re[3]: Memory barrier не могу понять что это
От: vsb Казахстан  
Дата: 05.04.23 13:19
Оценка: 6 (1)
Здравствуйте, paradok, Вы писали:

>>>Когда несколько процессоров работают с одним адресом памяти

P>это надо специально запрграммировать... сама по себе такая ситуация не может возникнуть... или давайте пример кода!

class Ab {
  public int a;
  public int b;
}

void thread1(Ab ab) {
  ab.a = 5;
  ab.b = 10;
}

void thread2(Ab ab) {
  if (ab.a != 5 && ab.b == 10) {
    impossible();
  }
}


Вот пример кода. Без барьеров памяти на некоторых архитектурах (вроде ARM) функция impossible может быть вызвана, хотя это противоречит интуиции. Могут быть и более тонкие баги, к примеру конструктор вызывается в одном потоке, указатель на сконструированный объект передаётся в другой поток, но другой поток видит не до конца сконструированный объект и будут очень странные баги. В Java в конструкторы специально вставляются нужные барьеры, чтобы такой ситуации не возникло, про C# не знаю. В С++ такое точно возможно.

P>если же вы сами запрограммировали создание шаред мемори и сами ее меняете из разных процессов то и сами должны позаботиться о синхронизации и никакие барьеры вам не нужны


Общая память чаще встречается при многопоточном программировании. Внутри одной программы все потоки имеют доступ к общей памяти процесса.

Если использовать синхронизацию, дополнительно никакие барьеры действительно не нужны. Барьеры нужны, когда кажется, что использовать синхронизацию — слишком дорого и хочется ускорить подобный код. Т.н. lock-free алгоритмы используют подобный подход.
Отредактировано 05.04.2023 13:22 vsb . Предыдущая версия . Еще …
Отредактировано 05.04.2023 13:21 vsb . Предыдущая версия .
Отредактировано 05.04.2023 13:21 vsb . Предыдущая версия .
Re[4]: Memory barrier не могу понять что это
От: Философ Ад http://vk.com/id10256428
Дата: 05.04.23 13:44
Оценка:
Здравствуйте, samius, Вы писали:

S>volatile как модификатор переменной — запрет на кэширование. volatile как инструкция — запрет на чтение/запись из кэша в конкретном месте, т.е. немного не о том в общем случае, но в частном (C# и .NET) volatile фактически генерирует вокруг обращений еще и барьеры. В языках, где volatile не генерирует барьеры, проще представить одно без другого.


volatile в шарпе не генерирует никаких барьеров.
Слово volatile запрещает оптимизации компялитора в отношении поля, например компилятор всегда будет обращаться памяти где лежит эта переменная, не кешируя её в регистре. Ещё: компилятор не исключит обращения к этой переменной при чтении.
Новое значение в переменную компилятор будет писать там, где это написал программист, а не там где это оказалось удобно компилятору.
Всё!

Больше volatile не делает ничего. Барьеры при обращении к нескольким volatile полям по-прежнему нужны.
Всё сказанное выше — личное мнение, если не указано обратное.
Re[2]: Memory barrier не могу понять что это
От: snaphold  
Дата: 05.04.23 13:44
Оценка:
Здравствуйте, fdn721, Вы писали:




F>PS Это справедливо для абстрактного процессора в вакууме. Все(кроме NUMA) процессоры с архитектура x86/x64 сделаны так, что все ядра знают про кэши соседних ядер, и соответственно ни каких барьеров памяти в них нет.



сначала вроде понял и уложил в памяти а потом вот это и непонятно тогда зачем мемори барьер нужен если ядря знают про кэши других ядер?
Re[5]: Memory barrier не могу понять что это
От: Философ Ад http://vk.com/id10256428
Дата: 05.04.23 13:45
Оценка:
Здравствуйте, Sharov, Вы писали:

S>....Ну и вроде соотв. доп. инструкции барьеров генерятся, хотя для х86 вроде бы


Кратко: дополнительные инструкции барьеров не генерируются, префикс lock не генерируется....
Более полно: http://rsdn.org/forum/dotnet/8499537.1
Автор: Философ
Дата: 05.04.23
Всё сказанное выше — личное мнение, если не указано обратное.
Re[3]: Memory barrier не могу понять что это
От: Философ Ад http://vk.com/id10256428
Дата: 05.04.23 13:49
Оценка:
Здравствуйте, Pauel, Вы писали:

P>А что они физически представляют? Функцию, инструкцию процессора или что?


В коннечном машинном коде будет mfence или как вариант одна из sfence/lfence инструкций — они запрещают переупорядочивание доступа к памяти вокруг себя.
Всё сказанное выше — личное мнение, если не указано обратное.
Re[4]: Memory barrier не могу понять что это
От: Философ Ад http://vk.com/id10256428
Дата: 05.04.23 13:50
Оценка:
Здравствуйте, Pauel, Вы писали:

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


В разных ядрах — запросто.
Всё сказанное выше — личное мнение, если не указано обратное.
Re[3]: Memory barrier не могу понять что это
От: Философ Ад http://vk.com/id10256428
Дата: 05.04.23 14:06
Оценка: +1
Здравствуйте, snaphold, Вы писали:

S>сначала вроде понял и уложил в памяти а потом вот это и непонятно тогда зачем мемори барьер нужен если ядря знают про кэши других ядер?


Тебя обманули: синхронизация кэшей между ядрами существует, но кэши тут не при чём. Процессор может переупорядочивать инструкции, и в этом проблема. Существуют специальные инструкции, запрещающие переупорядочивание доступа к памяти:
1)sfence — store fence (запрет переупорядочивания записи
2)lfence — load fence (запрет переупорядочивания загрузки)
3)mfence — full fence (запрет переупорядочивания и записи и загрузки)

барьер ставит одну из них.
Всё сказанное выше — личное мнение, если не указано обратное.
Re[3]: Memory barrier не могу понять что это
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 05.04.23 14:07
Оценка:
Здравствуйте, paradok, Вы писали:

P>сами должны позаботиться о синхронизации и никакие барьеры вам не нужны


Так "забота о синхронизации" как раз и состоит в применении барьеров и атомарных операций.
Re[4]: Memory barrier не могу понять что это
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 05.04.23 14:13
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Если использовать синхронизацию, дополнительно никакие барьеры действительно не нужны.


Это если любая синхронизация автоматически создает барьер для всего, что еще не дозаписано в память. В типовых системах именно так и делается, чтобы не морочиться с отслеживанием того, какие данные действительно нужно записывать, а какие нет. Но строгая модель параллельных вычислений требует явно указывать каждую зависимость по данным, иначе правильность не гарантируется.
Re[3]: Memory barrier не могу понять что это
От: vsb Казахстан  
Дата: 05.04.23 14:47
Оценка: +1
Здравствуйте, snaphold, Вы писали:

F>>PS Это справедливо для абстрактного процессора в вакууме. Все(кроме NUMA) процессоры с архитектура x86/x64 сделаны так, что все ядра знают про кэши соседних ядер, и соответственно ни каких барьеров памяти в них нет.


S>сначала вроде понял и уложил в памяти а потом вот это и непонятно тогда зачем мемори барьер нужен если ядря знают про кэши других ядер?


Ядра не знают про кеши других ядер. Существует некий протокол, который синхронизирует кеши, но это происходит как бы асинхронно. Процессор не ждёт окончания этой синхронизации для следующих операций. Он записал в кеш значение и потом специальное оборудование, которое управляет этим кешом, начинает рассылку сообщений по межпроцессорной шине, что по такому-то адресу значение поменялось. Эти сообщения через некоторое количество тактов достигнут другого ядра, другое ядро проверит, есть ли в его кеше такой адрес, если есть, то обновит в нём значение и так далее. То бишь если ты меняешь значение в памяти на одном процессоре, то другой процессор когда-нибудь его увидит. Но когда и в каком порядке — тут гарантий никаких без дополнительных инструкций не будет.

PS да, есть ещё проблема, что компилятор может "соптимизировать" обращения в память и вообще туда ничего не писать, используя регистр для этого. Тогда, конечно, ничего синхронизировать никто не будет, регистры это полностью приватные данные для процессора. Но это уже другой разговор.

PPS всё, что писали про то, что процессоры могут переупорядочивать запись в память тоже верно и тоже может вызывать неожиданное поведение у другого процессора, читающего ту же память. В общем тема довольно запутанная и моё имхо — лучше всего пользоваться примитивами синхронизации, которые на современных процессорах весьма быстрые, а про барьеры пускай думают те, кто пишет их реализации. Ну и про volatile не забывать, чтобы компилятор не слишком увлекался оптимизациями.
Отредактировано 05.04.2023 15:02 vsb . Предыдущая версия .
Re[4]: Memory barrier не могу понять что это
От: Sharov Россия  
Дата: 05.04.23 15:54
Оценка:
Здравствуйте, vsb, Вы писали:


vsb>Могут быть и более тонкие баги, к примеру конструктор вызывается в одном потоке, указатель на сконструированный объект передаётся в другой поток, но другой поток видит не до конца сконструированный объект и будут очень странные баги. В Java в конструкторы специально вставляются нужные барьеры, чтобы такой ситуации не возникло, про C# не знаю. В С++ такое точно возможно.


Ага, в шарпе все также как и в Яве. Т.е. нельзя "опубликовать" не до конца сконтруированный объект.
Кодом людям нужно помогать!
Re[2]: Memory barrier не могу понять что это
От: mike_rs Россия  
Дата: 05.04.23 16:31
Оценка:
Здравствуйте, samius, Вы писали:

S>Это инструкция, запрещающая перенос инструкций через себя при переупорядочивании.


причем бывает двух видов — прагма для компилятора и команда для процессора
Re[5]: Memory barrier не могу понять что это
От: 4058  
Дата: 05.04.23 17:47
Оценка: 6 (1)
Здравствуйте, Философ, Вы писали:

Ф>Здравствуйте, Pauel, Вы писали:


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


Ф>В разных ядрах — запросто.


Эти операции будут выполняться в рамках определенного (одного) потока, поэтому на другое ядро сама по себе операция сравнения не перекинется.
Re[6]: Memory barrier не могу понять что это
От: Философ Ад http://vk.com/id10256428
Дата: 05.04.23 17:57
Оценка:
Здравствуйте, 4058, Вы писали:

4>Эти операции будут выполняться в рамках определенного (одного) потока, поэтому на другое ядро сама по себе операция сравнения не перекинется.


Ну естественно речь о многопоточности идёт.
Всё сказанное выше — личное мнение, если не указано обратное.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.