Несколько против одной условной переменной - PullRequest
0 голосов
/ 29 мая 2018

Я работаю над приложением, в котором у меня есть только одна переменная условия и множество операторов ожидания с разными условиями.Всякий раз, когда одна из очередей или какое-либо другое состояние изменяется, я просто вызываю cv.notify_all(); и знаю, что все потоки, ожидающие этого изменения состояния, будут уведомлены (и, возможно, другие потоки, ожидающие другого условия).

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

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

Редактировать: Все переменные условия по-прежнему будут использовать один и тот же мьютекс.

1 Ответ

0 голосов
/ 31 мая 2018

Я бы рекомендовал иметь одно condition_variable на фактическое условие.Например, в производителе / ​​потребителе будет указано резюме для пустой буфер и другое резюме для заполненный буфер .

Не имеет смысла уведомлять всекогда вы могли бы просто уведомить одного.Это заставляет меня думать, что ваш condition_variable в действительности управляет несколькими фактическими условиями.

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

С точки зрения быстродействия трудно сказать, не зная ситуации, но есть вероятность существенного негативного воздействияСкорость добавления резюме очень низкая, она полностью затмевается стоимостью wait или notify.Если добавление большего количества резюме поможет вам отказаться от вызова notify-all, вероятность положительного влияния на скорость высока.

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

Это ужасная производительность, потому что блокировка мьютекса, разблокировка мьютекса, ожидание cv и сигнал cv относительно дороги.

Даже при вызове notify-не один, вы можете рассмотреть возможность сделать это после критической секции, чтобы попытаться предотвратить блокировку одного пробуждающего потока на мьютексе.И если вы действительно хотите уведомить всех, вы можете просто вызвать notify-one и сделать так, чтобы каждый поток уведомлял-один, когда он заканчивает критическую секцию.Это создает хороший линейный каскад поворота против взрыва раздора.

...