Оптимальное количество элементов для хранения в очереди для пула потоков в.NET?
Я создаю механизм фоновой обработки, который поддерживает отбрасывание как обрабатываемых, так и обрабатываемых элементов. Это для использования в приложении winforms, которое потребует интенсивной обработки некоторых элементов ввода, поэтому я создаю механизм очереди, где я могу ставить в очередь элементы рабочей нагрузки, и когда они обрабатываются, я получаю уведомление с результатами.
Вопрос в том, что эта очередь почти всегда будет содержать много элементов для начала, и я подумал, что вместо того, чтобы просто выгружать все в пул потоков, я бы помещал только первые N элементов в пул потоков и продолжал бы обратную засыпку, когда они обработанный. Причина, по которой я хочу это сделать, заключается в том, что после того, как я дам их в пул потоков, они будут обработаны, и даже если они помечены как отброшенные, они все равно будут занимать время очереди.
Благодаря реализации обратной засыпки, которую я сделал, я могу удалять элементы из очереди, если они будут отброшены, и помещать их в очередь, если можно так выразиться.
Таким образом, вопрос в том, как мне рассчитать это число N, количество элементов, которые нужно поместить и сохранить в очереди пула потоков.
Вопросы, которые я рассмотрел:
- Я мог бы хотеть поставить в очередь 2 * число процессоров, которое я вижу, является типичным числом элементов, чтобы гарантировать, что все процессоры работают
- Тем не менее, если фактическая обработка некоторых элементов выполняется очень быстро (что может произойти), то очередь в пуле потоков исчерпывается, прежде чем мой собственный класс сможет заполнить ее дополнительной работой, поэтому, возможно, я бы хотел, чтобы большее число не использовалось недостаточно. процессоры
- Должен ли я создать некоторую процедуру автонастройки для вычисления оптимального числа на основе текущего времени, которое занимает каждый элемент, так что, если они все супербыстрые, число будет намного выше, а если обработка занимает немного времени, она должна остаться низкий?
Как вы думаете?
Новое: Хорошо, из-за одного из ответов, я объясню немного больше. Каждый элемент, помещенный в очередь, помечается чем-то уникальным. Если я помещаю другой элемент в очередь с тем же ключом, что и существующий элемент, этот старый элемент считается "Отброшенным" и должен быть удален. Если элемент обрабатывается, свойство элемента рабочей нагрузки устанавливается в значение true, свойство "IsDicarded", за которое метод обработки отвечает за вызов. Если он обнаружит выброшенный элемент, он должен выйти раньше срока, не возвращая результатов.
Возможно, я должен немного поэкспериментировать и попытаться просто сбросить все в пул потоков.
Новый вопрос: есть ли ограничение на количество предметов, которые я могу поставить в очередь? Если нет, то это легко упростит мой класс.
Примечание: когда я говорю "длительная обработка", я имею в виду порядка 1-10 секунд. Поток еще лучше для этого? Я вижу в Интернете заметки о том, что "обработка должна быть быстрой", но что такое "быстрая", никогда не упоминается. Здесь скорость порядка миллисекунд?
2 ответа
Знаете ли вы умный пул Ami Bar?
Кажется, его реализация позволяет отменять необработанный элемент и динамически увеличивать потоки по мере необходимости, до жесткого ограничения; Я лично пользуюсь 100 * Environment.ProcessorsCount
Возможно ли, что вы могли бы упростить подход, изменив свои элементы, чтобы сначала проверить, что они все еще необходимы, прежде чем они сделают какую-либо работу? Это позволит обойти проблему ограничения числа в пуле, так как вы можете просто добавить их все, и когда каждый элемент будет обработан, он выйдет, если больше не будет необходимости.
Количество операций, которые могут быть поставлены в очередь в пуле потоков, ограничено только доступной памятью; однако пул потоков ограничивает количество потоков, которые могут быть активны в процессе одновременно. По умолчанию ограничение составляет 250 рабочих потоков на процессор и 1000 потоков завершения ввода-вывода.
Вы можете контролировать максимальное количество потоков, используя методы GetMaxThreads и SetMaxThreads.