Подтвердить что ты не робот

Multicore + Hyperthreading - как распределяются потоки?

Я читал обзор нового Intel Atom 330, где они отметили, что диспетчер задач показывает 4 ядра - два физических ядра, а еще два моделируют Hyperthreading.

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

Если ответ - это ничего, кроме 0%, существуют ли какие-либо стратегии смягчения, кроме создания большего количества потоков?

Я ожидаю, что будут разные ответы для Windows, Linux и Mac OS X.


Используя sk answer в качестве Google корма, а затем по ссылкам, я нашел GetLogicalProcessorInformation функции в Windows. В нем говорится о "логических процессорах, которые совместно используют ресурсы. Примером такого типа совместного использования ресурсов будут сценарии гиперпотоков". Это означает, что jalf верен, но это не совсем окончательный ответ.
4b9b3361

Ответ 1

Linux имеет довольно сложный планировщик потоков, который известен HT. Некоторые из его стратегий включают:

Пассивная балансировка: если на физическом ЦПУ запущено более одной задачи, планировщик попытается запустить любые новые задачи на втором физическом процессоре.

Active Loadbalancing: если есть 3 задачи, 2 на одном физическом процессоре и 1 на другом, когда второй физический процессор переходит в режим ожидания, планировщик попытается перенести одну из задач на него.

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

Итак, чтобы ответить на ваш вопрос (по крайней мере, на Linux); учитывая 2 потока на двухъядерной гиперпотоковой машине, каждый поток будет работать на своем собственном физическом ядре.

Ответ 2

Разумная ОС будет пытаться планировать интенсивные вычислительные задачи на своих собственных ядрах, но проблемы возникают, когда вы начинаете переключение контекста. Современная ОС по-прежнему имеет тенденцию планировать события на ядрах, где нет времени на планирование, но это может привести к тому, что процессы в параллельных приложениях будут меняться с ядра на ядро ​​довольно либерально. Для параллельных приложений вы не хотите этого, потому что вы теряете данные, которые процесс мог использовать в кешах по своему ядру. Люди используют совместимость процессора для управления этим, но в Linux семантика sched_affinity() может сильно различаться между дистрибутивами/ядрами/поставщиками и т.д.

Если вы работаете в Linux, вы можете с уверенностью контролировать совместимость процессора с Portable Affinity Library (PLPA). Это то, что OpenMPI использует внутренне, чтобы убедиться, что процессы получают доступ к их собственным ядрам в многоядерных и многоразрядных системах; они просто выделили модуль как отдельный проект. OpenMPI используется в Лос-Аламосе среди многих других мест, поэтому это хорошо протестированный код. Я не уверен, что эквивалент находится под Windows.

Ответ 3

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

Я написал простую программу на С#, которая запускает два потока. На моем четырехъядерном ядре Windows 7 я увидел неожиданные результаты.

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

Чтобы лучше увидеть результаты, скомпилируйте этот код с помощью свободно доступного компилятора csc.exe, который поставляется с клиентом .NET Framework 4.0, и запустите его на машине с несколькими ядрами. Когда прокси-сервер процессора закомментировал, диспетчер задач показал, что потоки распределены по всем четырем ядрам, каждый из которых работает примерно на 50%. С набором аффинности два потока максимизировали два ядра на 100%, а два других ядра на холостом ходу (что я ожидал увидеть до того, как я проведу этот тест).

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading.Tasks;

class Program
{
    [DllImport("kernel32")]
    static extern int GetCurrentThreadId();

    static void Main(string[] args)
    {
        Task task1 = Task.Factory.StartNew(() => ThreadFunc(1));
        Task task2 = Task.Factory.StartNew(() => ThreadFunc(2));
        Stopwatch time = Stopwatch.StartNew();
        Task.WaitAll(task1, task2);
        Console.WriteLine(time.Elapsed);
    }

    static void ThreadFunc(int cpu)
    {
        int cur = GetCurrentThreadId();
        var me = Process.GetCurrentProcess().Threads.Cast<ProcessThread>().Where(t => t.Id == cur).Single();
        //me.ProcessorAffinity = (IntPtr)cpu;     //using this line of code binds a thread to each core
        //me.IdealProcessor = cpu;                //seems to have no effect

        //do some CPU / memory bound work
        List<int> ls = new List<int>();
        ls.Add(10);
        for (int j = 1; j != 30000; ++j)
        {
            ls.Add((int)ls.Average());
        }
    }
}

Ответ 4

Вы можете убедиться, что оба потока получают запланированные для одних и тех же исполнительных блоков, придав им сродство к процессору. Это можно сделать либо в окнах, либо через unix через API (поэтому программа может запросить его) или через административные интерфейсы (поэтому администратор может установить его). Например. в WinXP вы можете использовать диспетчер задач для ограничения того, какой логический процессор может выполнить процесс.

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

Ответ 5

Вероятность составляет, по существу, 0%, что ОС не будет использовать как можно больше физических ядер. Ваша ОС не глупа. Его задача - запланировать все, и он хорошо знает, какие ядра он имеет. Если он видит два потока, интенсивно использующих ЦП, он будет работать на двух физических ядрах.

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

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

Итак, для крупномасштабных материалов HPC, да, вы хотите, чтобы каждый поток оставался на одном ядре, исправлен. Но для большинства более мелких задач это не имеет особого значения, и вы можете доверять планировщику ОС.

Ответ 6

Это очень хороший и актуальный вопрос. Как мы все знаем, гиперпоточное ядро ​​не является реальным процессором/ядром. Вместо этого это виртуальный процессор/ядро ​​(теперь я скажу ядро). Предполагается, что планировщик процессора Windows с Windows XP сможет отличать гиперпотоковые (виртуальные) ядра от реальных ядер. Вы можете себе представить, что в этом совершенном мире он справляется с ними "правильно", и это не проблема. Вы ошибаетесь.

Рекомендация Microsoft по оптимизации сервера BizTalk для Windows 2008 рекомендует отключить HyperThreading. Это говорит о том, что обработка гиперпотоковых ядер не идеальна, и иногда потоки получают временной срез на гиперпоточном ядре и страдают от штрафа (доля производительности реального ядра, 10% d guess, и Microsoft догадывается о 20-30%).

Ссылка на статью Microsoft, в которой предлагается отключить HyperThreading для повышения эффективности сервера: http://msdn.microsoft.com/en-us/library/cc615012(BTS.10).aspx

Это вторая рекомендация после обновления BIOS, так важно, как они ее считают. Они говорят:

ОТ MICROSOFT:

" Отключить гиперпоточность на BizTalk Серверы и серверы SQL Server

критическая гиперпоточность отключено для BizTalk Server компьютеры. Это настройка BIOS, обычно находится в процессоре настройки BIOS. Гиперпоточность делает сервер похоже, больше процессоров/процессорных ядер, чем он фактически делает; однако гиперпоточное процессоры обычно обеспечивают между 20 и 30% от эффективности физического процессора/процессорного ядра. Когда BizTalk Server подсчитывает количество процессоров для самонастраивающиеся алгоритмы; гиперпотоковые процессоры корректировки, которые должны быть перекошены, что что отрицательно сказывается на общей производительности."

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

Вместо полного отключения HyperThreading вы можете использовать такие программы, как Process Lasso (бесплатно), чтобы установить приращения для CPU по умолчанию для критических процессов, чтобы их потоки никогда не выделялись для виртуальных процессоров.

Итак... Я не думаю, что кто-то действительно знает, насколько хорошо Windows Scheduler обрабатывает виртуальные процессоры, но я думаю, что можно с уверенностью сказать, что XP справляется с этим хуже, и с тех пор они постепенно улучшали его, но он все еще не идеален. Фактически, он НИКОГДА не будет идеальным, потому что ОС не знает, какие потоки лучше всего использовать для этих медленных виртуальных ядер. Возможно, это проблема, и почему Microsoft рекомендует отключать HyperThreading в средах сервера.

Также помните, даже БЕЗ HyperThreading, есть проблема "основного измельчения". Если вы можете сохранить поток на одном ядре, это хорошо, поскольку оно уменьшает штрафные санкции на изменение.

Ответ 7

Я не знаю о других платформах, но в случае Intel они публикуют много информацию о потоковой передаче на своих Intel Software Network. У них также есть бесплатный информационный бюллетень ( "Отправка программного обеспечения Intel" ), вы можете подписаться по электронной почте и в последнее время много таких статей.

Ответ 8

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

Причины этого в основном связаны с HW:

  • ОС (и процессор) хочет использовать как можно меньше энергии, поэтому она будет максимально эффективно выполнять задачи, чтобы войти в состояние ASAP с низким энергопотреблением.
  • Запуск всего на одном и том же ядре заставит его нагреваться намного быстрее. В патологических условиях процессор может перегреться и сократить свои часы, чтобы остыть. Чрезмерное нагревание также приводит к тому, что вентиляторы процессора вращаются быстрее (думайте, ноутбуки) и создавайте больше шума.
  • Система никогда не работает. ISR и DPC запускаются каждые мс (на большинстве современных ОС).
  • Дефицит производительности из-за перекоса потоков от ядра к ядру пренебрежимо мал в 99,99% от рабочих нагрузок.
  • Во всех современных процессорах кеш последнего уровня используется совместно, поэтому коммутационные ядра не так уж плохи.
  • Для многосетевых систем (Numa) ОС минимизирует скачкообразный переход из гнезда в сокет, поэтому процесс остается "рядом" с контроллером памяти. Это сложная область при оптимизации для таких систем (десятки/сотни ядер).

BTW, то, как ОС знает топологию ЦП, через ACPI - интерфейс, предоставляемый BIOS.

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