Условные накладные расходы на ожидание

При использовании boost::conditional_variable, ACE_Conditional или непосредственно pthread_cond_wait есть ли накладные расходы на само ожидание? Это более конкретные проблемы, которые могут возникнуть:

  1. После того, как ожидающий поток будет незапланирован, будет ли он снова запланирован до истечения срока ожидания, а затем снова незапланирован, или он останется незапланированным до тех пор, пока не будет получен сигнал?
  2. Получает ли wait периодически мьютекс? В этом случае, я думаю, каждая итерация тратит некоторое время ЦП на системные вызовы для блокировки и освобождения мьютекса. Это то же самое, что постоянно получать и освобождать мьютекс?
  3. Кроме того, сколько времени проходит между сигналом и возвращением из wait?

Afaik, при использовании семафоров скорость отклика на получение вызовов зависит от размера временного интервала планировщика. Как это работает в pthread_cond_wait? Я предполагаю, что это зависит от платформы. Меня больше интересует Linux, но если кто-то знает, как это работает на других платформах, тоже поможет.

И еще вопрос: выделяются ли какие-то дополнительные системные ресурсы для каждого условного? Я не буду создавать 30000 мьютексов в своем коде, но стоит ли мне беспокоиться о 30000 условных операторов, использующих один и тот же мьютекс?


person FireAphis    schedule 18.10.2010    source источник


Ответы (2)


Вот что написано на справочной странице pthread_cond:

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

Итак, отсюда я бы ответил на вопросы следующим образом:

  1. Ожидающий поток не будет запланирован обратно до того, как ожидание будет сигнализировано или отменено.
  2. Нет периодических захватов мьютексов. Мьютекс повторно захватывается только один раз перед возвратом ожидания.
  3. Время, которое проходит между сигналом и возвратом ожидания, похоже на время планирования потока из-за освобождения мьютекса.

Что касается ресурсов, на той же странице руководства:

В реализации LinuxThreads никакие ресурсы не связаны с переменными условия, поэтому pthread_cond_destroy на самом деле ничего не делает, кроме проверки того, что условие не имеет ожидающих потоков.

Обновление: я покопался в источниках функций pthread_cond_* и обнаружил следующее:

  1. Все условные выражения pthread в Linux реализованы с использованием futex< /а>.
  2. Когда поток вызывает wait, он приостанавливается и не запускается по расписанию. Идентификатор потока вставляется в конец списка ожидающих потоков.
  3. Когда поток вызывает signal, поток в начале списка назначается обратно. Таким образом, пробуждение столь же эффективно, как и планировщик, никакие ресурсы ОС не потребляются, а единственные накладные расходы памяти связаны с размером списка ожидания (см. 6.35.7/kernel/futex.c#L872" rel="noreferrer">futex_wake).
person FireAphis    schedule 19.10.2010

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

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

30000 мьютексов не должны быть проблемой, но некоторые ОС могут иметь проблемы с 30000 спящими потоками.

person Potatoswatter    schedule 18.10.2010
comment
Спасибо за ответ. Мне нужно пояснение: после того, как ожидающий поток будет незапланирован, будет ли он запланирован обратно до истечения срока ожидания, а затем снова незапланирован, или он останется незапланированным до тех пор, пока не будет получен сигнал? - person FireAphis; 19.10.2010
comment
@Fire: я не уверен, что вы имеете в виду под истекающим сроком действия. Вам необходимо вызвать функцию типа while ( ! condition() ) pthread_cond_wait(…);, где condition — это любое логическое значение, которое должно быть true для продолжения выполнения, поэтому, если cond_wait возвращается преждевременно, вы просто вызываете ее снова. Но, как я уже сказал, многие операционные системы никогда этого не делают, а даже если и делают, обычно это не проблема. Если у вас есть тайм-аут, форма while ( ! condition() && pthread_cond_timedwait(…) != ETIMEDOUT ) ;. - person Potatoswatter; 19.10.2010