Одновременное чтение/запись указателя в многопроцес. системе
От: tnikolai  
Дата: 23.09.09 08:51
Оценка:
Пусть в указателе хранилось значение А. Один из процессоров записывает в него значение В, а другой процессор считывает значение этого указателя.
Какие значения могут быть считаны? Только А и В? Может ли случится что в этот момент запишутся только первые 2 байта В, а вторые останутся от А, или ещё какая нибудь проблемма.
Re: Одновременное чтение/запись указателя в многопроцес. сис
От: Кодт Россия  
Дата: 23.09.09 09:39
Оценка: +1 :)
Здравствуйте, tnikolai, Вы писали:

T>Пусть в указателе хранилось значение А. Один из процессоров записывает в него значение В, а другой процессор считывает значение этого указателя.

T>Какие значения могут быть считаны? Только А и В? Может ли случится что в этот момент запишутся только первые 2 байта В, а вторые останутся от А, или ещё какая нибудь проблемма.

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

А на нормальных платформах специально для этого есть средства блокировки — машинные инструкции типа LOCK и апишные функции типа InterlockedXXXXX (см. документацию к своей платформе).

Но даже если ты избавишься от гонок при чтении-записи одной переменной, — придётся удостовериться, что не остались гонки большего масштаба. Вообще, lock-free программирование — чертовски увлекательно и нетривиально.
Перекуём баги на фичи!
Re: Одновременное чтение/запись указателя в многопроцес. сис
От: remark Россия http://www.1024cores.net/
Дата: 23.09.09 11:31
Оценка: +1
Здравствуйте, tnikolai, Вы писали:

T>Пусть в указателе хранилось значение А. Один из процессоров записывает в него значение В, а другой процессор считывает значение этого указателя.

T>Какие значения могут быть считаны? Только А и В? Может ли случится что в этот момент запишутся только первые 2 байта В, а вторые останутся от А, или ещё какая нибудь проблемма.

На всех современных распространённых архитектурах (IA-32, Intel64, IA-64, SPARC, POWER) запись и чтение выровненных машинных слов (указателей) атомарно.
В принципе можно представить какой-то микроконтроллер, на котором указатель 16 бит, а шина памяти только 8 бит; но это совсем отдельная песня, тем более что нужно иметь ещё и многопроцессорную систему из таких микроконтроллеров.

На архитектуре x86 (IA-32, Intel64) атомарно чтение и запись выровненных данных размером 1, 2, 4, 8 и 16 байт.

Однако атомарность не единственная проблема, тебе так же необходимо учитывать упорядочивание. Иначе может получиться так, что поток считает новое значение указателя, но вот данные по этому указателю считаются совсем не те, что ты ожидаешь. Смотри:
http://www.rsdn.ru/forum/philosophy/3181311.1.aspx
Автор: remark
Дата: 20.11.08



1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: Одновременное чтение/запись указателя в многопроцес.
От: tnikolai  
Дата: 23.09.09 12:08
Оценка:
R>На всех современных распространённых архитектурах (IA-32, Intel64, IA-64, SPARC, POWER) запись и чтение выровненных машинных слов (указателей) атомарно.
R>В принципе можно представить какой-то микроконтроллер, на котором указатель 16 бит, а шина памяти только 8 бит; но это совсем отдельная песня, тем более что нужно иметь ещё и многопроцессорную систему из таких микроконтроллеров.

R>На архитектуре x86 (IA-32, Intel64) атомарно чтение и запись выровненных данных размером 1, 2, 4, 8 и 16 байт.


R>Однако атомарность не единственная проблема, тебе так же необходимо учитывать упорядочивание. Иначе может получиться так, что поток считает новое значение указателя, но вот данные по этому указателю считаются совсем не те, что ты ожидаешь. Смотри:

R>http://www.rsdn.ru/forum/philosophy/3181311.1.aspx
Автор: remark
Дата: 20.11.08


У меня есть односвязный список
struct element {
void * data;
element * next;}
Из одного потока идёт добавление в конец новых элементов, после добавления элемента к его данным уже не обращаются. next у нового эл. = null. Как подготовится новый элемент, в next записывается его указатель.

А в другом потоке идёт работа с элементами с другого конца списка. Как у элемента next==null, ожидание.

В этом случае возможны проблеммы?
Re[3]: Одновременное чтение/запись указателя в многопроцес.
От: remark Россия http://www.1024cores.net/
Дата: 23.09.09 12:33
Оценка:
Здравствуйте, tnikolai, Вы писали:

T>У меня есть односвязный список

T>struct element {
T>void * data;
T>element * next;}
T>Из одного потока идёт добавление в конец новых элементов, после добавления элемента к его данным уже не обращаются. next у нового эл. = null. Как подготовится новый элемент, в next записывается его указатель.

T>А в другом потоке идёт работа с элементами с другого конца списка. Как у элемента next==null, ожидание.


T>В этом случае возможны проблеммы?


Да, возможны. Вот я постил пример аналогичной spsc очереди:
http://software.intel.com/en-us/articles/single-producer-single-consumer-queue/

Эта реализация под платформу x86 (IA-32, Intel64), Intel C++. Для других платформ необходимо портировать функции load_consume()/store_release(). Общего рецепта сейчас нет (пока нет std::atomic<>), всё зависит от конкретной аппаратной платформы и компилятора.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: Одновременное чтение/запись указателя в многопроцес.
От: tnikolai  
Дата: 23.09.09 13:10
Оценка:
T>>В этом случае возможны проблеммы?

R>Да, возможны. Вот я постил пример аналогичной spsc очереди:

R>http://software.intel.com/en-us/articles/single-producer-single-consumer-queue/

R>Эта реализация под платформу x86 (IA-32, Intel64), Intel C++. Для других платформ необходимо портировать функции load_consume()/store_release(). Общего рецепта сейчас нет (пока нет std::atomic<>), всё зависит от конкретной аппаратной платформы и компилятора.



А какие именно проблеммы возможны?
Re[5]: Одновременное чтение/запись указателя в многопроцес.
От: remark Россия http://www.1024cores.net/
Дата: 23.09.09 13:17
Оценка:
Здравствуйте, tnikolai, Вы писали:

T>>>В этом случае возможны проблеммы?


R>>Да, возможны. Вот я постил пример аналогичной spsc очереди:

R>>http://software.intel.com/en-us/articles/single-producer-single-consumer-queue/

R>>Эта реализация под платформу x86 (IA-32, Intel64), Intel C++. Для других платформ необходимо портировать функции load_consume()/store_release(). Общего рецепта сейчас нет (пока нет std::atomic<>), всё зависит от конкретной аппаратной платформы и компилятора.


T>А какие именно проблеммы возможны?


Потребитель увидит корректный ненулевой next, но после этого считает некорректный data, или увидит и корректный data, но считает некорректные данные по указателю data.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[6]: Одновременное чтение/запись указателя в многопроцес.
От: tnikolai  
Дата: 23.09.09 15:06
Оценка:
Здравствуйте, remark, Вы писали:

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


T>>>>В этом случае возможны проблеммы?


R>>>Да, возможны. Вот я постил пример аналогичной spsc очереди:

R>>>http://software.intel.com/en-us/articles/single-producer-single-consumer-queue/

R>>>Эта реализация под платформу x86 (IA-32, Intel64), Intel C++. Для других платформ необходимо портировать функции load_consume()/store_release(). Общего рецепта сейчас нет (пока нет std::atomic<>), всё зависит от конкретной аппаратной платформы и компилятора.


T>>А какие именно проблеммы возможны?


R>Потребитель увидит корректный ненулевой next, но после этого считает некорректный data, или увидит и корректный data, но считает некорректные данные по указателю data.



Для MSVC объявить в структуре элемента указатели data и next как volatile, и перед записью адреса нового эл. в next вызвать _WriteBarrier() будет достаточно?
Re[7]: Одновременное чтение/запись указателя в многопроцес.
От: remark Россия http://www.1024cores.net/
Дата: 23.09.09 15:08
Оценка:
Здравствуйте, tnikolai, Вы писали:

T>>>А какие именно проблеммы возможны?


R>>Потребитель увидит корректный ненулевой next, но после этого считает некорректный data, или увидит и корректный data, но считает некорректные данные по указателю data.


T>Для MSVC объявить в структуре элемента указатели data и next как volatile, и перед записью адреса нового эл. в next вызвать _WriteBarrier() будет достаточно?


Для MSVC будет достаточно просто объявить next как volatile.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[8]: Одновременное чтение/запись указателя в многопроцес.
От: tnikolai  
Дата: 23.09.09 15:46
Оценка:
R>>>Потребитель увидит корректный ненулевой next, но после этого считает некорректный data, или увидит и корректный data, но считает некорректные данные по указателю data.

R>Для MSVC будет достаточно просто объявить next как volatile.


А каким образом volatile для next сделает указатель data и то на что он указывает корректным? Если в обеих случаях потребитель увидит корректный ненулевой next.

Всётаки суть не понятна.
Re[9]: Одновременное чтение/запись указателя в многопроцес.
От: remark Россия http://www.1024cores.net/
Дата: 23.09.09 16:12
Оценка:
Здравствуйте, tnikolai, Вы писали:

R>>>>Потребитель увидит корректный ненулевой next, но после этого считает некорректный data, или увидит и корректный data, но считает некорректные данные по указателю data.


R>>Для MSVC будет достаточно просто объявить next как volatile.


T>А каким образом volatile для next сделает указатель data и то на что он указывает корректным? Если в обеих случаях потребитель увидит корректный ненулевой next.


T>Всётаки суть не понятна.



Ключевое слово — упорядочивание.
Может быть так: производитель вначале сохранит указатель next, а только потом data и данные в data. Соотв. потребитель загрузит next, но когда будет считывать data, считает от туда мусор. Использование volatile это предотвратит.
Видимость последовательной консистентности (sequential consistency) обеспечивается только в рамках одного потока. В многопоточном окружении порядок обращений к памяти (как видно другим потокам) не сохраняется (т.е. не такой как записано у тебя в коде).



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[9]: Одновременное чтение/запись указателя в многопроцес.
От: OdesitVadim Украина  
Дата: 23.09.09 16:14
Оценка:
Здравствуйте, tnikolai, Вы писали:

R>>Для MSVC будет достаточно просто объявить next как volatile.


T>А каким образом volatile для next сделает указатель data и то на что он указывает корректным? Если в обеих случаях потребитель увидит корректный ненулевой next.


T>Всётаки суть не понятна.

правильно, потому что не поможет. если два процесса/треда только читают, или пишет только и только один, а остальные читают, то ещё можно понадеятся. А если читать/писать могут многие, то надеятся нельзя. Залочил мютексом/критической секцией, прочитал, проанализовал, поменял, разлочил.
Re[10]: Одновременное чтение/запись указателя в многопроцес.
От: Voinov Россия http://www.svoinov.ru
Дата: 23.09.09 19:06
Оценка:
Здравствуйте, OdesitVadim, Вы писали:

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


R>>>Для MSVC будет достаточно просто объявить next как volatile.


T>>А каким образом volatile для next сделает указатель data и то на что он указывает корректным? Если в обеих случаях потребитель увидит корректный ненулевой next.


T>>Всётаки суть не понятна.

OV>правильно, потому что не поможет. если два процесса/треда только читают, или пишет только и только один, а остальные читают, то ещё можно понадеятся. А если читать/писать могут многие, то надеятся нельзя. Залочил мютексом/критической секцией, прочитал, проанализовал, поменял, разлочил.

Вообще, если адреса выровняны по границе чтения кэш-памяти (обычно 16 байт), то дополнительной необходимости в синхронизации для мультипроцессорных систем не возникает. Для однопроцессорных систем в этом случае любое единичное обращение в память (в соответствии с IA-32) является атомарным, т.е. другой "процесс" не может, скажем, переписать значение сохраняемого в память указателя "наполовину", т.к. инструкции в однопроцессорной системе не могут выполниться "наполовину" в силу переключения задач и прерываний по границам инструкций.

Если посмотреть трассу обращения процессора в память, то всё будет выровняно на размер линейки в кэше — а все транзакции к памяти так и идут. Если говорить о Windows, то для сложных операций, включающих помимо сохранения/чтения из памяти ещё и арифметические операции (инкремент/декремент) есть функции, которые позволяют это сделать атомарно (см. Interlocked* функции). Если сначала нужно сделать load, затем какую-то операцию, а потом store, атомарность нарушается, поэтому рекомендуется использовать синхронизацию.
Re[9]: Одновременное чтение/запись указателя в многопроцес.
От: Sergey Chadov Россия  
Дата: 24.09.09 14:51
Оценка:
Здравствуйте, tnikolai, Вы писали:

T>А каким образом volatile для next сделает указатель data и то на что он указывает корректным? Если в обеих случаях потребитель увидит корректный ненулевой next.


T>Всётаки суть не понятна.


Конкретно MSVC увидев volatile самостоятельно расставляет барьеры.
--
Sergey Chadov

... << RSDN@Home 1.2.0 alpha rev. 685>>
Re[10]: Одновременное чтение/запись указателя в многопроцес.
От: Pepel Беларусь  
Дата: 25.09.09 12:00
Оценка:
Джеф Рихтер вам в помощь , он разжевывает досконально эту проблему
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.