2009-11-24 2 views
1

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

Позвольте мне описать 2 сценария.

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

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

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

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

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

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

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

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

Спасибо,

-Faken

ответ

5

Сценарий # 1: Сделать п темы, где «п» является количество ядер процессора

Сценарий # 2: То же самое, но вместо того, чтобы создавать и убивать нитей, все время, использовать WorkItem/тему Пул основан подход, как и .NET Parallel Framework.

Редактировать: Это хорошая статья, которая охватывает # 2 - http://msdn.microsoft.com/en-us/magazine/cc163340.aspx; пусть PFx определяет количество потоков, которые вы запускаете, вы просто описываете, как задачи связаны друг с другом.

+0

Хорошая точка. Если задача будет выполняться в течение микросекунды, потребуется немного времени, чтобы настроить поток и запустить его, выполняя настоящую работу! –

+0

Также, если вы используете C++ и Visual Studio 2010, доступны библиотека параллельных шаблонов и время выполнения параллелизма (PFX - .NET). См. Центр параллелизма для указателей на код .NET и C++: http://msdn.microsoft.com/en-us/concurrency/default.aspx – Rick

2

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

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

+0

А что, если каждая нить читает в глобальной информации, а затем выплевывает что-то прямо на жесткий диск? Моя бутылочная горловина будет записывать последовательность жесткого диска правильно? В этом случае, что произойдет, если многие потоки запросят последовательность записи (каждый файл будет содержать не более нескольких КБ), будет ли HD прыгать вокруг записи файлов или заканчивать один файл перед тем, как двигаться дальше? – Faken

+0

Зависит от привода.Большинство драйверов жестких дисков (первоначально только SCSI, но теперь и ATA) поддерживают операции сбора разброса, где группы запросов внутренне перегруппированы, чтобы соответствовать перемещению головки накопителя. – devstuff

+0

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

0

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

+0

Зависит от работы ПК, не работает ли он? – mpen

+0

да, конечно, окружающая среда, тип рабочих нитей будет делать все вопросы –

2

Это не вопрос с негибким ответом, несколько моментов, хотя:

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

Что касается соответствующего количества потоков для пула, это скорее зависит от типов выполняемых задач. Если они связаны с задачами, связанными с ЦП, то один поток на один процессор хорошо подходит: вы избегаете переключения контекста, когда вам это не нужно. Если, с другой стороны, они связаны с задачами, связанными с IO, скажем, что потоки выполняют связь сокетов, тогда вам может понадобиться удвоить пример числа чисел, чтобы вы могли лучше использовать свои процессоры, когда вы ожидаете ввода ввода-вывода.

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

1

Предполагая, что вы имеете в виду программу Windows, даже если это программа C++, а не программа dot-Net, она отплатит вам, чтобы обезопасить Joe Duffy от «Параллельного программирования в Windows» до начала. Он делает хороший шаг для использования подпрограмм для пула потоков, предоставляемых Windows, наиболее убедительно, потому что они уже настроены для конфигурации процессора, снимая это с плеч.
Если вы тогда идите в любом случае, ваш вопрос будет рассмотрен в книге, и вы наверняка избавитесь от стандартных ошибок.

0

Нитки не дешевые. Я знаю в основном по двум причинам использовать их:

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

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

Или оба, как если бы у вас была одна нить, чтобы хрустнуть, и один, чтобы ответить на пользователя.

Смежные вопросы