Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.220.179.171] |
|
Страницы: (3) 1 2 [3] все ( Перейти к последнему сообщению ) |
Сообщ.
#31
,
|
|
|
Сообщ.
#32
,
|
|
|
Цитата Jin X @ А вообще, непонятно, зачем cmpxchg делает запись во втором случае. Можно было бы обойтись и без неё. Это делается для упрощения "железной логики": Цитата Intel А избежать лишних тормозов при вызове cmpxchg в спин-цикле можно программно, добавив перед lock обычное сравнение (как рекомендует интел - “test, test-and-set” technique). To simplify the interface to the processor’s bus, the destination operand receives a write cycle without regard to the result of the comparison. ... (The processor never produces a locked read without also producing a locked write.) |
Сообщ.
#33
,
|
|
|
Цитата shm @ В атомарности. Цитата shm @ Иии?Ни разу не атомарно. Я не понимаю, что ты хочешь сказать Приведённый мной выше код - это внутренняя логика инструкции cmpxchg. leo, теперь ясно. |
Сообщ.
#34
,
|
|
|
Цитата Jin X @ Я не понимаю, что ты хочешь сказать То, что именно такая форма инструкции удобна для реализации lock-free алгоритмов и те же примитивов синхронизации. |
Сообщ.
#35
,
|
|
|
shm, ничуть не удобна. Потому что пока она будет делать Temp = Dest и Dest = Accumulator (в случае успешной проверки входа критической секции), то же самое может сделать и другой. И оба войдут в неё.
Temp1 = Dest Temp2 = Dest Temp1 = Src ? (Yes) Temp2 = Src ? (Yes) Dest = Accumulator Dest = Accumulator Добавлено Или мы о разном? |
Сообщ.
#36
,
|
|
|
Цитата Jin X @ Потому что пока она будет делать Она это делает атомарно (при наличии lock префикса и для SMP). Ну как еще написать не знаю. Добавлено Аппаратно эта инструкция, насколько я понимаю, реализована совсем не так, как ты расписал. Добавлено Я с трудом представляю как без этой инструкции можно реализовать тот же lock-free список. Если у тебя есть идеи - покажи. Кстати эта функция именно в таком виде используется в реализации практически всех примитивов синхронизации. |
Сообщ.
#37
,
|
|
|
Цитата shm @ При наличии lock - естественно. Но ты ж сам написал:Она это делает атомарно (при наличии lock префикса и для SMP). Ну как еще написать не знаю. Цитата shm @ Если же имелось в виду:То, что именно такая форма инструкции удобна для реализации lock-free алгоритмов и те же примитивов синхронизации. Цитата тогда без вопросов Неблокирующая синхронизация — подход в параллельном программировании на симметрично-многопроцессорных системах, проповедующий отказ от традиционных примитивов блокировки, таких, как семафоры, мьютексы и события. Разделение доступа между потоками идёт за счёт атомарных операций и специальных, разработанных под конкретную задачу, механизмов блокировки. © Википедия Цитата shm @ Это код из свежего Intel Instruction Reference (сообщение #27). Аппаратно эта инструкция, насколько я понимаю, реализована совсем не так, как ты расписал. Добавлено Цитата shm @ Так, а кто ж спорит-то? Кстати эта функция именно в таком виде используется в реализации практически всех примитивов синхронизации. |
Сообщ.
#38
,
|
|
|
Цитата Jin X @ тогда без вопросов именно. Цитата Jin X @ Это код из свежего Intel Instruction Reference Это псевдо-код поясняющий поведение инструкции. Он не имеет никакого отношения к ее аппаратной реализации. Добавлено Цитата Jin X @ Так, а кто ж спорит-то? А тогда ивзини, я неправильно понял твою реплику про cmpxchg. Тогда leo правильно написал. |
Сообщ.
#39
,
|
|
|
Нашёл интересную вещь в недрах AcquireSRWLockExclusive: NtWaitForKeyedEvent (ntdll.dll).
Возможно, это то, что мне нужно (если вернуться к первоначальной теме)... Буду изучать... http://www.locklessinc.com/articles/keyed_events/ |
Сообщ.
#40
,
|
|
|
Jin X, так обычные события чем не угодили я все понять не могу?
|
Сообщ.
#41
,
|
|
|
Уффф... Надо делать Init и Detele (в которых делается Init и Close... ну или просто Delete (Close) (либо создавать и удалять на каждом входе/выходе в/из крит.секции). Они более громоздкие/долгие. Надо делать отдельное событие под каждую критическую секцию (под каждый мьютекс). Короче, этот вариант мне кажется более интересным. Правда, это не совсем то, что я подумал изначально. Изначально мне казалось, что это альтернатива Sleep(1). Но всё равно лучше, чем Event. Вероятно. Я ещё не изучил этот вопрос
|
Сообщ.
#42
,
|
|
|
Цитата Jin X @ Надо делать Init и Detele Ой да целых пара наносекунд при запуске и завершении твоей программы, ога. Цитата Jin X @ либо создавать и удалять на каждом входе/выходе в/из крит.секции Не надо ничего создавать и удалять во время работы. Надо: Enter ... Leve инициализацию и удаления нужно вынести из основного цикла. Цитата Jin X @ Надо делать отдельное событие под каждую критическую секцию Цитата Jin X @ Но всё равно лучше, чем Event Что лучше? |
Сообщ.
#43
,
|
|
|
Цитата Jin X @ Нашёл интересную вещь в недрах AcquireSRWLockExclusive: NtWaitForKeyedEvent (ntdll.dll). Возможно, это то, что мне нужно (если вернуться к первоначальной теме)... Во-первых, NtWaitForKeyedEvent работает через тот же event, с той разницей, что 1) к одному эвенту можно прицепить несколько ключей (что несколько замедляет быстродействие, о котором ты так печешься), 2) если вместо первого параметра передать nil\null, то будет использован системный эвент (типа CritSecOutOfMemoryEvent) - возможно это "то, что тебе нужно", если тебе так хочется избежать "лишних" Create\Close, Init\Delete и т.п. Во-вторых, механизм использования NtWaitForKeyedEvent давно встроен в виндовые крит.секции (по кр.мере со времен XP) на случай облома создания собственного эвента крит.секции (по причине OutOfMemory или исчерпания лимита хэндлов). Поэтому, если тебе так нравится изобретать нестандартные велосипеды, то можно использовать небольшой хак с обычной крит.секцией - сразу после InitializeCriticalSectionAndSpinCount(cs,...), установить cs.LockSemaphore:=INVALID_HANDLE_VALUE - и всё, получишь два в одном: и готовый спин-луп с заданным числом повторений и ожидание NtWaitForKeyedEvent на системном эвенте (вместо создания собственного эвента для крит.секции и его ожидания на WaitForSingleObject). |
Сообщ.
#44
,
|
|
|
leo, интересно...
Почему же AcquireSRWLockShared, AcquireSRWLockExclusive не используют обычные Event'ы, а работают с KeyedEvent'ами? |
Сообщ.
#45
,
|
|
|
Цитата Jin X @ Почему же AcquireSRWLockShared, AcquireSRWLockExclusive не используют обычные Event'ы, а работают с KeyedEvent'ами? Потому, что это slim - упрощенный "до безобразия" вариант крит.секции. Структура SRWLOCK это набор битовых полей, упакованных в размер указателя (32 или 64 бита). В ней просто нет места не только для указателя на event, но и для OwningThreadID и RecursionCount (со всеми вытекающими особенностями использования по сравнению с крит.секцией). Индивидуального SpinCount-а тоже нет, используется некое дефолтное значение. Соотв-но и для ожидания освобождения лока используется не "обычный", а некий глобальный системный KeyedEvent. PS: Что касается быстродействия поиска ключа, то оно зависит от кол-ва, этих самых ключей, привязанных к одному KeyedEvent-у, ну и от используемой структуры хранения и алгоритма поиска ключей. В XP KeyedEvent использовался только в критической ситуации нехватки памяти, поэтому о быстродействии особо не беспокоились и использовали для хранения ключей простой список. А начиная с висты KeyedEvent-ы стали использовать для SRW-lock, условных переменных и т.п., и соотв-но стали хранить ключи в хэш-таблице для ускорения их поиска. Однако как бы не было реализовано хранение и поиск ключей, при малом\небольшом их кол-ве накладные расходы на их поиск\добавление\удаление составляют незначительный процент от общего времени ожидания эвента на NtWaitForKeyedEvent -> WaitForSingleObject |