Re[6]: Реализация критической секции на Interlocked.Exchange
От: CreatorCray  
Дата: 18.06.08 14:53
Оценка:
Здравствуйте, merk, Вы писали:

M>я думал, по старинке, что она просто обеспечивает непрерываемый обмен двух переменных.

Именно. Осмысливать суть ее работы следует в контексте двух и более одновременно работающих ядер/процов.

M>ну..иногда надо, в особо тяжелых случаях.

Отнюдь. Интенсивно курим доки по Lock-free алгоритмам
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[6]: Реализация критической секции на Interlocked.Exchange
От: merk Россия  
Дата: 18.06.08 15:02
Оценка: :)
Здравствуйте, netch80, Вы писали:

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


N>>>Вместо того, чтобы ругаться грозными словами — Вы бы почитали чего-нибудь по теме

M>>и читал по теме..и писал по теме, могу кинуть код ядра реально работающей RTOS.

N>Тогда Вы слишком странно пишете.


N>Переведите, пожалуйста, это предложение. При чём тут "сталкивание с шедулера"? Большинство блокировок типа "захватили мьютекс, поменяли два поля, отпустили мьютекс" действительно кратковременные — значительно короче, чем вход в режим ядра.

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



M>> если вы даете гарантию, что спинлоком можно эффективно решить все проблемы реальной синхронизации..то это немножко смешно. иногда! спинлок быстрей. в некотором количестве случаев. как общее решение это неприменимо.


N>Конечно, не даю. Конечно, как общее решение неприменимо. Но разве автор того кода говорил, что у него единственный допустимый вариант? Чего это Вы вдруг на него обрушились?


N>>>Во-вторых, есть ситуации, когда переход в спячку под управлением внешнего шедулера просто недопустим. Их мало, но они есть — например, работа того же шедулера, или истинного обработчика аппаратного прерывания.

M>>не спячку, а ожидание.

N>В данном случае это ожидание — именно спячка потому что спинлока тоже ждут, но иначе.


M>> общепринято, что тред переходит в режим wait. ожидание события. коим и является освобождение обьекта синхронизации.

M>>что касается вашего опасения, что это мол долго, то реализуется это очень просто
M>>время тратится на
M>>1. проверка занятости сьютекса(_счетчик >0 && _owner!=CurrentThread)-> перевод обьекта CurrentThread из двухсвязного списка активных тредов шедулера в такой же список ожидающих на этом мьютексе. переключение контекста. ФСЕ!

N>Это Ваше "фсё!" предполагает, что те самые списки шедулера доступны приложению из режима пользователя. Верю, что для RTOS это достаточно частый случай. Но в общем случае я бы такого не предполагал. Например, для той же Windows уход в спячку с ожиданием освобождения мьютекса делается уже средствами ядра — в то время как тред, захвативший объект крит.секции, почему-то тоже спит (мало ли чего он ждёт — может, страница памяти с диска грузится). Полагаться на шедулер и обязательную активность данного процесса некорректно.


косорукая винда — не показатель. ну не хочу я рассматривать win32 как изящный пример концептуальной системной библиотеки.

N>Не делайте вид, что Вы не оценили сарказм. Но Ваше чрезмерное тяготение в подходах к одному, совсем не распространённому, типу ситуации (один процессор, слабое разделение прав), который соответствует Вашим письмам — совсем не отражает типичную для многих других картину. И, обрушиваясь на них только потому, что условия не соответствуют Вашим — делаете хуже только себе.

Все! Понял, больше не буду. Большинство выч систем в мире имеют в себе N процессоров, миллионы тредов которые меняют по два поля в каком-то обьекте данных.
Большинство систем в мире носятся на самом деле в кармане, ездят, летают, плавают. И даже не стоят на столе. не говоря уже о мейнфреймах. и этот разрыв будет только увеличиваться.
и наша задача, чтобы это большинство — работало.
Re[4]: итог
От: merk Россия  
Дата: 18.06.08 15:34
Оценка: 6 (1) -2
Здравствуйте, С. Ю. Губанов, Вы писали:

СЮГ>Здравствуйте, merk, Вы писали:


M>>это не критсекция, это гуано.


СЮГ>У меня сейчас есть несколько свободных минут, поэтому я Вам отвечу, хотя Вы этого совершенно не заслуживаете так как Вы чрезвычайно самонадеяны и публично делаете неправильные обобщающие утверждения, а почти ничего не знаете. Вам нужно ещё очень многому научиться.


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

СЮГ>Так вот, описанная мной критическая секция используется в случае когда нужно синхронизировать доступ к очень быстро выполняющемуся участку кода. Быстро — это порядка 20 тактов процессора. Примерно столько же тактов нужно для Interlocked.Exchange на Athlon 64 X2. Пример такого быстрого кода: положить/взять чего-то в очередь, в стек или какой-то другой контейнер. Наибольший выигрыш получается когда количество потоков пытающихся сделать это одновременно равно нескольким сотням. Предлагаю Вам сравнить скорость обычного дотнетного lock () с моей критической секцией в Linux Mono хотя бы на одной сотне потоков конкурирующих за вход в неё. Вы будете приятно удивлены огромаднейшей разницей в скорости работы.


теория. если время нахождения внутри вашего синхроучастка сравнимо с врмением переключения тредов, внутри участка вас могут переключить. то есть в дело вмешиваются еще доп факторы. если тред хозяин участка переключат, то тред сидящий в полинге задержится в нем на доп время. то есть в дело вступают еще и приоритеты. а если многозадачность вытесняющая..., а высокоприоритетные треды получают все время проца, то вообще все встанет, поскольку высокоприоритетный в полинге будет блокировать низкоприоритеный в участке. бумц. казалось бы правильная фича вообще сломалась!
приехали...
как много оказалось условий, при которых ваш код можно назвать кодом для критсекции.
а?
Re[6]: Реализация критической секции на Interlocked.Exchange
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 18.06.08 16:42
Оценка: +1
Здравствуйте, merk, Вы писали:

N>>А теперь про переход в монопольный режим. Во-первых, это наиболее грубый из всех возможных вариантов реализации. Я уже понял, что про wait-free и про lock-free подходы Вы ничего не слышали; тогда почитайте здесь же про них, надеюсь, понравится. Но Вы категорически ограничиваетесь одним процессором! Все Ваши методы типа "запрет переключения" работают только на одном процессоре. Для синхронизации между несколькими процессорами используются другие методы, начиная со спинлоков. В коде, который Вы ругали в следующем письме, приведён именно спинлок. И то, как Вы на него обрушились, свидетельствует именно об устарелости знаний (когда там первые SMP появились?) Особенно это странно сейчас, когда двухъядерный процессор стоит на любом свежем десктопе.


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


Должен что? Тут пропущено слово.

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


Ну тогда надо действительно как-то это решать. Например, сказать более конкретно, чего хочется.

N>>Вот в том-то и дело, что не "однозначно", или по крайней мере этот hidden_mutex.lock() делается не как тупой системный вызов. У Sun это названо adaptive mutex, у других — другими именами, но смысл в том, что если interlocked exchange на уровне пользователя даёт захват мьютекса, то этого достаточно, чтобы не просить лишнего от ядра. А по статистике это не менее половины всех захватов (разумеется, в грамотно построенном коде).

M>ФСЕ! пошел читать про этот могучий exchange. он уже оказывает и мьютексы захватывает...
M> ладно закопали. думал он просто меняет переменные.

А какой критерий захвата мьютекса? Вот например классический ядерный мьютекс FreeBSD — в поле владения у него 32-битное значение из 8 битов на номер процессора (0xff — свободен) и 24 бита на рекурсивный счётчик. Захват делается проверкой, что старое значение содержит 0xff в старшем бите, и CAS с этим значением как старым и целевым (свой процессор и 1 в счётчике) как новым. Зачем ещё что-то, если успешный захват сам по себе даёт все необходимые данные? Вот если он не состоялся с N-й попытки, вот тогда уже надо с очередями играться.

M>Это в .NET? это спинлок? что это ваще? :)


А Вы не ёрничайте и не пытайтесь смотреть свысока на "какую-то .NET что это ваще", а подумайте. Это всегда полезно:)

N>>В WinAPI, critical section отличается от mutex именно тем, что видима только в одном процессе, но не в другом. Поэтому для неё можно использовать адаптивный захват с ограниченным количеством попыток (а вот если этого недостаточно — оно берёт уже ядерный мьютекс).

M>я так и думал :) и никакой excahge тут не причем. его отсутсвие позволяет решить проблему не менее принципиально.

Ошибаетесь. В многопроцессорном случае, без атомарных операций типа того же CAS (compare and swap), представителем которого является Interlocked.exchange, не обойтись. Даже если Вы успешно заблокировали текущий процессор от переключения на другую задачу и даже запретили все прерывания — другой процессор всё равно сможет влезть. Вот тут-то и приходится использовать атомарные операции — или спинлок на общение с группой мьютексов (можно даже каждому свой), или групповые атомарные обмены, или любой другой вариант — но никак не без него.

И я это Вам в прошлом сообщении писал — но Вы упорно цепляетесь за однопроцессорный случай.

N>>Это важно. Потому что мьютекс — это не просто семафор с не более чем 1 в счётчике. Это семафор, который умеет, в большинстве реализаций, становиться рекурсивным (то есть один и тот же агент может захватывать его много раз), или с контролем ошибок (повторный захват тем же агентом вызывает генерацию ошибки). Для семафора Дейкстры реализация подобных возможностей слишком дорога и неэффективна. Мьютекс оптимизируется в другом направлении, чем семафор с произвольным счётчиком.

M>а то мы не знали. :)

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

N>>Переведите, пожалуйста, это предложение. При чём тут "сталкивание с шедулера"? Большинство блокировок типа "захватили мьютекс, поменяли два поля, отпустили мьютекс" действительно кратковременные — значительно короче, чем вход в режим ядра.

M>Имеется ввиду перемещение из списка активных в список ожидающих событие.

Ах, вот какой у Вас жаргон? Ну так очередь ожидающих вообще-то тоже под управлением шедулера.

M>Что за задачи вы там решаете? когда много тредов меняют два поля??? зачем так много тредов и так мало полей?:)


Ситуации бывают самые разные. Например, добавить в список — типичная задача типа "поменять два поля" (даже если эти поля далеко от самого мьютекса). А списки работ/событий/etc. — для ряда дизайнов и задач являются основным средством.

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


Да, у меня действительно во многом сильносвязанные системы. Например, VoIP софтсвитч. Разные треды делят несколько общих баз, очередей и пулов, на всё это накладывается многонитевый движок событий (очень извращённая штука, но без неё никак).

M>кстати очевидно, что если два треда сильно уж слижком часто занимаюся синхронизацией — это говорит, об сильной зависимости. возможно их нужно соединить в один. ну или что-то вроде того.


Невозможно — они должны работать раздельно.

M>косорукая винда — не показатель. ну не хочу я рассматривать win32 как изящный пример концептуальной системной библиотеки.


Как изящный — может, и нет (не хочу сильно спорить о вкусах). Но как контекст _данного_ треда — да. А в данном случае мы к тому же говорим о весьма вменяемой подсистеме.

M>Все! Понял, больше не буду. Большинство выч систем в мире имеют в себе N процессоров, миллионы тредов которые меняют по два поля в каком-то обьекте данных.

M>Большинство систем в мире носятся на самом деле в кармане, ездят, летают, плавают. И даже не стоят на столе. не говоря уже о мейнфреймах. и этот разрыв будет только увеличиваться.

С точки зрения голого количества — да. А вот с точки зрения приложенной работы на них — нет. Как известно, 80-90% всей разработки приходится даже не на продажное ПО, а на внутреннее.

M>и наша задача, чтобы это большинство — работало.


Да пожалуйста, сколько угодно. Я тоже однажды на embedded работал, специфику помню. Но надо же и понимать, что она, мягко говоря, не единственная...
The God is real, unless declared integer.
Re[4]: и совсем уж про очередь...вспомнилось
От: merk Россия  
Дата: 18.06.08 16:47
Оценка: -2 :)
Здравствуйте, С. Ю. Губанов, Вы писали:
СЮГ>Так вот, описанная мной критическая секция используется в случае когда нужно синхронизировать доступ к очень быстро выполняющемуся участку кода. Быстро — это порядка 20 тактов процессора. Примерно столько же тактов нужно для Interlocked.Exchange на Athlon 64 X2. Пример такого быстрого кода: положить/взять чего-то в очередь, в стек или какой-то другой контейнер. Наибольший выигрыш получается когда количество потоков пытающихся сделать это одновременно равно нескольким сотням. Предлагаю Вам сравнить скорость обычного дотнетного lock () с моей критической секцией в Linux Mono хотя бы на одной сотне потоков конкурирующих за вход в неё. Вы будете приятно удивлены огромаднейшей разницей в скорости работы.

а что у вас за очередь такая?
безукоризненная очередь должна обеспечивать следующий функционал:
1. число кладущих и число берущих потоков произвольно
2. если очередь пуста — берущий уходит в ожидание(не поллинг!!!) события — очередь стала не пуста. причем с таймаутом, ибо он не может сидеть в ожидании вечно.
3. если очередь переполнилась(бесконечных очередей не бывает) — кладущий уходит в ожидание события "есть место для нового элемента", опять же с таймаутом, по той же причине.
но ваши "секции" защищают только непосредственное заталкивание обьекта в очередь, при условии, что она не переполнена, и взятие, при условии, что не пуста.
если очередь пуста, ваш берущий будет вынужден(в силу вашей реализации) находиться в поллинге. то есть опять двадцать пять, грузим проц, но уже в другом месте.
короче. очереди и стеки, как минимум на таких секциях реализуются или просто некорректно, или активно грузят проц. таймаут не упоминается.
возразите.
Re[7]: Реализация критической секции на Interlocked.Exchange
От: merk Россия  
Дата: 18.06.08 17:08
Оценка: -1
Здравствуйте, netch80, Вы писали:

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


N>>>А теперь про переход в монопольный режим. Во-первых, это наиболее грубый из всех возможных вариантов реализации. Я уже понял, что про wait-free и про lock-free подходы Вы ничего не слышали; тогда почитайте здесь же про них, надеюсь, понравится. Но Вы категорически ограничиваетесь одним процессором! Все Ваши методы типа "запрет переключения" работают только на одном процессоре. Для синхронизации между несколькими процессорами используются другие методы, начиная со спинлоков. В коде, который Вы ругали в следующем письме, приведён именно спинлок. И то, как Вы на него обрушились, свидетельствует именно об устарелости знаний (когда там первые SMP появились?) Особенно это странно сейчас, когда двухъядерный процессор стоит на любом свежем десктопе.


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


N>Должен что? Тут пропущено слово.


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

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


N>>>В WinAPI, critical section отличается от mutex именно тем, что видима только в одном процессе, но не в другом. Поэтому для неё можно использовать адаптивный захват с ограниченным количеством попыток (а вот если этого недостаточно — оно берёт уже ядерный мьютекс).

M>>я так и думал и никакой excahge тут не причем. его отсутсвие позволяет решить проблему не менее принципиально.

N>Ошибаетесь. В многопроцессорном случае, без атомарных операций типа того же CAS (compare and swap), представителем которого является Interlocked.exchange, не обойтись. Даже если Вы успешно заблокировали текущий процессор от переключения на другую задачу и даже запретили все прерывания — другой процессор всё равно сможет влезть. Вот тут-то и приходится использовать атомарные операции — или спинлок на общение с группой мьютексов (можно даже каждому свой), или групповые атомарные обмены, или любой другой вариант — но никак не без него.


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

N>И я это Вам в прошлом сообщении писал — но Вы упорно цепляетесь за однопроцессорный случай.


N>>>Это важно. Потому что мьютекс — это не просто семафор с не более чем 1 в счётчике. Это семафор, который умеет, в большинстве реализаций, становиться рекурсивным (то есть один и тот же агент может захватывать его много раз), или с контролем ошибок (повторный захват тем же агентом вызывает генерацию ошибки). Для семафора Дейкстры реализация подобных возможностей слишком дорога и неэффективна. Мьютекс оптимизируется в другом направлении, чем семафор с произвольным счётчиком.


N>>>Переведите, пожалуйста, это предложение. При чём тут "сталкивание с шедулера"? Большинство блокировок типа "захватили мьютекс, поменяли два поля, отпустили мьютекс" действительно кратковременные — значительно короче, чем вход в режим ядра.

M>>Имеется ввиду перемещение из списка активных в список ожидающих событие.

N>Ах, вот какой у Вас жаргон? Ну так очередь ожидающих вообще-то тоже под управлением шедулера.

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

M>>Что за задачи вы там решаете? когда много тредов меняют два поля??? зачем так много тредов и так мало полей?


к тому же в самом низу топика я написал как должна быть реализована очередь(что хотел делать автор). и ваших критсекций просто не достаточно для корректной реализации.
Re[11]: Реализация критической секции на Interlocked.Exchang
От: remark Россия http://www.1024cores.net/
Дата: 18.06.08 21:20
Оценка:
Здравствуйте, netch80, Вы писали:

N>Большинству программистов вопрос барьеров _пока_ не важен, потому что в x86 форсированная сериализация операций чтения и записи (то есть защищаемые данные гарантированно запишутся в память раньше, чем 0 в спинлок). Но Intel обещает это скоро отключить.



А откуда дровишки? Можно какие-нибудь ссылки?
Они ж вроде как только недавно как раз задокументировали свою модель памяти, и там написано, что load имеет семантику acquire, а store — release.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[12]: Реализация критической секции на Interlocked.Exchang
От: remark Россия http://www.1024cores.net/
Дата: 18.06.08 21:33
Оценка: +1
Здравствуйте, vdimas, Вы писали:

V>Вот тут действительно, стоит поэкспериментировать, что быстрее, один Interlocked.Exchange, или пара барьеров памяти. (Хотя второй опциональный, ИМХО, по крайней мере, когда речь идет об однопроцессорной машине).


На однопроцессорной машине и Interlocked не нужен.

V>Хм, тогда имеет смысл сделать две реализации, одну только для чтения защищаемых данных (экономим 1 барьер), другую — для чтения и записи. Учитывая, что в большинстве сценариев защищаемые данные пишутся гораздо реже, чем читаются, это может иметь смысл.


При чтении нужны оба барьера. Барьеры — это всегда игра для двух (потоков). Если барьеры выполняет только один поток, то эффекта от них не будет.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[12]: Реализация критической секции на Interlocked.Exchang
От: remark Россия http://www.1024cores.net/
Дата: 18.06.08 21:35
Оценка:
Здравствуйте, Were, Вы писали:

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


N>>А сделали для операции инлайнинг (это на C#-то?) или нет, если она корректно описана — с барьерами — уже неважно.


W>Хм с барьерами-то конечно неважно. Я комментировал код без барьеров )


W>
W>private void ExitCriticalSection ()
W>{
W>    this.interlockedFlag = 0;
W>}
W>


Есть здесь барьер или нет — нельзя сказать. Это зависит от определения переменной interlockedFlag. Если она volatile, то необходимый барьер здесь есть, и это вполне законный cli код.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[11]: Реализация критической секции на Interlocked.Exchang
От: remark Россия http://www.1024cores.net/
Дата: 18.06.08 21:38
Оценка:
Здравствуйте, netch80, Вы писали:

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


Барьеры никак не влияют на задержку. Если бы было какое-то средство для ускорения работы с памятью, поверь мне, оно было бы просто включено всегда по-умолчанию.
Хотя барьер после освобождения критической секции тоже иногда ставится. Но это уже имеет отношение к fairness, и вообще очень спорный подход для общего случая.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: Реализация критической секции на Interlocked.Exchange
От: remark Россия http://www.1024cores.net/
Дата: 18.06.08 21:47
Оценка:
Здравствуйте, SergeyGubanov, Вы писали:

SG>Реализация критической секции на Interlocked.Exchange


SG>Объясните пожалуйста, а то никак не могу врубиться, почему ежели я реализую критическую секцию используя атомарную операцию обмена, то MSDN рекомендует писать так:


SG>Второй вариант правильный или нет?


Если flag объявлен как volatile, то да, если нет — то нет.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: Реализация критической секции на Interlocked.Exchange
От: remark Россия http://www.1024cores.net/
Дата: 18.06.08 21:52
Оценка: +1
Здравствуйте, Сергей Юрьевич Губанов, Вы писали:

СЮГ>Я тут, вобщем, написал тестовую програмку и запустил её на ночь. Сейчас пришёл на работу, смотрю -- работает. Она всю ночь совершала по 2 миллиона блокировок в секунду и не зависла. Машина двухядерная: Athlon-64 X2. Это конечно ещё ничего не доказывает, но на размышления наводит...


Это наводит на размышления, что это ничего не доказывает.
Во-первых, не видно объявление flag. Это в данном случае, определяет, корректный это код или нет.
Во-вторых, ловить ошибки алгоритмов синхронизации тестами неимоверно сложно. Составление тестов, которые ловят ошибки это целое искусство. В данном случае, допустим алгоритм некорректный, ну 2 потока одновременно вызвали Sleep(0), ну и что? Возможно это происходило за ночь. Возможно нет.
Программы с подобными ошибками работают *годами* до первого сбоя.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[7]: Реализация критической секции на Interlocked.Exchange
От: CreatorCray  
Дата: 18.06.08 22:42
Оценка:
Здравствуйте, netch80, Вы писали:

N>CAS (compare and swap), представителем которого является Interlocked.exchange

Небольшая поправка: CAS это InterlockedCompareExchange
Простой InterlockedExchange это для чутка более простых операций.

... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[8]: Реализация критической секции на Interlocked.Exchange
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 19.06.08 06:03
Оценка:
Здравствуйте, CreatorCray, Вы писали:

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


N>>CAS (compare and swap), представителем которого является Interlocked.exchange

CC>Небольшая поправка: CAS это InterlockedCompareExchange
CC>Простой InterlockedExchange это для чутка более простых операций.

Да, верно, я их слегка путаю в виндовых названиях.
The God is real, unless declared integer.
Re[12]: Реализация критической секции на Interlocked.Exchang
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 19.06.08 06:08
Оценка:
Здравствуйте, remark, Вы писали:

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


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


R>Барьеры никак не влияют на задержку. Если бы было какое-то средство для ускорения работы с памятью, поверь мне, оно было бы просто включено всегда по-умолчанию.


Это ты за слово "тянуть" зацепился?;)) Я имел в виду, чтобы запись нуля в ячейку не была раньше, чем запись тех данных, которые должны стать всем видимы до того, как лок освободится.

R>Хотя барьер после освобождения критической секции тоже иногда ставится. Но это уже имеет отношение к fairness, и вообще очень спорный подход для общего случая.


Угу, потому и только "желательно".
The God is real, unless declared integer.
Re[8]: Реализация критической секции на Interlocked.Exchange
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 19.06.08 07:30
Оценка: +1
Здравствуйте, merk, Вы писали:

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

N>>Должен что? Тут пропущено слово.
M>иемлось ввиду...ну вот есть программист и ему очень надо. ему обьясняют про синхронизацию — то и се... ну например про крит секцию. он приходит в сюда форум, и видит как типа удачно реализована крит секция в данном топике. типа спинлок. он радостно вставляет это в код...

Вы крайне своеобразно относитесь к другим программистам — судя по Вашим словам, они такие недоумки, что будут хвататься за любой пример кода, не смотря на то, насколько он адекватен задаче, корректен и так далее. Ладно, я бы поверил в такой подход по отношению к индусам (если верить слухам про них). Но на RSDN, мне до сих пор казалось, создано достаточно условий, чтобы так не поступали.

Откуда такое неверие в людей?

N>>Ошибаетесь. В многопроцессорном случае, без атомарных операций типа того же CAS (compare and swap), представителем которого является Interlocked.exchange, не обойтись. Даже если Вы успешно заблокировали текущий процессор от переключения на другую задачу и даже запретили все прерывания — другой процессор всё равно сможет влезть. Вот тут-то и приходится использовать атомарные операции — или спинлок на общение с группой мьютексов (можно даже каждому свой), или групповые атомарные обмены, или любой другой вариант — но никак не без него.

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

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

А Вы тут же обрушились со всей силы на него.

N>>Ах, вот какой у Вас жаргон? Ну так очередь ожидающих вообще-то тоже под управлением шедулера.

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

Где как. На RTOS — может быть. На обычной OS, тред, сидящий в read(), может сидеть так хоть годами — как делают getty на практически любом юниксе.

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


Ну есть и другие варианты. Но действительно так как активизация должна произойти из какого-то кода:) — это или регулярная задача, или обработчик прерывания. А механизмы могут быть разными — например, реализовывать пайп через только мьютексы некорректно, обычно используется что-то вроде condition variable.

M>>>Что за задачи вы там решаете? когда много тредов меняют два поля??? зачем так много тредов и так мало полей?:)

M>к тому же в самом низу топика я написал как должна быть реализована очередь(что хотел делать автор). и ваших критсекций просто не достаточно для корректной реализации.

Я перечитал все сообщения автора в этом треде и не вижу ни одного упоминания очереди. Мне кажется, что Ваше представление про наличие какой-то очереди в его задумке, мягко говоря, поспешно.
The God is real, unless declared integer.
Re[13]: Реализация критической секции на Interlocked.Exchang
От: vdimas Россия  
Дата: 19.06.08 08:52
Оценка:
Здравствуйте, remark, Вы писали:


R>При чтении нужны оба барьера. Барьеры — это всегда игра для двух (потоков). Если барьеры выполняет только один поток, то эффекта от них не будет.


Ну дык, пишущий делает барьер до и после записи, а все читающие — только перед чтением, я про экономию одного барьера говорил.
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[2]: Реализация критической секции на Interlocked.Exchange
От: С. Ю. Губанов Россия http://SergeyGubanov.narod.ru/
Дата: 19.06.08 09:01
Оценка:
Здравствуйте, remark, Вы писали:

R>Если flag объявлен как volatile, то да, если нет — то нет.


А Вы вообще как, знаете что такое язык C#? И что означает слово volatile в этом языке? Вы его с Си или с Си++ не перепутали случайно? Пожалуй, перепутали.

Напоминаю:

1) В языке C# есть такое правило, что если функция объявлена так: void F (ref int x) то фактический параметр x не может быть volatile.

2) int System.Threading.Interlocked.Exchange(ref int location1, int value)
Re[5]: итог
От: С. Ю. Губанов Россия http://SergeyGubanov.narod.ru/
Дата: 19.06.08 09:03
Оценка:
Здравствуйте, merk, Вы писали:

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


Большое спасибо, это очень важно, а я об этом позабыл. Надо будет принять меры.
Re[5]: и совсем уж про очередь...вспомнилось
От: С. Ю. Губанов Россия http://SergeyGubanov.narod.ru/
Дата: 19.06.08 09:09
Оценка:
Здравствуйте, merk, Вы писали:

M> 2. если очередь пуста — берущий уходит в ожидание


У меня он уходит на ожидание другим способом, не имеющим к этой критической секции никакого отношения.

А импульсы Monitor.Pulse я посылать не могу, у меня возможно и 16 миллионов сообщений в секунду. Импульсы же эффективны при сотне сообщений в секунду, но не при миллионах...
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.