Двухъядерный Hyperthreading: Должен ли я использовать 4 потока или 3 или 2?
Если вы одновременно создаете несколько потоков (или процессов), лучше ли создавать столько физических процессоров, сколько количество логических процессоров, если предполагается, что задача связана с ЦП? Или лучше сделать что-то между ними (скажем, 3 потока)?
Зависит ли производительность от типа выполняемых команд (скажем, не будет ли доступ к нелокальной памяти сильно отличаться от обращений в кеш)? Если да, то в каких случаях лучше воспользоваться гиперпотоком?
Update:
Причина, о которой я прошу, я помню, где-то читал, что если у вас столько задач, сколько количество виртуальных процессоров, задачи на одном и том же физическом ядре могут иногда голодать некоторые ресурсы процессора и мешать друг другу получать столько ресурсов по мере необходимости, возможно, снижая производительность. Вот почему я задаюсь вопросом, является ли хорошая идея наличием столько потоков, сколько виртуальных ядер.
Ответы
Ответ 1
Производительность зависит от множества факторов. Большинство задач не связаны строго с ЦП, так как даже если все данные находятся в памяти, они обычно не встроены в кэш процессора. Я видел примеры (например, этот), где шаблоны доступа к памяти могут резко изменить профиль производительности для данного "параллельного" процесса.
Короче говоря, нет идеального числа для всех ситуаций.
Ответ 2
Скорее всего, вы увидите улучшение производительности, выполняющее 2 потока на ядро с включенным HyperThreading. Задания, которые кажутся полностью связанными с ЦП, обычно не являются, и HyperThreading может извлечь несколько "лишних" циклов из случайного прерывания или контекстного переключателя.
С другой стороны, с ядерным процессором iX, который имеет Turbo Boost, вы могли бы лучше запустить 1 поток на ядро, чтобы заставить процессор разогнаться.
На работе мы регулярно запускаем многоядерные серверы с полным процессором, которые выполняют различные вычисления в течение нескольких дней. Некоторое время назад мы измерили разницу в производительности с HT и без него. Мы обнаружили, что в среднем с HyperThreading и одновременным запуском в два раза больше рабочих мест мы могли бы выполнить такое же количество заданий на 10% быстрее, чем без HyperThreading.
Предположим, что 2 & times; ядра - это хорошее место для начала, , но нижняя строка: measure!
Ответ 3
Я помню, что гиперпоточность может дать вам до 30% повышения производительности. в общем, вам лучше рассматривать их как 4 разных ядра. конечно, в некоторых конкретных обстоятельствах (например, с одной и той же длинной задачей, привязанной к каждому ядру), вы можете лучше разделить свою обработку, учитывая, что некоторые ядра являются просто логическими
больше информации о самом гиперпотоке здесь
Ответ 4
Использование Hyperthreading для запуска двух потоков на одном и том же ядре, когда оба потока имеют похожие шаблоны доступа к памяти, но доступ к непересекающимся структурам данных, будут примерно одинаково эквивалентны их запуску на двух отдельных ядрах, каждая из которых имеет половину кеша. Если шаблоны доступа к памяти таковы, что половины кеша будет достаточно для предотвращения перебоев, производительность может быть хорошей. Если шаблоны доступа к памяти таковы, что половина кэша вызывает измельчение, может быть десятикратное увеличение производительности (подразумевая, что было бы намного лучше без гиперпотока).
С другой стороны, есть ситуации, когда гиперпоточность может быть огромной победой. Если многие потоки будут считывать и записывать одни и те же общие данные, используя блокированные структуры данных, и все потоки должны видеть согласованное представление данных, попытка запуска потоков на непересекающемся процессоре может вызвать избиение, поскольку только один процессор за раз может имеют доступ на чтение и запись к любой заданной строке кэша; запуск таких потоков на двух ядрах может занять больше времени, чем запуск только по одному. Однако такой арбитраж кеша не требуется, когда к части данных обращаются несколько потоков на одном ядре. В таких случаях гиперпоточность может быть огромной победой.
К сожалению, я не знаю, как дать планировщику какие-либо "подсказки", чтобы предположить, что некоторые потоки должны делиться ядром, когда это возможно, в то время как другие должны запускаться отдельно, когда это возможно.
Ответ 5
HT позволяет повысить примерно на 10-30% для задач, связанных с cpu, которые используют дополнительные виртуальные ядра. Хотя эти задачи могут показаться связанными с процессором, если они не являются сборкой на заказ, они, как правило, страдают от ожидания ввода-вывода между ОЗУ и локальным кешем. Это позволяет работать одному потоку, работающему на физическом ядре с поддержкой HT, в то время как другой поток ожидает ввода-вывода. Однако это имеет недостаток, поскольку два потока имеют один и тот же кеш/шину, что приведет к меньшему количеству ресурсов, каждый из которых может привести к приостановке обоих потоков при ожидании ввода-вывода.
В последнем случае запуск одного потока уменьшит максимальную одновременную теоретическую мощность обработки (на 10-30%) в пользу запуска одного потока без замедления извлечения кэша, что может быть очень значительным в некоторых приложениях.
Выбор того, какие ядра использовать, столь же важен, как и выбор количества потоков для запуска. Если каждый поток привязан к процессору примерно одинаковой продолжительности, лучше установить сродство, чтобы потоки, использующие в основном разные ресурсы, находились на разных физических ядрах, а потоки с использованием общих ресурсов группировались в одни и те же физические ядра (другое виртуальное ядро), поэтому что общие ресурсы могут использоваться из одного и того же кеша без дополнительного ожидания ввода-вывода.
Поскольку каждая программа имеет разные характеристики использования ЦП, а переполнение кэша может или не может быть основным замедлением (обычно это так), невозможно определить, какое идеальное число потоков должно быть без профилирования в первую очередь. Последнее, что нужно отметить, это то, что OS/Kernel также потребует некоторое пространство процессора и кеша. Как правило, идеально подходит для того, чтобы оставить одиночное (физическое) ядро выделенным для ОС, если требуется зависание в реальном времени для связанных с ЦП потоков, чтобы избежать совместного использования ресурсов кэша/процессора. Если потоки часто ждут ввода-вывода и кэширования, это не проблема, или если в ОС реального времени, специально разработанной для приложения, вы можете пропустить этот последний шаг.
http://en.wikipedia.org/wiki/Thrashing_(computer_science)
http://en.wikipedia.org/wiki/Processor_affinity
Ответ 6
Все остальные ответы уже дают много отличной информации. Но еще один момент, который следует учитывать, заключается в том, что модуль SIMD разделяется между логическими ядрами на одной и той же матрице. Итак, если вы используете потоки с кодом SSE, вы запускаете их на всех 4 логических ядрах или просто создаете 2 потока (если у вас есть два чипа)? Для этого нечетного случая лучше всего профиль с вашим приложением.