Критические разделы, которые вращаются на Posix? - PullRequest
3 голосов
/ 17 декабря 2009

Windows API предоставляет критические секции, в которых ожидающий поток будет вращаться ограниченное количество раз перед переключением контекста, но только в многопроцессорной системе. Они реализованы с использованием InitializeCriticalSectionAndSpinCount. (См. http://msdn.microsoft.com/en-us/library/ms682530.aspx.). Это эффективно, когда у вас есть критическая секция, которая часто блокируется только на короткий период времени, и поэтому конфликт не должен немедленно вызывать переключение контекста. Два связанных вопроса:

  1. Для высокоуровневой кроссплатформенной библиотеки потоков или реализации блока synchronized имеет ли небольшое значение вращения перед переключением контекста хорошее значение по умолчанию?
  2. Что, во всяком случае, эквивалентно InitializeCriticalSectionAndSpinCount в других ОС, особенно в Posix?

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

Ответы [ 2 ]

3 голосов
/ 17 декабря 2009

Мое мнение таково, что оптимальное «число оборотов» для лучшей производительности приложения слишком зависит от аппаратного обеспечения, чтобы оно было важной частью кроссплатформенного API, и вам, вероятно, следует просто использовать мьютексы (в posix, pthread_mutex_init / destroy / lock / trylock) или спин-блокировки (pthread_spin_init / destroy / lock / trylock). Обоснование следует.

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

1: очевидно, что это зависит от владельца блокировки, работающего параллельно потоку, пытающемуся получить блокировку. Это невозможно на одном исполнительном ядре, и почти наверняка Microsoft воспринимает это число как 0 в таких средах. Даже с несколькими ядрами вполне возможно, что владелец блокировки не работает, когда другой поток пытается получить блокировку, и в таких случаях оптимальное число вращений (для этой попытки) все еще равно 0.

2: при одновременном выполнении оптимальное число вращений по-прежнему зависит от оборудования. Разным процессорам потребуется разное количество времени для выполнения одинаковых операций. У них разные наборы команд (у ARM, с которым я работаю больше, нет инструкции по целочисленному разделению), разные размеры кеша, у ОС будут разные страницы в памяти ... Уменьшение числа вращений может занять разное время на архитектура хранения данных, чем архитектура, в которой арифметические инструкции могут напрямую обращаться к памяти. Даже на одном и том же процессоре одна и та же задача займет различное количество времени, в зависимости (по крайней мере) от содержимого и организации кэша памяти.

Если оптимальное число вращений при одновременном выполнении бесконечно, то функции pthread_spin_* должны делать то, что вам нужно. Если это не так, используйте функции pthread_mutex_*.

0 голосов
/ 26 октября 2011

Для кросс-платформенной библиотеки потоков высокого уровня или реализация синхронизированного блока, имеет небольшое количество вращение перед переключением контекста по умолчанию?

Казалось бы, так. Много месяцев назад в Solaris 2.x были реализованы адаптивные блокировки, которые делали именно это - вращались какое-то время, если мьютекс удерживается потоком, выполняющимся на другом процессоре, или иным блоком.

Очевидно, что нет смысла крутиться на однопроцессорных системах.

...