Оптимальное количество элементов для хранения в очереди для пула потоков в .NET?

Я создаю механизм фоновой обработки, который поддерживает отбрасывание как подлежащих обработке, так и обрабатываемых элементов. Это для использования в приложении winforms, которое потребует интенсивной обработки некоторых входных элементов, поэтому я создаю механизм очереди, в котором я могу ставить в очередь элементы рабочей нагрузки, и когда они обрабатываются, я получаю уведомление с результатами.

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

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

Итак, вопрос в том, как мне вычислить это число N, количество элементов, которые нужно поместить и сохранить в очереди пула потоков.

Проблемы, которые я рассмотрел:

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

Как вы думаете?

Новинка: хорошо, из-за одного из ответов я объясню немного больше. Каждый элемент, помещенный в очередь, имеет уникальный ключ. Если я помещаю в очередь другой элемент с тем же ключом, что и у существующего элемента, этот старый элемент считается «отброшенным» и должен быть удален. Если элемент обрабатывается, свойству элемента рабочей нагрузки присваивается значение true, свойству IsDicarded, за вызов которого отвечает метод обработки. Если он обнаруживает отброшенный элемент, он должен выйти раньше, не возвращая никаких результатов.

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

Новый вопрос: есть ли ограничение на количество элементов, которые я могу поставить в очередь? Если нет, то это легко упростит мой класс.

Примечание. Когда я говорю "длительная обработка", я имею в виду от 1 до 10 секунд. Является ли threadpool даже лучшим для этого? Я вижу во всем Интернете заметки о том, что «обработка должна быть быстрой», но никогда не упоминается, что такое «быстрая». Здесь быстро порядка миллисекунд?


person Community    schedule 03.12.2009    source источник


Ответы (2)


Знакомы ли вы с интеллектуальным пулом потоков от Ami Bar?

Кажется, его реализация позволяет вам отменить необработанный элемент и динамически увеличивать потоки по мере необходимости до жесткого предела; Я лично использую 100 * Environment.ProcessorsCount

person Community    schedule 03.12.2009
comment
Нет, я не знал об этом, я посмотрю, это выглядит многообещающе. Лучший код — это код, который мне не нужно писать, но он просто работает «из коробки» :) - person Lasse V. Karlsen; 03.12.2009

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

Количество операций, которые можно поставить в очередь в пул потоков, ограничено только доступной памятью; однако пул потоков ограничивает количество потоков, которые могут быть одновременно активны в процессе. По умолчанию ограничение составляет 250 рабочих потоков на ЦП и 1000 потоков завершения ввода-вывода.

Вы можете управлять максимальным количеством потоков с помощью методов GetMaxThreads и SetMaxThreads.

http://msdn.microsoft.com/en-us/library/0ka9477y.aspx

person Community    schedule 03.12.2009
comment
Да, они это делают, элементы, отправляемые в делегат, содержат метод IsDicarded, который они должны вызывать не только до, но и во время обработки, если обработка длительная, чтобы прервать ее досрочно. Возможно, я слишком усложнил этот вопрос и должен просто отслеживать существующие элементы, они имеют ключ, чтобы я мог найти их, чтобы отказаться от них в случае замены, и просто сбросить их все в пул потоков. Возможно, мне следует поэкспериментировать с этим решением. - person Lasse V. Karlsen; 03.12.2009
comment
Похоже, что это, безусловно, стоит попробовать, особенно если это означает избегание других сложностей в определении размера и управлении пулом вручную. - person Ed Guiness; 03.12.2009
comment
Знаете ли вы, существует ли ограничение на количество рабочих элементов, которые я могу поместить в пул потоков? - person Lasse V. Karlsen; 03.12.2009
comment
Похоже, это отличное время, чтобы сделать ветку для экспериментов :) - person Lasse V. Karlsen; 03.12.2009
comment
Ах, похоже, мне нужно взглянуть на умный пул потоков, о котором упоминает Рубенс, мне нужна поддержка приоритизации. Например, когда рассматриваемая форма открыта, все данные помещаются в очередь для обработки, но если пользователь изменяет некоторые определенные столбцы в сетке, результаты для этих столбцов повторно помещаются в очередь для обработки с более высоким приоритетом, так что в конечном итоге все данные обрабатываются, но то, с чем пользователь возится, будет обработано в первую очередь. - person Lasse V. Karlsen; 03.12.2009