Memory barrier не могу понять что это
От: dsalodki Беларусь http://dsalodki.wix.com/resume
Дата: 03.04.23 08:47
Оценка: +1
Поясните пожалуйста самым простым способом, я гуглю, но что-то не понятно. Толи это позволяет отменить кеширование переменно, толи ещё что-то
Re: Memory barrier не могу понять что это
От: kov_serg Россия  
Дата: 03.04.23 09:02
Оценка: +1 -1
Здравствуйте, dsalodki, Вы писали:

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


https://www.youtube.com/watch?v=nh9Af9z7cgE
Re[2]: Memory barrier не могу понять что это
От: dsalodki Беларусь http://dsalodki.wix.com/resume
Дата: 03.04.23 09:05
Оценка: +1 -1
Спасибо, но я бы не писал на русскоязычный форум, если бы знал английский
Re[3]: Memory barrier не могу понять что это
От: kov_serg Россия  
Дата: 03.04.23 09:20
Оценка:
Здравствуйте, dsalodki, Вы писали:

D>Спасибо, но я бы не писал на русскоязычный форум, если бы знал английский

Это не должно вас останавливать.
Re: Memory barrier не могу понять что это
От: samius Япония http://sams-tricks.blogspot.com
Дата: 03.04.23 09:32
Оценка: 37 (3) +1
Здравствуйте, dsalodki, Вы писали:

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

Это инструкция, запрещающая перенос инструкций через себя при переупорядочивании.
Re: Memory barrier не могу понять что это
От: Pzz Россия https://github.com/alexpevzner
Дата: 03.04.23 11:07
Оценка: 164 (6) +5
Здравствуйте, dsalodki, Вы писали:

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


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

a = 5;
b = 10;


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

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

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

Вот тут-то и нужны явные барьеры памяти, чтобы сказать процессору, "доделай, пожалуйста, все операции с памятью, которые я заказывал до этого места, потому что дальше логика моей программы будет рассчитывать на то, что все отложенные/параллельные операции к этому месту уже доделаны"
Re[2]: Memory barrier не могу понять что это
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 03.04.23 11:51
Оценка:
Здравствуйте, Pzz, Вы писали:


Pzz>Вот тут-то и нужны явные барьеры памяти, чтобы сказать процессору, "доделай, пожалуйста, все операции с памятью, которые я заказывал до этого места, потому что дальше логика моей программы будет рассчитывать на то, что все отложенные/параллельные операции к этому месту уже доделаны"


На пальцах вроде всё понятно, но вот в те же плюсики завезли чуть ли не штук пять различных типов барьеров. Я пока плотно вопрос не изучал, но по диагонали — нифига не понял, чем отличаются
Маньяк Робокряк колесит по городу
Re[3]: Memory barrier не могу понять что это
От: Pzz Россия https://github.com/alexpevzner
Дата: 03.04.23 12:54
Оценка: +2
Здравствуйте, Marty, Вы писали:

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


Ну, я описал самый простой случай полного барьера, который полностью отделяет операции "до барьера" от операций "после барьера". Он очень дорогой, и в реальной жизни обычно столько не нужно. Нам, например, может быть важно, чтобы все записи, которые по тексту программы стоят до барьера, до него и произошли, а что там с чтениями, может быть и не важно. Кроме того, у разных процессоров разная модель памяти, а стандарт C++, он, типа, всехний. Поэтому пытается покрыть все возможные варианты. На каком-то конкретном железе разные варианты могут и совпадать, но это не значит, что они будут совпадать на другом железе.
Re[2]: Memory barrier не могу понять что это
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 03.04.23 13:02
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Вот тут-то и нужны явные барьеры памяти, чтобы сказать процессору, "доделай, пожалуйста, все операции с памятью, которые я заказывал до этого места, потому что дальше логика моей программы будет рассчитывать на то, что все отложенные/параллельные операции к этому месту уже доделаны"


А что они физически представляют? Функцию, инструкцию процессора или что?
Re[3]: Memory barrier не могу понять что это
От: paradok  
Дата: 03.04.23 13:20
Оценка:
Здравствуйте, Pauel, Вы писали:

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


Pzz>>Вот тут-то и нужны явные барьеры памяти, чтобы сказать процессору, "доделай, пожалуйста, все операции с памятью, которые я заказывал до этого места, потому что дальше логика моей программы будет рассчитывать на то, что все отложенные/параллельные операции к этому месту уже доделаны"


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


a=10
b=5
но a + b = любое число? или вовсе не инициализировано?
Re[2]: Memory barrier не могу понять что это
От: paradok  
Дата: 03.04.23 13:22
Оценка:
Здравствуйте, Pzz, Вы писали:



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


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


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


а в реальности что бывает
a=5
b=10
a>b=true

?
Re[3]: Memory barrier не могу понять что это
От: Pzz Россия https://github.com/alexpevzner
Дата: 03.04.23 13:33
Оценка: 10 (1)
Здравствуйте, Pauel, Вы писали:

Pzz>>Вот тут-то и нужны явные барьеры памяти, чтобы сказать процессору, "доделай, пожалуйста, все операции с памятью, которые я заказывал до этого места, потому что дальше логика моей программы будет рассчитывать на то, что все отложенные/параллельные операции к этому месту уже доделаны"


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


В Си — функцию. Которая, фактически, превращается в инструкцию процессора.

https://stackoverflow.com/questions/50323347/how-many-memory-barriers-instructions-does-an-x86-cpu-have
Re[3]: Memory barrier не могу понять что это
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 03.04.23 13:57
Оценка:
Здравствуйте, paradok, Вы писали:

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

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

P>?

P>

На одном процессоре такого не будет, процессор следит за зависимостями, и подкладывает результаты в соответствии с зависимостями.
Re[3]: Memory barrier не могу понять что это
От: Sharowarsheg  
Дата: 03.04.23 15:59
Оценка:
Здравствуйте, paradok, Вы писали:

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

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

Да, если a=5 b = 10 выполняется на одном процессоре, а сравнение на другом.
Re[3]: Memory barrier не могу понять что это
От: Aquilaware  
Дата: 03.04.23 18:23
Оценка:
Здравствуйте, Marty, Вы писали:

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


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

Каждый конкретный язык/среда предоставляет свой набор примитивов для барьеров, поэтому их API могут отличатся, но базовый принцип один и тот же.
Re[2]: Memory barrier не могу понять что это
От: Codealot Земля  
Дата: 03.04.23 18:53
Оценка:
Здравствуйте, samius, Вы писали:

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


Не только. Барьеры также касаются синхронизации кэшей разных ядер.
Ад пуст, все бесы здесь.
Re[2]: Memory barrier не могу понять что это
От: Sharov Россия  
Дата: 03.04.23 19:26
Оценка:
Здравствуйте, samius, Вы писали:

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


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

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

Это вроде volatile делает, а барьер на уровне железа просит закоммитить все возможные
изменения в памяти и привести кэши в порядок. Просто инструкции может перенести компилятор и
volatile ему это не даст.
Кодом людям нужно помогать!
Re[3]: Memory barrier не могу понять что это
От: Codealot Земля  
Дата: 03.04.23 20:51
Оценка:
Здравствуйте, Sharov, Вы писали:

S>Это вроде volatile делает, а барьер на уровне железа просит закоммитить все возможные

S>изменения в памяти и привести кэши в порядок. Просто инструкции может перенести компилятор и
S>volatile ему это не даст.

ЕМНИП volatile — один из частных видов барьера памяти.
Ад пуст, все бесы здесь.
Re[4]: Memory barrier не могу понять что это
От: Sharov Россия  
Дата: 03.04.23 22:25
Оценка:
Здравствуйте, Codealot, Вы писали:

S>>Это вроде volatile делает, а барьер на уровне железа просит закоммитить все возможные

S>>изменения в памяти и привести кэши в порядок. Просто инструкции может перенести компилятор и
S>>volatile ему это не даст.
C>ЕМНИП volatile — один из частных видов барьера памяти.

Скорее способ сказать компилятору, чтобы он не занимался соотв. оптимизациями с соотв.
переменной. Ну и вроде соотв. доп. инструкции барьеров генерятся, хотя для х86 вроде бы
особого смысл они не имеют. Тут в тему должен ворваться netch80 и все объяснить.
Кодом людям нужно помогать!
Re[3]: Memory barrier не могу понять что это
От: samius Япония http://sams-tricks.blogspot.com
Дата: 04.04.23 04:04
Оценка: 6 (1) +2 -1
Здравствуйте, Sharov, Вы писали:

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


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


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

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

S>Это вроде volatile делает, а барьер на уровне железа просит закоммитить все возможные

S>изменения в памяти и привести кэши в порядок. Просто инструкции может перенести компилятор и
S>volatile ему это не даст.

volatile как модификатор переменной — запрет на кэширование. volatile как инструкция — запрет на чтение/запись из кэша в конкретном месте, т.е. немного не о том в общем случае, но в частном (C# и .NET) volatile фактически генерирует вокруг обращений еще и барьеры. В языках, где volatile не генерирует барьеры, проще представить одно без другого.
Барьер же — это идея, а не команда кэшам, которую они выполняют. Идея о том, что порядок операций должен быть вот такой, меняться он может "так" и "этак", но не "вот так", и эффекты от этих операций "ощутимы вот таким образом". А железо, в свою очередь (даже не само железо, а модель памяти, скорее), должно соответствовать и обеспечивать корректную работу этой идеи. Если для этого требуется сбросить кэши — будет исполнено. Если потребуется затормозить ядро — будет так.
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>Эти операции будут выполняться в рамках определенного (одного) потока, поэтому на другое ядро сама по себе операция сравнения не перекинется.


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

F>Ох уж эти объясняторы...


F>На самом деле ни кто ни чего не переупорядочивает.


На самом деле переупорядочивает. В Pentium-Pro появился буфер переупорядочивания, тогда ещё размером в 40 мопов и теперь он решает в каком порядке выполнять мопы, а не ты.
Всё сказанное выше — личное мнение, если не указано обратное.
Re[4]: Memory barrier не могу понять что это
От: Философ Ад http://vk.com/id10256428
Дата: 05.04.23 18:02
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Ядра не знают про кеши других ядер. Существует некий протокол,...


угу https://ru.wikipedia.org/wiki/MOESI
Всё сказанное выше — личное мнение, если не указано обратное.
Re: Memory barrier не могу понять что это
От: syrompe  
Дата: 05.04.23 18:17
Оценка:
Здравствуйте, dsalodki, Вы писали:

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


Это же форум по .Net.
Atomicity, volatility and immutability are different, part one и еще там два эпизода по ссылкам. (блин, уже 12 лет прошло)

Поправьте где неправ:
1. volatile в С# — какая-то шляпа
2. lock — вроде как ведет к Memory Barier, правда неявно
3. у нас есть Interlocked, которого хватает в 99%
Re[2]: Memory barrier не могу понять что это
От: Философ Ад http://vk.com/id10256428
Дата: 05.04.23 19:32
Оценка: 12 (1)
Здравствуйте, syrompe, Вы писали:

S>Поправьте где неправ:

S>1. volatile в С# — какая-то шляпа

Нет, оно работает так как должно. Штука очень полезная, особенно если ты шаришь память между между процессами (например с помощью MMF). Например, у тебя выделена память с помощью VirtualAlloc(), в которой ты сделал окно. Ты на неё смотришь через стуктуру (приводишь к указателю на структуру). Все поля этой структуры должны быть volatile — компилятор никогда не сможет угадать, кто и когда поменяет эту память. Фактически это указание компилятору, что к памяти имеет доступ кто-то ещё.

S>2. lock — вроде как ведет к Memory Barier, правда неявно


Да, это так.

S>3. у нас есть Interlocked, которого хватает в 99%

Нет: кому-то хватает, а кому-то нет. Interlocked в конечном счёте выставляет префикс lock на операции обращения к памяти. Это приодит к сигналу Lock на шине процессора при исполнение — производительность на таких штуках серьёзно деградирует.
В принципе любые примитивы синхронизации приводят к деградации производительности. Чем более они высокоуровневые — тем сильнее, хотя с походами в ядро им конечно не сравниться.

Насчёт Interlocked: в циклах ожидания нужно использовать процессорную инструкцию pause, но из C# этого сделать невозможно. Вот пример:

            while (1 == Interlocked.CompareExchange(ref m_dwBusy, 1, 0))
            {
                //здесь должна быть pause
            }


Т.е. я не знаю — по-моему это ещё не ушло в релиз.
Всё сказанное выше — личное мнение, если не указано обратное.
Отредактировано 05.04.2023 19:32 Философ . Предыдущая версия .
Re[3]: Memory barrier не могу понять что это
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 05.04.23 20:38
Оценка:
Здравствуйте, Философ, Вы писали:

S>>3. у нас есть Interlocked, которого хватает в 99%


Ф>Нет: кому-то хватает, а кому-то нет. Interlocked в конечном счёте выставляет префикс lock на операции обращения к памяти. Это приодит к сигналу Lock на шине процессора при исполнение — производительность на таких штуках серьёзно деградирует.


Чтобы почувствовать эту "серьезную деградацию", на современном железе нужно дергать эти операции с частотой хотя бы в сотни тысяч, а лучше — миллионы раз в секунду. Соответственно, чтоб это стало видно на фоне работы полезного кода, он должен быть идеально вылизан — и не на уровне языка, а на уровне машинного кода.

Ф>В принципе любые примитивы синхронизации приводят к деградации производительности. Чем более они высокоуровневые — тем сильнее, хотя с походами в ядро им конечно не сравниться.


Какие высокоуровневые примитивы синхронизации обходятся без походов в ядро?
Re[5]: Memory barrier не могу понять что это
От: Sharowarsheg  
Дата: 06.04.23 00:50
Оценка:
Здравствуйте, paradok, Вы писали:


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


Ну да. Если ты намеренно не запрограммировал это на разных потоках, то барьер не нужен. Вообще, мне кажется, если программировать всё в одном потоке, то вообще можно не знать, что барьеры существуют. По крайней мере, в "обычных" языках и процессорах.
Re[5]: Memory barrier не могу понять что это
От: samius Япония http://sams-tricks.blogspot.com
Дата: 06.04.23 02:50
Оценка:
Здравствуйте, Философ, Вы писали:

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


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


Ф>volatile в шарпе не генерирует никаких барьеров.

Если так, то с помощью какоюй таблетки обеспечивается семантика, заявленная в спеке C# в общем случае, а не про Intel X86/X64?

A read of a volatile field is called a volatile read. A volatile read has “acquire semantics”; that is, it is guaranteed to occur prior to any references to memory that occur after it in the instruction sequence.
A write of a volatile field is called a volatile write. A volatile write has “release semantics”; that is, it is guaranteed to happen after any memory references prior to the write instruction in the instruction sequence.


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

Ф>Новое значение в переменную компилятор будет писать там, где это написал программист, а не там где это оказалось удобно компилятору.
Ф>Всё!

Ф>Больше volatile не делает ничего. Барьеры при обращении к нескольким volatile полям по-прежнему нужны.

С оговорками про конкретную платформу — да. А вообще есть другие мнения. А так же указание полного барьера в методах VolatileRead/Write.
Re[6]: Memory barrier не могу понять что это
От: Философ Ад http://vk.com/id10256428
Дата: 06.04.23 04:50
Оценка:
Здравствуйте, samius, Вы писали:

Ф>>volatile в шарпе не генерирует никаких барьеров.

S>Если так, то с помощью какоюй таблетки обеспечивается семантика, заявленная в спеке C# в общем случае, а не про Intel X86/X64?

с помощью Thread.VolatileRead() и Thread.VolatileWrite()

S>С оговорками про конкретную платформу — да. А вообще есть другие мнения. А так же указание полного барьера в методах VolatileRead/Write.


Фишка в том, что барьеры нужны там где они нужны: там где есть опасность перестановок — нужны, там где пофиг — не нужны.
Всё сказанное выше — личное мнение, если не указано обратное.
Re[4]: Memory barrier не могу понять что это
От: Философ Ад http://vk.com/id10256428
Дата: 06.04.23 04:58
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Чтобы почувствовать эту "серьезную деградацию", на современном железе нужно дергать эти операции с частотой хотя бы в сотни тысяч, а лучше — миллионы раз в секунду.


И тем не менее достичь этого легко: даже Thread.SpinWait(Int32) используется частенько. Достичь 100К итераций ожидания не так сложно как тебе кажется.

ЕМ>Какие высокоуровневые примитивы синхронизации обходятся без походов в ядро?


Ну например SpinLock, ну а если повезёт, то например ManualResetEventSlim тоже может на ожидании без походов в ядро обойтись.
Всё сказанное выше — личное мнение, если не указано обратное.
Re[7]: Memory barrier не могу понять что это
От: samius Япония http://sams-tricks.blogspot.com
Дата: 06.04.23 05:28
Оценка:
Здравствуйте, Философ, Вы писали:

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


Ф>>>volatile в шарпе не генерирует никаких барьеров.

S>>Если так, то с помощью какоюй таблетки обеспечивается семантика, заявленная в спеке C# в общем случае, а не про Intel X86/X64?

Ф>с помощью Thread.VolatileRead() и Thread.VolatileWrite()

Разумеется, работа с volatile полями не приводит к задействованию этих методов. И, прямо в документации по предъявленным ссылкам, написано, что барьеры вставляются при необходимости.

S>>С оговорками про конкретную платформу — да. А вообще есть другие мнения. А так же указание полного барьера в методах VolatileRead/Write.


Ф>Фишка в том, что барьеры нужны там где они нужны: там где есть опасность перестановок — нужны, там где пофиг — не нужны.

А разве кто-то утверждал обратное? Что они не нужны там, где нужны и нужны там, где не нужны?
Re[8]: Memory barrier не могу понять что это
От: Философ Ад http://vk.com/id10256428
Дата: 06.04.23 06:13
Оценка:
Здравствуйте, samius, Вы писали:

S>...И, прямо в документации по предъявленным ссылкам, написано, что барьеры вставляются при необходимости.


А в коде BCL написано что, там безусловно вставляется барьер, без всяких "по необходимости". Сходи и посмотри.

S>А разве кто-то утверждал обратное? Что они не нужны там, где нужны и нужны там, где не нужны?


В этой теме кто-то говорил, что для volatile полей генерируются барьеры. На деле же барьеры ты должен вставлять сам.
Всё сказанное выше — личное мнение, если не указано обратное.
Отредактировано 06.04.2023 6:18 Философ . Предыдущая версия .
Re[9]: Memory barrier не могу понять что это
От: samius Япония http://sams-tricks.blogspot.com
Дата: 06.04.23 06:18
Оценка:
Здравствуйте, Философ, Вы писали:

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


S>>...И, прямо в документации по предъявленным ссылкам, написано, что барьеры вставляются при необходимости.


Ф>А в коде BCL написано что, там безусловно вставляется барьер, без всяких "по необходимости". Сходи и посмотри.

Я об этом пару сообщений назад написал.
Re[4]: Memory barrier не могу понять что это
От: Философ Ад http://vk.com/id10256428
Дата: 06.04.23 06:27
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Какие высокоуровневые примитивы синхронизации обходятся без походов в ядро?


Сейчас глянул сорцы CLR — Monitor.Enter() в конечном счёте тоже может без походов в ядро обойтись.
Всё сказанное выше — личное мнение, если не указано обратное.
Re[5]: Memory barrier не могу понять что это
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 06.04.23 07:56
Оценка:
Здравствуйте, Философ, Вы писали:

Ф>И тем не менее достичь этого легко: даже Thread.SpinWait(Int32) используется частенько. Достичь 100К итераций ожидания не так сложно как тебе кажется.


Ну да, если вставлять, где ни попадя, то легко. Если хоть немного с умом (то есть, сообразуясь с реальной потребностью), то достаточно сложно.

ЕМ>>Какие высокоуровневые примитивы синхронизации обходятся без походов в ядро?


Ф>Ну например SpinLock


Он только с виду "высокоуровневый". Внутри там примитивный цикл из InterlockedCompareExchange (которая раскрывается в команду CmpXchg), InterlockedIncrement/InterlockedDecrement (которые раскрываются в lock xadd), или чего-то подобного. Реально же высокоуровневые примитивы, подразумевающие ожидание с переключением потоков, без походов в ядро не реализуемы.

Ф>если повезёт, то например ManualResetEventSlim тоже может на ожидании без походов в ядро обойтись.


И это на той же технике, как и критические секции со spin count. Как раз костыли для тех, кто их использует бездумно, "по учебнику".
Re[5]: Memory barrier не могу понять что это
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 06.04.23 07:58
Оценка:
Здравствуйте, Философ, Вы писали:

ЕМ>>Какие высокоуровневые примитивы синхронизации обходятся без походов в ядро?


Ф>Сейчас глянул сорцы CLR — Monitor.Enter() в конечном счёте тоже может без походов в ядро обойтись.


Из каких соображений Вы причисляете такие средства к "высокоуровневым"?
Re[6]: Memory barrier не могу понять что это
От: Философ Ад http://vk.com/id10256428
Дата: 06.04.23 08:29
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Из каких соображений Вы причисляете такие средства к "высокоуровневым"?


Из тех соображений, что иногда синхронизация делается вообще без каких-либо примитивов, пример рукопашной синхронизации.
Всё сказанное выше — личное мнение, если не указано обратное.
Re[7]: Memory barrier не могу понять что это
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 06.04.23 09:21
Оценка:
Здравствуйте, Философ, Вы писали:

ЕМ>>Из каких соображений Вы причисляете такие средства к "высокоуровневым"?


Ф>Из тех соображений, что иногда синхронизация делается вообще без каких-либо примитивов, пример рукопашной синхронизации.


То есть, если программа использует InterlockedCompareExchange, что фактически просто вставляет команду CmpXchg, то это "низкоуровневое" средство, а если вызывает некую библиотечную функцию, в которую завернута та же команда, то средство враз становится "высокоуровневым"?
Re[8]: Memory barrier не могу понять что это
От: Философ Ад http://vk.com/id10256428
Дата: 06.04.23 09:36
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>То есть, если программа использует InterlockedCompareExchange, что фактически просто вставляет команду CmpXchg, то это "низкоуровневое" средство, а если вызывает некую библиотечную функцию, в которую завернута та же команда, то средство враз становится "высокоуровневым"?


Ну в общем-то да: даже ReaderWriterLock в конечном счёте ведёт к CompareExchange.

Признаю, что пожалуй ты прав: SpinLock не стоило относить к высокоуровневым.
Всё сказанное выше — личное мнение, если не указано обратное.
Re[4]: Memory barrier не могу понять что это
От: okman Беларусь https://searchinform.ru/
Дата: 06.04.23 11:21
Оценка:
Здравствуйте, Философ, Вы писали:

Ф>В конечном машинном коде будет mfence или как вариант одна из sfence/lfence инструкций — они запрещают переупорядочивание доступа к памяти вокруг себя.


sfence/lfence/mfence — это малость для другого. В машинный код для x86/x64 практически всегда вставляется инструкция типа xchg, xadd или что-то подобное.
Re[5]: Memory barrier не могу понять что это
От: Философ Ад http://vk.com/id10256428
Дата: 06.04.23 12:35
Оценка:
Здравствуйте, okman, Вы писали:

O>sfence/lfence/mfence — это малость для другого. В машинный код для x86/x64 практически всегда вставляется инструкция типа xchg, xadd или что-то подобное.


Интересно, откуда инфа? Можно какие-нибудь доказательства, типа вот такой ссылки, ну или вот такой, или дизасм получающегося кода, или объяснение того, что именно будет делать функция типа

void Foo(){
Thread.MemoryBarrier();
}


Я ОООчень бы хотел узнать, почему вы так думаете, откуда вы это взяли и где тут логика.

ЗЫ: прежде чем отвечать сходите по приведённым ссылкам.

UPD: по своей же ссылке увидел

 #elif defined(HOST_X86)

  #define YieldProcessor() __asm { rep nop }
  #define MemoryBarrier() MemoryBarrierImpl()
  __forceinline void MemoryBarrierImpl()
  {
      int32_t Barrier;
      __asm {
          xchg Barrier, eax
      }
  }


Т.е. если платформа не AMD64 будет действительно xchg. Но логики я тут всё равно не вижу.
И да, где теперь найти X86 но не X86_64?
Всё сказанное выше — личное мнение, если не указано обратное.
Отредактировано 06.04.2023 13:00 Философ . Предыдущая версия .
Re[9]: Memory barrier не могу понять что это
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 06.04.23 20:24
Оценка: 92 (3)
Здравствуйте, Философ, Вы писали:

Ф>SpinLock не стоило относить к высокоуровневым.


Spin locks активно используются в ядрах ОС, в тех случаях, когда чисто технически невозможно выполнить ожидание с переключением контекста, а можно лишь поциклить какое-то разумное время (единицы-десятки микросекунд) в надежде, что параллельный, ядерный же, код, который не может быть прерван в любой момент на сколь угодно долгое время, быстро сделает свои дела и освободит блокировку. Если тщательно не следить за временем, проводимым в циклах, легко наплодить глюков — например, виндовые драйверы нередко проводят в ожидании сотни микросекунд, хотя положено не более 25.

Использовать такое на пользовательском уровне нужно с осторожностью, поскольку поток, вошедший в такой цикл, может быть прерван, и другой поток, пытающийся его дождаться, исчерпает свой квант, и тоже будет вытеснен. До какой-то частоты использования такие блокировки позволяют сэкономить на переключениях в ядро, но дальше они могут привести к резкому росту накладных расходов. Особенно в том случае, если код отлаживался на восьмиядерном процессоре, а затем запущен на двухъядерном, где вероятность прерывания потока примерно вчетверо выше.
Re[10]: Memory barrier не могу понять что это
От: Философ Ад http://vk.com/id10256428
Дата: 06.04.23 21:09
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

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


Я знаю это. Спинлоки у меня там, где ожидаемое время WaitForSingleObject() на сигнальном объекте, например на свободном мьютексе, больше чем время ожидания. Второй случай, когда я такое использую — протокол реализован на MMF, где одно из полей — признак занятости. Там просто без вариантов: Sleep(1) ждёт дольше чем нужно.
Всё сказанное выше — личное мнение, если не указано обратное.
Re[6]: Memory barrier не могу понять что это
От: Mr.Delphist  
Дата: 06.04.23 21:14
Оценка: 6 (1)
Здравствуйте, Sharowarsheg, Вы писали:

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


Безотносительно многопоточности, возможно переупорядочивание инструкций внутри одного ядра (АЛУ).

Погуглите
* cpu instruction reordering
* out of order execution

Если отдельно взятый поток/АЛУ решит, что заданные две инструкции можно исполнить в любом порядке (поскольку зависимостей между ними не наблюдает), то он выберет тот, который даст бОльшую эффективность по заданному policy: energy consumption, или memory throughput или idle cycle count, или что там сейчас считается важным.

Само собой, что возможны случаи, когда сделанное предположение об отсутствии зависимостей является неверным, и АЛУ тем самым вносит side-effect, который не ожидался автором программы — лезут плавающие баги. Особенно сложно правильно определять такие зависимости, когда имеем дело с managed-платформами, когда есть некоторый промежуточный уровень абстракции (рантайм C# или Java VM). Именно поэтому там вводится понятие "модели памяти" (memory model), чтобы хоть как-то очертить правила игры и дать базовые гарантии, работающие одинаково на всех поддерживаемых аппаратных платформах. Ну а если базовых гарантий недостаточно или мы хотим объехать их для какого-то выигрыша — тогда в бой идут явные задания барьеров памяти.
Re[4]: Memory barrier не могу понять что это
От: Mr.Delphist  
Дата: 06.04.23 21:26
Оценка: 6 (1) +2
Здравствуйте, vsb, Вы писали:

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


Однако определённый эффект на соседние ядра это тоже оказывает, поэтому, например, нельзя "бесплатно" (с точки зрения производительности) делать активную запись двумя потоками в две соседних ячейки памяти, если они попадают в одну кэш-линию. По каждому сигналу инвалидации кэш-линии, контроллер памяти будет ставить другое ядро на холд при попытке обращения к соседней ячейке, пока не синхронизирует два экземпляра этой кеш-линии. Хотя казалось бы, зачем тут синхронизация исполнения — ведь каждый поток пишет только в свою ячейку и никак не работает с соседней (гуглить false sharing).
Re[6]: Memory barrier не могу понять что это
От: okman Беларусь https://searchinform.ru/
Дата: 07.04.23 08:28
Оценка: 6 (1) +1
Здравствуйте, Философ, Вы писали:

Ф>Интересно, откуда инфа? Можно какие-нибудь доказательства [...] или дизасм получающегося кода, или объяснение того, что именно будет делать функция типа

Ф>
Ф>void Foo(){
Ф>Thread.MemoryBarrier();
Ф>}
Ф>


Ф>Я ОООчень бы хотел узнать, почему вы так думаете, откуда вы это взяли и где тут логика.

Ф>Т.е. если платформа не AMD64 будет действительно xchg. Но логики я тут всё равно не вижу.

Прежде всего, откуда я это взял. Работа такая
:-)


Да просто видел уже много-много раз при работе с крэш-дампами, в отладчике, в IDA Pro, при анализе ситуаций с зависаниями и другими проблемами.
Частенько приходится работать непосредственно с ассемблерными листингами, в основном это 32- и 64-битный код под архитектуры Intel/AMD (до ARM пока руки не дошли).
Также иногда интересно бывает написать что-то с использованием atomic или memory_order_xxx (C++) и посмотреть, во что компилятор превратит написанное.
И я вообще не припомню, чтобы хоть раз где-то видел sfence, lfence или mfence в многопоточке, в основном там всегда именно xchg, cmpxchg, xadd и т.п.

sfence/lfence/mfence, насколько я знаю, появились в SSE/SSE2 для поддержки non-temporal операций вроде movntdq, когда запись идет напрямую в память, не попадая в кэш CPU.
Т.е. они дают возможность упорядочивать такие операции более эффективным способом по сравнению с cpuid, например.

В обычном прикладном коде такие вещи практически не встречаются. Ну и сам по себе mfence, если верить дискуссиям в Гугле, занимает больше тактов CPU по сравнению с
locked-инструкциями типа xchg. Поэтому, а также ввиду определенных причин, связанных с особенностями работы Intel/AMD в этих аспектах, в "обычном" коде чаще
используется именно xchg, а не fence.

Вообще, тема эта очень обширная и сложная, в двух-трех предложениях и малой части не описать. Например, очень часто компилятор не вставляет никаких специальных
барьеров туда, где ты вроде бы их ожидаешь. Например потому, что определенные гарантии предоставляет сама архитектура: "stores are not reordered with other stores" и т.д.
Отредактировано 07.04.2023 8:33 okman . Предыдущая версия .
Re[7]: Memory barrier не могу понять что это
От: paradok  
Дата: 07.04.23 14:36
Оценка:
Здравствуйте, Mr.Delphist, Вы писали:


MD>Само собой, что возможны случаи,


пример кода чтобы можно было запустить и увидеть эти самые плавающие ошибки?
Re[8]: Memory barrier не могу понять что это
От: Философ Ад http://vk.com/id10256428
Дата: 07.04.23 18:19
Оценка: 10 (1)
Здравствуйте, paradok, Вы писали:

MD>>Само собой, что возможны случаи,


P>пример кода чтобы можно было запустить и увидеть эти самые плавающие ошибки?


Можно. https://eric-lo.gitbook.io/lock-free-programming/memory-fence
Там в статье пример кода, который это демонстрирует.
Всё сказанное выше — личное мнение, если не указано обратное.
Отредактировано 07.04.2023 18:20 Философ . Предыдущая версия .
Re[9]: Memory barrier не могу понять что это
От: 4058  
Дата: 08.04.23 06:17
Оценка:
Здравствуйте, Философ, Вы писали:

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


P>>пример кода чтобы можно было запустить и увидеть эти самые плавающие ошибки?


Ф>Можно. https://eric-lo.gitbook.io/lock-free-programming/memory-fence

Ф>Там в статье пример кода, который это демонстрирует.

В данной статье автор в одном потоке пишет в глобальные переменные, а в другом из них читает без обеспечения должным образом критической секции при обращении к этим переменным (т.е. нарочито демонстрирует поведение ССЗБ):

, при этом настойчиво пытается продемонстрировать побочный эффект от переупорядочивания присвоений в обоих потоках разбросанных по разным ядрам.
Re[10]: Memory barrier не могу понять что это
От: Философ Ад http://vk.com/id10256428
Дата: 08.04.23 09:48
Оценка:
Здравствуйте, 4058, Вы писали:

4>В данной статье автор в одном потоке пишет в глобальные переменные, а в другом из них читает без обеспечения должным образом критической секции при обращении к этим переменным (т.е. нарочито демонстрирует поведение ССЗБ):..


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


4>, при этом настойчиво пытается продемонстрировать побочный эффект от переупорядочивания присвоений в обоих потоках разбросанных по разным ядрам.


Так ведь продемонстировал же! И демонстрашка там эта очень в тему: раз уж мы разбираемся в lock-free, то должны бы знать и о буферах переупорядочивания, и о спекулятивном исполнении и ещё много чего.
Всё сказанное выше — личное мнение, если не указано обратное.
Отредактировано 08.04.2023 9:53 Философ . Предыдущая версия .
Re[5]: Memory barrier не могу понять что это
От: Pzz Россия https://github.com/alexpevzner
Дата: 08.04.23 14:45
Оценка: 6 (1) +2
Здравствуйте, okman, Вы писали:

O>sfence/lfence/mfence — это малость для другого. В машинный код для x86/x64 практически всегда вставляется инструкция типа xchg, xadd или что-то подобное.


Это разные вещи.

Представь, два потока на разных ядрах CPU у тебя одновременно инкрементируют одну переменную. Пусть даже с помощью одной инструкции процессора, а не трех (прочитать, проинкрементировать, сохранить).

Величина, на которую увеличится переменная, будет меньше, чем суммарное количество операций по ее увеличению, сделанных обеими потоками. Вот смотри, что делает инструкция INC, если ее аргумент — адрес в памяти, с учетом кеширования:
1. Загрузить значение в ALU. Значение само по себе, скорее всего, в кеше
2. Прибавить 1
3. Сохранить значение в кеш.

Поскольку потоков два, а переменная одна, на 3-м шаге возникает синхронизация кешей. На 3-м, заметь, а не на 1-м. Поэтому запросто может быть, что на первом шаге оба потока прочтут в ALU одно и то же значение (кеш в этот момент синхронен и процессору не о чем беспокоиться), прибавят к нему 1 и сохранят на место. Т.е., в итоге, переменная увеличится на 1, хотя оба потока ее увеличивали.

Чтобы этого избежать, существует префикс LOCK. Он делает всю цепочку 1-2-3 атомарной в том смысле, что с того момента, пока один поток сделал шаг 1 и до того, как он сделал 3, второму потоку просто не дадут туда войти.

У некоторых команд, типа XCHG, префикс LOCK встроенный, некоторым другим приходится приделывать его явно.

Это совсем не то же самое, что reordering инструкций, от которого "защищают" барьеры памяти.
Отредактировано 08.04.2023 18:38 Pzz . Предыдущая версия .
Re[6]: Memory barrier не могу понять что это
От: Философ Ад http://vk.com/id10256428
Дата: 08.04.23 22:08
Оценка:
Здравствуйте, Pzz, Вы писали:

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


Pzz>Чтобы этого избежать, существует префикс LOCK...

Pzz>Это совсем не то же самое, что reordering инструкций, от которого "защищают" барьеры памяти.

Ты не находишь странным такое объяснять системному программисту, который разбирает дампы и ковыряется в ассемблерных листингах!? По-моему он просто стебётся.
С другой стороны, он просто не понимает зачем вся эта фигня — просто никогда не слышал о lock-free алгоритмах. И при этом очень вероятно, что и не видел никогда в многопоточном коде *fence инструкций: lock-free всё-таки редкость. Даже сомневаюсь, что в ВУЗах такое учат.
Всё сказанное выше — личное мнение, если не указано обратное.
Re[7]: Memory barrier не могу понять что это
От: Философ Ад http://vk.com/id10256428
Дата: 08.04.23 22:21
Оценка:
Здравствуйте, okman, Вы писали:

O>Да просто видел уже много-много раз при работе с крэш-дампами, в отладчике, в IDA Pro, при анализе ситуаций с зависаниями и другими проблемами.


Видел что? Во что превращается c++ intrinsic _mm_mfence?

O>И я вообще не припомню, чтобы хоть раз где-то видел sfence, lfence или mfence в многопоточке, в основном там всегда именно xchg, cmpxchg, xadd и т.п.


Это потому, что указанные инструкции используются для атомарных операций, при этом суть их — блокировки. Все приведённые инструкции неявно выставляют LOCK# на шину. Барьеры же используются для lock-free алгоритмов.

O>sfence/lfence/mfence, насколько я знаю, появились в SSE/SSE2 для поддержки non-temporal операций вроде movntdq, когда запись идет напрямую в память, не попадая в кэш CPU.


О таков варианте использования в мануале по оптимизации для Pentium-4, где они впервые появились. К несчастью полную докуменацию по Pentium-4 мне не удалось найти — не могу ни подтвердить, ни опровергнуть

O>В обычном прикладном коде такие вещи практически не встречаются. Ну и сам по себе mfence, если верить дискуссиям в Гугле, занимает больше тактов CPU по сравнению с

O>locked-инструкциями типа xchg.

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

O>Вообще, тема эта очень обширная и сложная, в двух-трех предложениях и малой части не описать.


Ооо! Это точно.


O>Например, очень часто компилятор не вставляет никаких специальных

O>барьеров туда, где ты вроде бы их ожидаешь. Например потому, что определенные гарантии предоставляет сама архитектура: "stores are not reordered with other stores" и т.д.

Не понимаю о чём идёт речь. Что и где должно теоретически быть, но не вставляет? Я думал, что синхронизация целиком и полностью ответственность программиста.
Всё сказанное выше — личное мнение, если не указано обратное.
Отредактировано 08.04.2023 22:23 Философ . Предыдущая версия .
Re[7]: Memory barrier не могу понять что это
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 09.04.23 08:42
Оценка: 3 (1) +1
Здравствуйте, Философ, Вы писали:

Ф>С другой стороны, он просто не понимает зачем вся эта фигня — просто никогда не слышал о lock-free алгоритмах. И при этом очень вероятно, что и не видел никогда в многопоточном коде *fence инструкций


Или слышал и знает, что на x86/x64 атомарные операции создают full memory barrier...
Re[8]: Memory barrier не могу понять что это
От: okman Беларусь https://searchinform.ru/
Дата: 09.04.23 09:35
Оценка: 9 (1) +1
Здравствуйте, Философ, Вы писали:

Ф>Видел что? Во что превращается c++ intrinsic _mm_mfence?


Подчеркну: я описываю лишь то, что многократно видел сам за последние несколько лет. Без претензий на что-либо, просто наблюдения и выводы,
сделанные в контексте использования MS C++ под 32- и 64-битные версии Windows.

Если мы пишем 'MemoryBarrier' — компилятор впихнет туда xchg или какой-нибудь lock or.
Если используем Interlocked-функции или работаем через <atomic> из C++ (memory_order_seq_cst) — снова получаем на выходе xchg, cmpxchg, xadd и т.д.
Если заглянем в реализацию каких-нибудь примитивов синхронизации — там тоже много где используется "xchg и компания".
И т.д.

Почему там отсутствует (или исчезающе мало) mfence — я не берусь утверждать со 100% определенностью. Но подозреваю, что все очень прозаично и на
современных процессорах locked instructions вроде xchg выполняются быстрее, чем mfence.

Ну а sfence/lfence, если не рассматривать кейсы с "non-temporal hint", на x86 и x64 вообще бессмысленны, потому что там для "load-load" и
"store-store" порядок гарантируется архитектурой. И вставлять, например, sfence между двумя записывающими mov — только терять время.


Ф>Это потому, что указанные инструкции используются для атомарных операций, при этом суть их — блокировки. Все приведённые инструкции неявно выставляют LOCK# на шину. Барьеры же используются для lock-free алгоритмов.


Давайте рассмотрим xchg как пример. В контексте обсуждения эта инструкция обладает как минимум тремя полезными свойствами:

1. она атомарна
2. она работает как барьер, запрещая "перепрыгивать" через нее операциям записи или чтения
3. она сбрасывает буферы записи (store buffer), действуя аналогично инструкциям сериализации вроде cpuid

Пруф — документ "Intel® 64 and IA-32 Architectures Software Developer’s Manual (Combined Volumes)", редакция "May 2019":

8.2.2 Memory Ordering in P6 and More Recent Processor Families

...
Reads or writes cannot be reordered with I/O instructions, locked instructions, or serializing instructions.
...
Locked instructions have a total order.


11.10 STORE BUFFER

Intel 64 and IA-32 processors temporarily store each write (store) to memory in a store buffer. The store buffer
improves processor performance by allowing the processor to continue executing instructions without having to
wait until a write to memory and/or to a cache is complete. It also allows writes to be delayed for more efficient use
of memory-access bus cycles.

In general, the existence of the store buffer is transparent to software, even in systems that use multiple processors.
The processor ensures that write operations are always carried out in program order. It also insures that the
contents of the store buffer are always drained to memory in the following situations:

...

* When a LOCK operation is performed.

...


22.34 STORE BUFFERS AND MEMORY ORDERING

The Pentium 4, Intel Xeon, and P6 family processors provide a store buffer for temporary storage of writes (stores)
to memory (see Section 11.10, “Store Buffer”). Writes stored in the store buffer(s) are always written to memory
in program order, with the exception of “fast string” store operations (see Section 8.2.4, “Fast-String Operation and
Out-of-Order Stores”).

The Pentium processor has two store buffers, one corresponding to each of the pipelines. Writes in these buffers
are always written to memory in the order they were generated by the processor core.

It should be noted that only memory writes are buffered and I/O writes are not. The Pentium 4, Intel Xeon, P6
family, Pentium, and Intel486 processors do not synchronize the completion of memory writes on the bus and
instruction execution after a write. An I/O, locked, or serializing instruction needs to be executed to synchronize
writes with the next instruction (see Section 8.3, “Serializing Instructions”).


И теперь вопрос от меня: чем xchg хуже mfence в плане использования в качестве барьера?


O>>В обычном прикладном коде такие вещи практически не встречаются. Ну и сам по себе mfence, если верить дискуссиям в Гугле, занимает больше тактов CPU по сравнению с

O>>locked-инструкциями типа xchg.

Ф>Весьма примерно представляю, как это проверить. Буду рад примеру кода, который подтвердит или опровергнет эту гипотезу.


У меня есть только ссылка, ведущая на обсуждение в группы linux kernel, где, насколько я понял, там в итоге отказались от mfence в пользу lock:

x86 memory barrier: why does Linux prefer MFENCE to Locked ADD?
https://groups.google.com/g/fa.linux.kernel/c/hNOoIZc6I9E/m/WlyXcgwoCwAJ


O>>Например, очень часто компилятор не вставляет никаких специальных

O>>барьеров туда, где ты вроде бы их ожидаешь. Например потому, что определенные гарантии предоставляет сама архитектура: "stores are not reordered with other stores" и т.д.

Ф>Не понимаю о чём идёт речь. Что и где должно теоретически быть, но не вставляет? Я думал, что синхронизация целиком и полностью ответственность программиста.


Ну например, примерно такой код обычно приводится в качестве примера использования acquire/release семантики:
#include <atomic>
#include <cstdio>
#include <thread>
 
int data;
std::atomic<bool> ready;
 
void producer()
{
    data = 123;
    ready.store(true, std::memory_order_release);
}
 
void consumer()
{
    while (false == ready.load(std::memory_order_acquire)) {}
    printf("data = %d", data);
}
 
int main()
{
    std::thread t1(producer);
    std::thread t2(consumer);
    t1.join(); t2.join();
    return 0;
}


Здесь, мол, у нас в producer между записью в data и ready будет барьер, гарантирующий, что первое будет завершено строго до второго. И то же самое в consumer —
поток сначала увидит ready, и только потом начнет читать data. Но если посмотреть сгенерированный ассемблерный код, там нет никаких явно выставленных барьеров
при работе с переменной 'ready', просто mov на чтение и mov на запись:
void producer(void) PROC
    mov     DWORD PTR int data, 123
    npad    1
    mov     BYTE PTR std::atomic<bool> ready, 1
    ret     0
void producer(void) ENDP 

void consumer(void) PROC
    npad    2
$LL2@consumer:
    movzx   eax, BYTE PTR std::atomic<bool> ready
    npad    1
    test    al, al
    je      SHORT $LL2@consumer
    ...
void consumer(void) ENDP
Re[8]: Memory barrier не могу понять что это
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 09.04.23 10:52
Оценка: +1
Здравствуйте, Философ, Вы писали:

Ф>Это потому, что указанные инструкции используются для атомарных операций, при этом суть их — блокировки. Все приведённые инструкции неявно выставляют LOCK# на шину. Барьеры же используются для lock-free алгоритмов.


Я что-то думал, что lock-free алгоритмы — это про то, что не используется никаких объектов синхронизации, даже таких легких, как spin lock/CriticalSection. Без атомарных операций lock-free вряд ли получиться сделать, и префикс команды LOCK он не про то совсем
Маньяк Робокряк колесит по городу
Re[9]: Memory barrier не могу понять что это
От: Философ Ад http://vk.com/id10256428
Дата: 09.04.23 12:11
Оценка:
Здравствуйте, okman, Вы писали:

O>2. она работает как барьер, запрещая "перепрыгивать" через нее операциям записи или чтения

O>3. она сбрасывает буферы записи (store buffer), действуя аналогично инструкциям сериализации вроде cpuid

O>

O>8.2.2 Memory Ordering in P6 and More Recent Processor Families
O>Locked instructions have a total order.


O>

O> * When a LOCK operation is performed.

O> ...



Спасибо. Это то, что я упустил — забыл, или не внимательно читал. Я аж полез и перепроверил — это действительно так.
Сорри, просто не знал, об эффектах префикса LOCK.

O>И теперь вопрос от меня: чем xchg хуже mfence в плане использования в качестве барьера?


Не знаю.
Всё сказанное выше — личное мнение, если не указано обратное.
Re[8]: Memory barrier не могу понять что это
От: Философ Ад http://vk.com/id10256428
Дата: 09.04.23 12:12
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Или слышал и знает, что на x86/x64 атомарные операции создают full memory barrier...


Полагаю, что тут этого много кто не знал. Я проверил — это действительно так.
Всё сказанное выше — личное мнение, если не указано обратное.
Re[5]: Memory barrier не могу понять что это
От: vmpire Россия  
Дата: 09.04.23 20:08
Оценка: 6 (1)
Здравствуйте, Sharov, Вы писали:


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


S>Ага, в шарпе все также как и в Яве. Т.е. нельзя "опубликовать" не до конца сконтруированный объект.

А если в середине конструктора вызвать виртуальный метод, который передаст this в другой поток?
Re[6]: Memory barrier не могу понять что это
От: Sharov Россия  
Дата: 09.04.23 21:50
Оценка:
Здравствуйте, vmpire, Вы писали:

S>>Ага, в шарпе все также как и в Яве. Т.е. нельзя "опубликовать" не до конца сконтруированный объект.

V>А если в середине конструктора вызвать виртуальный метод, который передаст this в другой поток?

Интересно, не пробовал. Зачем для этого виртуальный метод, любой пойдет же?
Кодом людям нужно помогать!
Re[7]: Memory barrier не могу понять что это
От: vmpire Россия  
Дата: 10.04.23 00:23
Оценка:
Здравствуйте, Sharov, Вы писали:


S>>>Ага, в шарпе все также как и в Яве. Т.е. нельзя "опубликовать" не до конца сконтруированный объект.

V>>А если в середине конструктора вызвать виртуальный метод, который передаст this в другой поток?
S>Интересно, не пробовал. Зачем для этого виртуальный метод, любой пойдет же?
Виртуальный интереснее. Так может быть ещё не до конца инициализирован даже базовый класс
Re[5]: Memory barrier не могу понять что это
От: MadHuman Россия  
Дата: 10.04.23 06:00
Оценка:
P>>>а в реальности что бывает
P>>>a=5
P>>>b=10
S>>a > b=true

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


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


выше речь шла про процессор, и вообще-то такое возможно, если перед сравнением шедулер потоков ОС переключил выполнение потока на другой процессор.
Re[9]: Memory barrier не могу понять что это
От: paradok  
Дата: 10.04.23 06:17
Оценка:
Здравствуйте, Философ, Вы писали:

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


MD>>>Само собой, что возможны случаи,


P>>пример кода чтобы можно было запустить и увидеть эти самые плавающие ошибки?


Ф>Можно. https://eric-lo.gitbook.io/lock-free-programming/memory-fence

Ф>Там в статье пример кода, который это демонстрирует.

нет. там просто создаются две нити и их пускают обрабатывать одну и туже память.
речь же шла о коде без принудительного создания нитей
a=2
b=3
a>b=true
Re[10]: Memory barrier не могу понять что это
От: Философ Ад http://vk.com/id10256428
Дата: 10.04.23 06:33
Оценка: 6 (1)
Здравствуйте, paradok, Вы писали:

P>...без принудительного создания нитей


ааа, я пропустил этот момент. Думал, тебе нужен просто пример кода, демонстрирующий реордер.
Всё сказанное выше — личное мнение, если не указано обратное.
Re[6]: Memory barrier не могу понять что это
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 10.04.23 08:40
Оценка:
Здравствуйте, MadHuman, Вы писали:

MH>такое возможно, если перед сравнением шедулер потоков ОС переключил выполнение потока на другой процессор.


Невозможно. Если железо не обеспечивает синхронизации кэшей само, планировщик делает это при переключении.
Re[7]: Memory barrier не могу понять что это
От: MadHuman Россия  
Дата: 10.04.23 08:49
Оценка:
ЕМ>Здравствуйте, MadHuman, Вы писали:

MH>>такое возможно, если перед сравнением шедулер потоков ОС переключил выполнение потока на другой процессор.


ЕМ>Невозможно.

вы утверждаете что при вытесняющей многозадачности невозможно что шедулер ОС продолжит выполнение потока на другом ядре??
очевидно что такое возможно. планировщик по возможности старается конечно сохранить выполнение треда на одном ядре, но не всегда это возможно.


ЕМ>Если железо не обеспечивает синхронизации кэшей само, планировщик делает это при переключении.

планировщик при восстановлении потока, восстанавливает регистры, он не знает что делал поток и к какой памяти обращался.
хотя тут деталями не владею, возможно при перекидывании потока на другое ядро кроме восттановления регистров ОС и делает ещё что-то
чтоб обеспечить консистентность кэшей. а может это в железе как-то обеспечено.
Re[8]: Memory barrier не могу понять что это
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 10.04.23 09:08
Оценка: +2
Здравствуйте, MadHuman, Вы писали:

MH>вы утверждаете что при вытесняющей многозадачности невозможно что шедулер ОС продолжит выполнение потока на другом ядре??


Нет, конечно. Я утверждаю, что невозможны эффекты, которые Вы описывали.

MH>возможно при перекидывании потока на другое ядро кроме восттановления регистров ОС и делает ещё что-то чтоб обеспечить консистентность кэшей.


Не "возможно", а достоверно. Любая многопоточная ОС всегда гарантирует, что все данные отдельного потока, выполняемого на разных процессорах, будут выглядеть так же, как и на одном процессоре — если, конечно, поток специально не пытается отследить переключения. Проблемы могут возникать только при доступе к одним и тем же данным со стороны разных потоков.
Re[9]: Memory barrier не могу понять что это
От: MadHuman Россия  
Дата: 10.04.23 09:19
Оценка:
ЕМ>Не "возможно", а достоверно. Любая многопоточная ОС всегда гарантирует, что все данные отдельного потока, выполняемого на разных процессорах, будут выглядеть так же, как и на одном процессоре
это да, без этого никак.
я выразил неуверенность, в том каким образом это достигается. как шедулер ОС может знать с какой памятью (ну кроме стэка) поток работал и как? никак.
поэтому вероятно это в железе обеспечено, но возможно ОС при продолжении работы потока на другом ядре даёт команду что-то типа — синхронизировать/сбросить кэши ядра (тот самый мемори барьер?).
Re[3]: Memory barrier не могу понять что это
От: Sharov Россия  
Дата: 10.04.23 10:30
Оценка:
Здравствуйте, Философ, Вы писали:

Ф>
Ф>            while (1 == Interlocked.CompareExchange(ref m_dwBusy, 1, 0))
Ф>            {
Ф>                //здесь должна быть pause
Ф>            }
Ф>

Ф>Т.е. я не знаю — по-моему это ещё не ушло в релиз.

По ссылке в деталях не читал, но чем этот pause от spinlock отличается? Энергоэффективностью, т.е. не гоняет циклы на ядре по чем зря?
Кодом людям нужно помогать!
Re[10]: Memory barrier не могу понять что это
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 10.04.23 10:56
Оценка: 6 (1)
Здравствуйте, MadHuman, Вы писали:

MH>как шедулер ОС может знать с какой памятью (ну кроме стэка) поток работал и как?


Ну вот как планировщик может знать, с какими регистрами поток работал, и с какими будет работать следующий? Может, какие-то регистры и не нужно сохранять, ибо их не испортят. Но, поскольку он этого не знает, то сохраняет все регистры — на всякий случай. Затратно, зато надежно. В служебных потоках виндового ядра, например, автоматически сохраняются только регистры общего назначения, а всякие FPU/SSE, с которыми в ядре работать не принято, надо сохранять и восстанавливать вручную.

MH>вероятно это в железе обеспечено, но возможно ОС при продолжении работы потока на другом ядре даёт команду что-то типа — синхронизировать/сбросить кэши ядра (тот самый мемори барьер?).


Сама по себе синхронизация кэшей в x86/x64 обеспечена аппаратно, так что планировщику достаточно лишь создать барьер, чтобы исключить перестановку операций. Ничего специального для этого делать не нужно, поскольку любому планировщику приходится использовать атомарные операции, каждая из которых в x86/x64 создает полный барьер.
Re[4]: Memory barrier не могу понять что это
От: Философ Ад http://vk.com/id10256428
Дата: 10.04.23 10:59
Оценка: +1
Здравствуйте, Sharov, Вы писали:


S>По ссылке в деталях не читал, но чем этот pause от spinlock отличается? Энергоэффективностью, т.е. не гоняет циклы на ядре по чем зря?


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

приведённый пример кода — просто пример реализации SpinLock. Иногда приходится вот так, руками её реализовывать: штатный SpinLock неудобен/непригоден для вот таких кейсов: https://github.com/scumware/RTSS_time_reader/blob/master/RTSS_interop/OSD.cs#L415
Всё сказанное выше — личное мнение, если не указано обратное.
Re[8]: Memory barrier не могу понять что это
От: Sharov Россия  
Дата: 10.04.23 11:17
Оценка:
Здравствуйте, Философ, Вы писали:

Ф>Это потому, что указанные инструкции используются для атомарных операций, при этом суть их — блокировки. Все приведённые инструкции неявно выставляют LOCK# на шину. Барьеры же используются для lock-free алгоритмов.



Дополню ответ Марти выше -- lock-free алгоритмы это суть алгоритмы на оснвое CAS, т.е. на основе атомарных инструкций процессора. Т.е. программист не использует никакие примитивы синхронизации и походы в ядро, вместо этого lock используеются на уровне железа. Т.е. lock-free на уровне железе нифига не lock-free, но судя
по всему, быстрее чем с примитивами синхронизации. Как-то так.
Кодом людям нужно помогать!
Re[5]: контроллер памяти
От: Sharov Россия  
Дата: 10.04.23 11:31
Оценка:
Здравствуйте, Mr.Delphist, Вы писали:

MD>Однако определённый эффект на соседние ядра это тоже оказывает, поэтому, например, нельзя "бесплатно" (с точки зрения производительности) делать активную запись двумя потоками в две соседних ячейки памяти, если они попадают в одну кэш-линию. По каждому сигналу инвалидации кэш-линии, контроллер памяти будет ставить другое ядро на холд при попытке обращения к соседней ячейке, пока не синхронизирует два экземпляра этой кеш-линии. Хотя казалось бы, зачем тут синхронизация исполнения — ведь каждый поток пишет только в свою ячейку и никак не работает с соседней (гуглить false sharing).


А контроллер памяти что-то знает про L1\L2\L3, т.е. он ли решает, что какой-то процессор\ядро надо на холд
поставить? Мне казалось, это какая-то процессораная логика внутри цпу решает.
Кодом людям нужно помогать!
Re[9]: Memory barrier не могу понять что это
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 10.04.23 11:45
Оценка: 6 (1)
Здравствуйте, Sharov, Вы писали:

S>lock-free на уровне железе нифига не lock-free


Так не все ж алгоритмы, требующие атомарности и исключительности, подразумевают более долгое ожидание, чем требуется на банальную синхронизацию доступа к одной-двум ячейкам памяти. Даже обычный инкремент разделяемого счетчика традиционно было принято заворачивать в критическую секцию, которая традиционно же работала через примитивы синхронизации ОС, влекущие обращение к планировщику ядра. Замена на аппаратно атомарную операцию как раз и превращает действие в lock-free, подразумевая, что никто не тормозится дольше, чем это требуется на аппаратное выполнение команды в самом неудачном случае.

Кроме этого, многие lock-free алгоритмы не требуют, чтобы действие непременно выполнялось определенным потоком. В ряде случаев достаточно, чтобы его выполнил любой поток, который первым сумел получить доступ к ресурсу.

Ну а продвинутые lock-free алгоритмы еще и подразумевают сотрудничество между потоками. Если один выполнил команду типа test-and-set и получил нуль (ресурс был свободен), он выбирает одну последовательность действий, а другой, получив не нуль — другую. Задача в том, чтобы завершить операцию за некоторое разумное количество таких шагов, по времени заведомо выигрывающее у алгоритмов с ожиданием.
Re[6]: контроллер памяти
От: Mr.Delphist  
Дата: 10.04.23 18:54
Оценка:
Здравствуйте, Sharov, Вы писали:

S>А контроллер памяти что-то знает про L1\L2\L3, т.е. он ли решает, что какой-то процессор\ядро надо на холд

S>поставить? Мне казалось, это какая-то процессораная логика внутри цпу решает.

Думаю, в современных процах очень тяжело провести чёткую границу где заканчивается контроллер и начинается сам CPU, но для простоты картины да, можно считать контроллер отдельным модулем. Иначе как бы разные процессоры узнавали об изменениях в данных со стороны своих соседей? Речь не про многоядерность (там можно эту логику на тот же чип вкрячить), а про многопроцессорные конфигурации. Собственно, поэтому ранние двухпроцессорные сборки на Pentium и были бессмысленными для большинства применений — процессорам приходилось играть по максимально пессимистичному варианту синхронизации из-за неразвитой на тот момент механики согласования доступа к данным.
Re[7]: контроллер памяти
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 11.04.23 04:25
Оценка:
Здравствуйте, Mr.Delphist, Вы писали:

MD>можно считать контроллер отдельным модулем. Иначе как бы разные процессоры узнавали об изменениях в данных со стороны своих соседей?


Обмениваясь друг с другом по магистрали.

MD>ранние двухпроцессорные сборки на Pentium


Ранние были на 486. В нем и появилась команда cmpxchg.

MD>были бессмысленными для большинства применений


Те, кто их применял, были вполне довольны.
Re[4]: Memory barrier не могу понять что это
От: Doc Россия http://andrey.moveax.ru
Дата: 12.04.23 07:40
Оценка:
Здравствуйте, kov_serg, Вы писали:

D>>Спасибо, но я бы не писал на русскоязычный форум, если бы знал английский

_>Это не должно вас останавливать.

Более того, можно открыть видео в Yandex браузере и он сам предложит перевести аудио на русский.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.