Сколько потоков использовать? - PullRequest
13 голосов
/ 07 июля 2011

Я знаю, что есть некоторые существующие вопросы, и они дают очень хороший общий взгляд на вещи. Я надеюсь получить некоторые детали на стороне C # / VB.Net для фактической реализации (не философия) некоторых из этих перспектив.

Мой частный случай

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

Для каждого полученного файла (который может быть не более тысячи в секунду) служба должна работать с файлами в течение 1-10 секунд (каждый) в зависимости от количества других служб, локальных ресурсов и ожидания ввода-вывода в сети раз.

Чтобы помочь службе с этими пакетными рабочими нагрузками Я внедрил систему очередей. Эти тысячи файлов, получаемых в секунду, помещаются в очередь. Контроллер рассчитывает количество используемых потоков на основе размера очереди до тех пор, пока не достигнет параметра «Максимальное количество потоков», которое не позволяет ему создавать дополнительные потоки. Эти потоки помещаются в пул потоков и повторно используются для циклического перемещения по очереди. Контроллер будет; с интервалами; пересчитать количество необходимых потоков. Если размер очереди уменьшается, освобождается соответствующее количество потоков.

Вечная проблема

Сколько потоков я должен пик на? Ясно, что добавление нового потока каждый раз, когда файл был получен, было бы глупо из-за отсутствия лучшего слова - производительность, в лучшем случае, ухудшилась бы. Ограничение потоков, когда загрузка ЦП составляет всего 10% для каждого ядра, также не является наилучшим использованием ресурсов.

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

Что тогда, если мы переместим образ сервера на другой хост, который быстрее / медленнее / отличается от первого? Я должен повторить процесс заново?

В идеале, я хочу, чтобы координатор разумно увеличил размер пула потоков до тех пор, пока загрузка ЦП не станет равной x% (будет ли 80% разумно? 90%? 99%? ). Понятно, что я хочу сделать это без добавления большего количества потоков, чем необходимо, чтобы набрать x%, в противном случае все, что я в итоге получу, это потоки, которые не просто ожидают ресурсы ввода-вывода, но и ожидают друг друга.

Заранее спасибо!


Смежные вопросы (если вам нужны общие идеи):

Сколько потоков создать?

Сколько потоков слишком много?

Сколько потоков создавать и когда?


Осложнение для вас

Где было бы весело, если бы я не усложнял задачу?

В настоящее время служба регулярно отбрасывает 100% ресурсов процессора во время этих всплесков. Проблема заключается в пиках загрузки процессора. Он переходит из режима ожидания (0-10%) в 100% и снова возвращается вниз. Я не уверен, что смогу в этом помочь - в идеале я бы не принял это до 100%. Проблема существует, потому что упомянутые файлы на самом деле являются изображениями, и частью процесса служб является передача изображения в черный ящик System.Windows.Media, который выполняет для меня некоторую сложную обработку изображений.

Между шипами возникают затишья из-за ожидания ввода-вывода и другой обработки, которая продолжается.Если всплески, достигающие 100%, не могут помочь (и я полностью знаю, как предотвратить это, или если я должен), как я должен стремиться к тому, чтобы график загрузки ЦП выглядел?Сел постоянно на 100%?Отскок между 50-100?Если я попытаюсь выполнить выборку, чтобы решить, что, по-видимому, будет работать лучше, гарантируется ли, что переключение хоста виртуальных серверов также будет работать лучше с тем же графиком?

Эта дополнительная сложность, я не будупринять во внимание тех из вас, кто готов ответить.Не стесняйтесь игнорировать этот раздел.Тем не менее, любой ответ, который также объясняет эту сложность, или даже ответы, которые просто дают советы о том, как справиться с этим, я, по крайней мере, возбуждаю!

Черт возьми, длинный вопрос - извините за это - и спасибо за то, что так много прочитали !!

Ответы [ 3 ]

6 голосов
/ 07 июля 2011

PerformanceCounter позволяет запрашивать использование процессора.

Однако пробовали ли вы что-то, что предоставляет инфраструктура?

        foreach (var file in files)
        {
            var workitem = file;
            Task.Factory.StartNew(() =>
            {
                // do work on workitem
            }, TaskCreationOptions.LongRunning | TaskCreationOptions.PreferFairness);
        }

Можно настроить уровень параллелизма дляЗадачи в задаче. Factory .

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

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

Редактировать: (примечание к комментарию):

Нет ссылокВозможно, я использовал придуманный термин, так как английский не мой язык.Я имею в виду: иметь переменную, в которой вы сохраняете дисперсию до последней проверки (prevDelta), и называет ее дельтой.добавьте это к переменной avrageDelta и разделите на 2 каждый раз, когда вы «проверяете».У вас будет переменная averageDelta, которая в основном будет низкой, поскольку у вас нет активности.Затем создайте другой набор дельта-переменных, который у вас уже есть (delta - prevdelta), и сохраните его в дельта-переменной, которая является не средним значением всех дельт, а средним значением дельт за небольшой промежуток времени (вам придется придуматьалгоритм, чтобы точно рассчитать эту временную дисперсию).После этого вы можете сравнить среднюю дельту и «временную дельту».Средняя дельта будет в основном низкой и будет медленно подниматься при появлении очередей.В этот же период временная дельта будет очень быстро расти.Затем возникает ситуация, когда всплеск останавливается, средняя дельта медленно снижается, а «временная» идет очень быстро.

2 голосов
/ 07 июля 2011

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

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

0 голосов
/ 07 июля 2011

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

...