Как выбрать лучшее количество потоков для многоядерности? - PullRequest
8 голосов
/ 10 июня 2009

У меня есть некоторая неловко-распараллеливаемая работа в консольном приложении .NET 3.5, и я хочу воспользоваться преимуществами гиперпоточности и многоядерных процессоров. Как выбрать лучшее количество рабочих потоков, чтобы использовать любой из этих потоков в произвольной системе? Например, если это двухъядерное ядро, я хочу 2 потока; Я буду хотеть 4 темы. В конечном счете, мне нужно определить характеристики процессора, чтобы я мог знать, сколько потоков создать.

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

Ответы [ 13 ]

15 голосов
/ 10 июня 2009

Я бы посоветовал вам не пытаться определить это самостоятельно. Используйте ThreadPool и позвольте .NET управлять потоками за вас.

9 голосов
/ 10 июня 2009

Вы можете использовать Environment.ProcessorCount , если это единственное, что вам нужно. Но обычно лучше использовать ThreadPool.

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

4 голосов
/ 10 июня 2009

Правильный номер, очевидно, 42 .

Теперь о серьезной ноте. Просто используйте пул потоков, всегда.

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

2) Если вы выполняете ввод-вывод (включая вызовы БД), вам следует использовать асинхронный ввод-вывод и завершать вызовы в ThreadPool, называемые процедурами завершения.

Эти две единственные действительные причины, по которым у вас должно быть несколько потоков, и обе они лучше всего обрабатываются с помощью ThreadPool. Все остальное, включая запуск потока для каждого «запроса» или «соединения», на самом деле являются анти-шаблонами в мире Win32 API (fork является допустимым шаблоном в * nix, но определенно не в Windows).

Для более специализированного и более подробного обсуждения темы я могу только порекомендовать статьи Рика Викика на эту тему:

3 голосов
/ 10 июня 2009

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

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

Блокировка никогда не бывает оптимальной, но если вы выполняете какую-либо форму блокировки, то ответ резко изменится.

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

3 голосов
/ 10 июня 2009

Хорошее эмпирическое правило, учитывая, что вы полностью связаны с процессором, это processorCount+1.

Это + 1 , потому что вы всегда будете запускать / останавливать / прерывать некоторые задачи, а n задачи почти никогда не будут полностью заполнять n процессоров.

2 голосов
/ 10 июня 2009

Или даже лучше, чем ThreadPool, используйте экземпляры задач .NET 4.0 из TPL. Библиотека параллельных заданий построена на основе платформы .NET 4.0, которая фактически определяет оптимальное количество потоков для максимально эффективного выполнения задач.

2 голосов
/ 10 июня 2009

Единственный способ - это сочетание данных и анализа кода на основе данных о производительности.

Различные семейства и скорости ЦП в зависимости от скорости памяти и других операций в системе будут отличаться от других.

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

1 голос
/ 10 июня 2009

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

1 голос
/ 10 июня 2009

Я недавно кое-что прочитал по этому вопросу (см. Принятый ответ на этот вопрос , например).

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

Есть ряд вопросов по сходной теме - поиск по «оптимальному количеству потоков» (без кавычек) дает вам пару страниц результатов.

0 голосов
/ 14 июня 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...