Лучший способ замедлить поток?Использование Sleep () в порядке? - PullRequest
8 голосов
/ 17 января 2010

Я написал библиотеку C ++, которая выполняет серьезную тяжелую работу с процессором (все это - математические вычисления и вычисления) и, если оставить ее на собственные устройства, будет легко потреблять 100% всех доступных ресурсов процессора (она также многопотокова по количеству из доступных логических ядер на машине).

Таким образом, у меня есть обратный вызов внутри основного цикла вычислений, который должно вызывать программное обеспечение, использующее библиотеку:

while(true)
{
    //do math here
    callback(percent_complete);
}

При обратном вызове клиент вызывает Sleep (x), чтобы замедлить поток.

Первоначально клиентский код представлял собой фиксированный вызов Sleep (100), но это приводило к плохой ненадежной производительности, потому что некоторые машины заканчивают математику быстрее, чем другие, но режим ожидания одинаков на всех машинах. Итак, теперь клиент проверяет системное время, и если прошло более 1 секунды (что == несколько итераций), он будет спать в течение полсекунды.

Является ли это приемлемым способом замедления потока? Должен ли я использовать семафор / мьютекс вместо Sleep (), чтобы максимизировать производительность? Хорошо ли спит x миллисекунд за каждую 1 секунду обработки или что-то не так, что я не замечаю?

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

Спасибо!

Ответы [ 5 ]

23 голосов
/ 17 января 2010

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

4 голосов
/ 17 января 2010

Что не так с процессором на 100%? Это то, к чему вы должны стремиться, а не пытаться избежать. Эти математические вычисления важны, нет? Если вы не пытаетесь избежать захвата какого-либо другого ресурса, который явно не управляется ОС (мьютекс, диск и т. Д.) И используется основным потоком, попытка замедлить ваш поток - плохая идея. А как насчет многоядерных систем (которые будут почти во всех системах в будущем)? Вы бы замедлили поток без всякой причины.

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

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

В общем, если вы вызываете Sleep (x), в вашем дизайне что-то не так или лениво, а если x == 0, вы открываете себя для живых блокировок (поток вызывает Sleep (0) на самом деле может быть перенесено немедленно, что делает его ноль).

2 голосов
/ 17 января 2010

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

Единственное программное обеспечение, в котором я использую такую ​​функцию, это BOINC клиент . Я не знаю, какой механизм он использует, но он с открытым исходным кодом и мультиплатформенный, так что помогите себе.

Имеется опция конфигурации («ограничить использование ЦП до X%»). Путь, который я ожидаю реализовать, заключается в использовании зависящих от платформы API, таких как clock() или GetSystemTimes(), и сравнении времени процессора с истекшим временем настенных часов. Сделайте небольшую реальную работу, проверьте, находитесь ли вы на уровне или ниже нормы, и если вы на некоторое время перешли в спящий режим, чтобы вернуться обратно.

Клиент BOINC прекрасно работает с приоритетами и не вызывает проблем с производительностью для других приложений даже при максимальной загрузке процессора на 100%. Причина, по которой я использую дроссель, заключается в том, что в противном случае клиент все время запускает центральный процессор и увеличивает скорость вращения вентилятора и уровень шума. Поэтому я запускаю его на уровне, когда вентилятор работает тихо. С лучшим охлаждением, возможно, мне бы это не понадобилось: -)

0 голосов
/ 17 января 2010

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

0 голосов
/ 17 января 2010

Взгляните на cpulimit . Он отправляет SIGSTOP и SIGCONT по мере необходимости, чтобы поддерживать процесс ниже заданного процента использования процессора.

Тем не менее, WTF на "сумасшедших жалобах и фантастических обзорах о том, как ваше программное обеспечение убивает производительность ПК". Я бы с большей вероятностью пожаловался, что ваше программное обеспечение работает медленно и не использует мое оборудование наилучшим образом, но я не ваш клиент.

Редактировать: в Windows SuspendThread() и ResumeThread() могут, вероятно, вызывать подобное поведение.

...