Стоимость мьютекса, критической секции и т. д. в Windows

Я где-то читал, что накладные расходы на мьютекс не так уж велики, потому что переключение контекста происходит только в случае конфликта.

Также известны фьютексы в Linux.

Справится ли то же самое с Windows? Является ли Critical Section более подходящей картой для мьютексов в Linux.

Из того, что я понял, критические секции обеспечивают лучшую оптимальную производительность по сравнению с Mutex, верно ли это для каждого случая?

Есть ли крайний случай, когда мьютексы работают быстрее, чем критический раздел в Windows.

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

Добавлена ​​информация: ОС Windows Server,
Язык C++


person Desert Ice    schedule 06.08.2013    source источник
comment
Конечно, если ваше приложение имеет частые конфликты, вы можете переосмыслить идею о том, что мьютексы не имеют больших накладных расходов.   -  person pattivacek    schedule 06.08.2013


Ответы (2)


Учитывая конкретную цель Critical Sections и Mutexes, я не думаю, что вы можете задать вопрос относительно стоимости, поскольку у вас нет большой альтернативы, когда вам нужно несколько потоков, затрагивающих одни и те же данные. Очевидно, что если вам просто нужно увеличить/уменьшить число, вы можете использовать функции Interlocked*() для числа volatile, и все готово. Но для чего-то более сложного вам нужно использовать объект синхронизации.

Начните чтение с объектов синхронизации, доступных в Windows^. Все функции перечислены там, красиво сгруппированы и правильно объяснены. Некоторые только для Windows 8.

Что касается вашего вопроса, Critical Sections дешевле, чем Mutexe, поскольку они предназначены для работы в одном и том же процессе. Прочтите это^ и это ^ или просто следующая цитата.

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

Я использую Critical Sections для синхронизации одного и того же процесса и Mutexes для синхронизации между процессами. Только когда мне ДЕЙСТВИТЕЛЬНО нужно знать, был ли заброшен объект синхронизации, я использую мьютексы в том же процессе.

Итак, если вам нужен объект синхронизации, вопрос не в стоимости, а в том, что дешевле :) На самом деле нет другой альтернативы, кроме повреждения памяти.

PS: могут быть альтернативы, такие как один упомянутый в выбранном ответе здесь^, но я всегда выбираю основные функции, специфичные для платформы, а не кросс-платформенность. Это всегда быстрее! Поэтому, если вы используете Windows, используйте инструменты Windows :)

ОБНОВЛЕНИЕ

В зависимости от ваших потребностей вы можете уменьшить потребность в объектах синхронизации, пытаясь выполнять как можно больше автономной работы в потоке и объединять данные только в конце или время от времени.

Глупый пример: Возьмите список URL-адресов. Вам нужно очистить их и проанализировать.

  1. Добавьте кучу потоков и начните выбирать URL-адреса один за другим из входного списка. Для каждого вашего процесса вы централизуете результаты по мере его выполнения. Это в реальном времени и круто
  2. Или вы можете добавить потоки, каждый из которых имеет часть входных URL-адресов. Это устраняет необходимость синхронизации процесса выбора. Вы сохраняете результат анализа в потоке и в конце объединяете результат только один раз. Или, скажем, только один раз каждые 10 URL-адресов. Не для каждого из них. Это значительно сократит количество операций синхронизации.

Таким образом, затраты можно снизить, выбрав правильный инструмент и подумав, как уменьшить количество блокировок и разблокировок. Но расходы убрать нельзя :)

PS: я думаю только об URL :)

ОБНОВЛЕНИЕ 2:

Была потребность в проекте, чтобы сделать некоторые измерения. И результаты были довольно неожиданными:

  • std::mutex — самый дорогой. (цена кроссплатформенности)
  • Собственный Windows Mutex в 2 раза быстрее, чем std.
  • Critical Section в 2 раза быстрее нативного Mutex.
  • SlimReadWriteLock составляет +-10% от Critical Section.
  • Мой самодельный InterlockedMutex (спин-блокировка) в 1,25-1,75 раза быстрее, чем Critical Section.
person CodeAngry    schedule 06.08.2013
comment
Я знал, что не могу убрать стоимость, но просто думал, подходят ли мне критическая секция или мьютексы. Хотя спасибо за информацию - person Desert Ice; 07.08.2013
comment
-1 для изменчивого. Вы никогда не должны полагаться только на volatile для многопоточности. Либо используйте atomic, либо комбинируйте volatile с заборами памяти. В противном случае ваш изменчивый доступ может быть переупорядочен, например, в Linux/gcc. - person Петър Петров; 08.03.2016
comment
Неправда, что другого выхода нет. Реализация Windows является общесистемной и регулируется списками разрешений\доступа, мьютексы предназначены для синхронизации интерфейсов между процессами, они не эквивалентны классическим мьютексам. Критические секции взаимодействуют с диспетчером приоритетов потоков, потоки в Windows имеют собственную область памяти — Thread Local Storage. Вызовы этих функций включают довольно много вызовов dll. Если глубокое и повсеместное взаимодействие с ОС не требуется, можно использовать не-API, мьютексы пользовательского пространства, спин-блокировки, атомарные и т. Д. Ради производительности. - person Swift - Friday Pie; 28.09.2018

Используя std::mutex в Windows 8, я обычно получаю 3-4-кратное улучшение (в неконкурентном случае) ускорения, используя мою собственную блокировку вращения:

на основе мьютекса

auto time = TimeIt([&]() {
for (int i = 0; i < tries; i++) {
    bool val = mutex.try_lock();
    if (val) {
        data.value = 1;
    }
}

});

самодельный замок без блокировки

time = TimeIt([&]() {
    for (int i = 0; i < tries; i++) {
        if (!guard.exchange(true)) {
            // I own you
            data.value = 1;
            guard.store(true);
        }
    }
});

Тесты сделаны на x86.

Я не понял, что std::mutex использует подчеркивание в окнах, потому что это генерирует много кода.

person Ghita    schedule 05.12.2013