OberonCore
https://forum.oberoncore.ru/

Реализация критической секции на Interlocked Exchange
https://forum.oberoncore.ru/viewtopic.php?f=31&t=1029
Страница 1 из 2

Автор:  Сергей Губанов [ Понедельник, 16 Июнь, 2008 11:16 ]
Заголовок сообщения:  Реализация критической секции на Interlocked Exchange

Вот, ежели я реализую критическую секцию используя атомарную операцию обмена, то MSDN рекомендует писать что-то вроде следующего:
Код:
if (System.Threading.Interlocked.Exchange(ref flag, 1) == 0)
{
  // ...
  // ...
  // ...
  System.Threading.Interlocked.Exchange(ref flag, 0);
}

А почему бы не написать попроще:
Код:
if (System.Threading.Interlocked.Exchange(ref flag, 1) == 0)
{
  // ...
  // ...
  // ...
  flag = 0;
}

Вроде второй вариант тоже правильный, или нет?

Автор:  Илья Ермаков [ Понедельник, 16 Июнь, 2008 11:44 ]
Заголовок сообщения:  Re: Реализация критической секции на Interlocked Exchange

В данном случае, может быть, и будет работать.

А вообще, если во время записи в переменную кто-то ещё может её читать, то надо использовать Interlocked. Может быть (теоретически, относительно тех. возможности конкр. процессоров не знаю) такая ситуация, что один процессор записал только часть слова, а второй уже полез читать.

Автор:  Wlad [ Понедельник, 16 Июнь, 2008 11:54 ]
Заголовок сообщения:  Re: Реализация критической секции на Interlocked Exchange

Сергей Губанов писал(а):
Вроде второй вариант тоже правильный, или нет?

Ёй! Лучше - не надо! - Неизвестно на какой проц, в недалёком и светлом будущем, это потом нативно скомпилено будет...

Автор:  Wlad [ Понедельник, 16 Июнь, 2008 12:09 ]
Заголовок сообщения:  Re: Реализация критической секции на Interlocked Exchange

Илья Ермаков писал(а):
такая ситуация, что один процессор записал только часть слова, а второй уже полез читать.

Не,... с частями слова - наврядли, но вот на счёт такого - вполне "ох-ох-ох":
Код:
mov eax,0 // или  xor eax,eax
// здесь уходим в другой поток, потом - продолжаем...
mov var,eax

В то время, как System.Threading.Interlocked.Exchange(ref flag, 1) скорее всего подразумевает компиляцию в команду, типа xchg на х86 (или её аналог на других архитектурах), которая в любых условиях и архитектурах выполняется гарантированно атомарно...

Автор:  Сергей Губанов [ Понедельник, 16 Июнь, 2008 12:22 ]
Заголовок сообщения:  Re: Реализация критической секции на Interlocked Exchange

Спасибо.

Автор:  Сергей Губанов [ Понедельник, 16 Июнь, 2008 12:45 ]
Заголовок сообщения:  Re: Реализация критической секции на Interlocked Exchange

Владимир Лось писал(а):
Код:
mov eax,0 // или  xor eax,eax
// здесь уходим в другой поток, потом - продолжаем...
mov var,eax


Не совсем понимаю чем это плохо? Ведь переменной flag всё равно будет присвоен 0, правда не мгновенно, а с небольшой задержкой.

Автор:  Wlad [ Среда, 18 Июнь, 2008 19:31 ]
Заголовок сообщения:  Re: Реализация критической секции на Interlocked Exchange

Сергей Губанов писал(а):
Владимир Лось писал(а):
Код:
mov eax,0 // или  xor eax,eax
// здесь уходим в другой поток, потом - продолжаем...
mov var,eax


Не совсем понимаю чем это плохо? Ведь переменной flag всё равно будет присвоен 0, правда не мгновенно, а с небольшой задержкой.

Как-то не кошет...
А если у вас флаг не бинарным будет?... Да ещё и "привязанный" значениями к потокам?... :о)

Автор:  Trurl [ Четверг, 19 Июнь, 2008 09:50 ]
Заголовок сообщения:  Re: Реализация критической секции на Interlocked Exchange

Скорее всего flag = 0; будет скомпилировано в
Код:
mov flag, 0
, а System.Threading.Interlocked.Exchange - в вызов InterlockedExchange.
Код:
  push 0
  push flag
  call InterlockedExchange
  ...
InterlockedExchange:
  mov     ecx, [esp+4]
  mov     eax, [esp+8]
  xchg    eax, [ecx]
  ret     8

Особой разницы не вижу

Автор:  Сергей Губанов [ Четверг, 19 Июнь, 2008 12:55 ]
Заголовок сообщения:  Re: Реализация критической секции на Interlocked Exchange

Я на RSDN спросил:
http://www.rsdn.ru/forum/message/2988602.1.aspx
там сказали, что может случится так, что слишком интеллектуальный процессор с целью оптимизации может поменять порядок выполнения инструкций и код flag = 0 может оказаться выполненым чуть раньше чем надо, но код с "интерлокедом" процессор с другим кодом менять местами не будет.

Автор:  Евгений Темиргалеев [ Четверг, 19 Июнь, 2008 13:09 ]
Заголовок сообщения:  Re: Реализация критической секции на Interlocked Exchange

Короче с этими навороченными CISC процессорами программировать приходится с RISC-ом для себя. Как в Си++ -- множество подводных камней. И не знаешь, как себя будет вести завтра новая модель...

Автор:  Mirage [ Четверг, 19 Июнь, 2008 16:39 ]
Заголовок сообщения:  Re: Реализация критической секции на Interlocked Exchange

Может быть изменен порядок не инструкций (хотя и инструкций тоже может) а непосредственно операций чтения и записи. Причем не только самим CPU, но и продвинутым компилятором.
Конкретно на x86 - операция чтения может быть помещена CPU перед операцией записи, хотя встречена сперва запись. В рамках одного ядра/процессора обеспечивается верный результат, а вот при многоядерности/многопроцессорности уже нет.
Есть понятие такое - барьер (MemoryBarrier в Windows). Через него операции "не проходят". Interlockedxxx уже содержат этот барьер.

Автор:  Сергей Губанов [ Четверг, 19 Июнь, 2008 17:22 ]
Заголовок сообщения:  Re: Реализация критической секции на Interlocked Exchange

Mirage писал(а):
Конкретно на x86 - операция чтения может быть помещена CPU перед операцией записи, хотя встречена сперва запись.

Это хорошо, значит на x86 операция записи flag = 0; выполнится заведомо после фактического выхода из критической секции. Значит можно безбоязнено использовать простую flag = 0; вместо её интерлокед-варианта...

Я на работе уже на три ночи оставлял программу работать с простым flag = 0; она всё ещё и не зависла. Машина: Athlon64 X2.

Автор:  Евгений Темиргалеев [ Четверг, 19 Июнь, 2008 20:25 ]
Заголовок сообщения:  Re: Реализация критической секции на Interlocked Exchange

Сергей Губанов писал(а):
Значит можно безбоязнено использовать простую flag = 0; вместо её интерлокед-варианта...
А смысл? Оптимизация?

Автор:  Mirage [ Пятница, 20 Июнь, 2008 09:45 ]
Заголовок сообщения:  Re: Реализация критической секции на Interlocked Exchange

Сергей Губанов писал(а):
Это хорошо, значит на x86 операция записи flag = 0; выполнится заведомо после фактического выхода из критической секции. Значит можно безбоязнено использовать простую flag = 0; вместо её интерлокед-варианта...


Эт если инструкции из защищенной секции не будут перемещен CPU еще дальше, а он может. Если будут, то секция не будет полностью защищать весь код. Вобщем станут возможны всякие чудеса. И тесты это не выявят, т.к. перемещение инструкций зависит от кода, т.е. тест должен все время менять защищенный код.

Если так важна скорость, то может имеет смысл использовать т.н. lockless синхронизацию. В принципе, как раз это и пытаетесь сделать, т.к. Interlockedxxx обычно тут и используются. Но еще есть ассемблерные инструкции типа cmpxchg, через которые interlockedxxx и работают.
Но тут надо очень хорошо понимать все эти перемещения инструкций, операций чтения/записи и т.п. и знать когда надо ставить барьеры, а когда не надо.

Автор:  Сергей Губанов [ Пятница, 20 Июнь, 2008 09:55 ]
Заголовок сообщения:  Re: Реализация критической секции на Interlocked Exchange

Евгений Темиргалеев писал(а):
А смысл? Оптимизация?

Да. Если вместо двух interlocked-операций можно использовать только одну, то будет работать почти в два раза быстрее! Операции семейства Interlocked.*** на многопроцессорной машине выполняются тактов примерно от 20-30 и более в зависимости от типа и количества процессоров (20-30 - это не теоретическое значение, а это я типа померил на Athlon 64 X2). Хотя конечно, на однопроцессорной машине при наличии всего одного потока время выполнения может быть небольшим, затрудняюсь сказать сколько, наверное тактов 2-6. Ежели надо защитить участок кода, который сам выполняется тактов за 5-10, то использование спинлока на interlocked-операциях самое то.

Автор:  Сергей Губанов [ Пятница, 20 Июнь, 2008 09:59 ]
Заголовок сообщения:  Re: Реализация критической секции на Interlocked Exchange

Mirage писал(а):
Эт если инструкции из защищенной секции не будут перемещен CPU еще дальше

А если я сделаю присваивание flag = 0 в отдельной процедуре Exit:
Код:
MySpinlockCriticalSection.Enter;
...
a := b;
MySpinlockCriticalSection.Exit;

неужели процессор на столько может обнаглеть, что выполнит сначала MySpinlockCriticalSection.Exit; а потом a := b? Всё-таки вызов процедуры...

Автор:  Mirage [ Пятница, 20 Июнь, 2008 10:54 ]
Заголовок сообщения:  Re: Реализация критической секции на Interlocked Exchange

Сергей Губанов писал(а):
неужели процессор на столько может обнаглеть, что выполнит сначала MySpinlockCriticalSection.Exit; а потом a := b? Всё-таки вызов процедуры...


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

Автор:  Wlad [ Воскресенье, 22 Июнь, 2008 13:02 ]
Заголовок сообщения:  Re: Реализация критической секции на Interlocked Exchange

"...а как всё хорошо начиналось! - вызываем в Москву... и как всё закончилось - на конкурс самодеятельности!..."

И вот представьте: это кто понимайт - говорит и обсуждает ( с разумением оп чём ваще речь идёт ), а каково среднестатистическому вчерашнему студенту (да - и не только!)?! : "Фсё зробыв по правилам! - а включашь - фигня получается!" :twisted:

Автор:  Vlad [ Воскресенье, 22 Июнь, 2008 22:39 ]
Заголовок сообщения:  Re: Реализация критической секции на Interlocked Exchange

Владимир Лось писал(а):
И вот представьте: это кто понимайт - говорит и обсуждает ( с разумением оп чём ваще речь идёт ), а каково среднестатистическому вчерашнему студенту (да - и не только!)?! : "Фсё зробыв по правилам! - а включашь - фигня получается!" :twisted:


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

P.S. Почему нельзя использовать флажки в виде обычный переменных для синхронизации - в приличных книжках тоже пишут. Потому как это частая ошибка у недоучившихся студентов.

Автор:  Илья Ермаков [ Понедельник, 23 Июнь, 2008 06:43 ]
Заголовок сообщения:  Re: Реализация критической секции на Interlocked Exchange

Так речь не о примитивах синхронизации, а о "соответствии" написанного и сгенерированного кода, которое может получиться... С точки зрения синхронизации первый вариант Сергея вполне верен - если изменение идёт внутри критической секции, значит, его выполняет только один поток. Однако, зная, что всегда тут будут "заподлы", я бы, конечно, так не стал делать, о чём сказал Сергею... А дальше коллеги конкретно объяснили, почему...

Страница 1 из 2 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/