Почему mutex pthread считается "медленнее", чем futex?

Почему мьютексы POSIX считаются более тяжелыми или медленными, чем futexes? Где накладные расходы, исходящие из типа mutex pthread? Я слышал, что мьютексы pthread основаны на futexes, и когда они неоспоримы, не делайте никаких вызовов в ядро. Похоже, что мьютекс pthread является всего лишь "оберткой" вокруг futex.

Является ли накладные расходы просто вызовом функции-обертки и необходимость использования функцией mutex для "настройки" futex (т.е. в основном настройка стека для вызова функции mutex pthread)? Или есть некоторые дополнительные барьеры памяти, которые происходят с мьютексом pthread?

Ответ 1

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

Я предполагаю, что вы говорите о ядро ​​, когда вы говорите о потоках POSIX. Вполне возможно, что полностью реализована пользовательская реализация потоков POSIX, которые не требуют системных вызовов, но имеют другие проблемы.

Я понимаю, что futex находится на полпути между потоком POSIX ядра и потоком POSIX в пользовательском пространстве.

Ответ 2

Futexes были созданы для улучшения производительности мьютексов pthread. NPTL использует futexes, LinuxThreads, предшествовавшие futexes, и я думаю, что здесь происходит "более медленное" рассмотрение. Мьютекс NPTL может иметь некоторые дополнительные накладные расходы, но это не должно быть много.

Edit: Фактические накладные расходы в основном состоят из:

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

Итак, несколько циклов (типичный случай) до нескольких циклов + неверное предсказание ветвления + дополнительный провал кэша (очень худший случай).

Ответ 3

Короткий ответ на ваш вопрос заключается в том, что futexes, как известно, реализуются как можно более эффективно, в то время как мьютекс pthread может быть или не быть. Как минимум, mutex pthread имеет служебные данные, связанные с определением типа мьютекса, а futexes - нет. Таким образом, futex почти всегда будет по меньшей мере столь же эффективен, как и mutex pthread, пока и если кто-то не подумает о какой-либо структуре, более легкой, чем futex, а затем выпустит реализацию pthreads, которая использует ее для своего мьютекса по умолчанию.

Ответ 4

Технически говоря, мьютексы pthread не медленнее или быстрее, чем futexes. pthread - это всего лишь стандартный API, поэтому, будь он медленным или быстрым, зависит от реализации этого API.

В частности, в Linux mutexs pthread реализованы как futexes и поэтому быстро. Фактически, вы не хотите использовать сам API futex, поскольку он очень прост в использовании, не имеет соответствующих функций-оболочек в glibc и требует кодирования в сборке, который был бы не переносимым. К счастью для нас, разработчики glibc уже закодировали все это для нас под капотом API-интерфейса mutex pthread.

Теперь, поскольку большинство операционных систем не реализовали futexes, тогда программисты обычно означают, что mutex pthread - это производительность, которую вы получаете от обычной реализации мьютексов pthread, которая медленнее.

Итак, статистический факт, что в большинстве операционных систем, совместимых с POSIX, mutex pthread реализован в пространстве ядра и медленнее, чем futex. В Linux они имеют одинаковую производительность. Возможно, что существуют другие операционные системы, в которых мьютексы pthread реализованы в пользовательском пространстве (в незащищенном случае) и, следовательно, имеют лучшую производительность, но на данный момент я знаю только Linux.

Ответ 5

В AMD64 futex имеет 4 байта, а NPTL pthread_mutex_t - 56 байтов! Да, есть значительные накладные расходы.