Как распределить нагрузку между всеми ядрами процессора

Обновлено: 04.07.2024

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

Чтобы объяснить это, необходимо определение использования ЦП. В качестве отправной точки я буду использовать определение из Technopedia, в котором говорится:

Использование ЦП — это использование вычислительных ресурсов компьютера или объем работы, выполняемой ЦП. Фактическая загрузка ЦП зависит от количества и типа задач управляемых вычислений. Для одних задач требуется больше времени ЦП, а для других требуется меньше из-за требований к ресурсам, не связанным с ЦП.

Далее определение гласит:

Загрузку ЦП не следует путать с загрузкой ЦП.

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

Во времена одноядерных процессоров загрузка ЦП была довольно простой задачей. Если процессор работал на фиксированной частоте 2,0 ГГц, загрузка ЦП представляла собой процент времени, затраченного процессором на работу. (Не выполнение работы означает бездействие.) При 50-процентной загрузке процессор выполнял около 1 миллиарда циклов работы за одну секунду. Современные процессоры имеют несколько ядер, аппаратную многопоточность, общий кэш и даже динамически изменяющиеся частоты. Кроме того, точные сведения об этих компонентах различаются от процессора к процессору, что затрудняет сравнение использования ЦП.

Существующие процессоры могут иметь общие кэши L3 для всех ядер или общие кэши L2 и L1 для ядер. Иногда эти ресурсы делятся интересным образом. В качестве примера на рис. 1 показаны процессоры Xeon E5 v2 — Xeon E5 v3 (любезно предоставлено EnterpriseTech).


Рисунок 1. Архитектуры Xeon E5v2–Xeon E5v3.

Обратите внимание, как меняется конкретная архитектура ЦП при переходе от поколения Ivy Bridge (Xeon E5 v2) к поколению Haswell (Xeon E5 v3) и как по-разному распределяются ресурсы в этих двух архитектурах.

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

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

Симметричная многопоточность (SMT), как и технология Intel Hyper-Threading, имеет логические ядра, которые совпадают с физическими ядрами, и могут иметь общие исполнительные блоки. Эти процессоры также имеют характеристики неоднородного доступа к памяти (NUMA), поэтому размещение процессов, включая их привязку к определенным ядрам, может влиять на загрузку ЦП.

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

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

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

Использование ЦП или загрузка ЦП?

Как упоминалось в первом разделе статьи, "загрузку ЦП не следует путать с загрузкой ЦП". Это очень важное различие, которое позволит избежать путаницы.

В Linux (и вычислениях *nix в целом) загрузка системы – это мера работы, которую выполняет система. Классическая команда uptime (или w) выводит три средних значения нагрузки для 1-минутного, 5-минутного и 15-минутного периодов времени. Когда система простаивает, число загрузки равно нулю. Для каждого процесса, который использует или ожидает ЦП, нагрузка увеличивается на единицу. Как правило, это включает в себя влияние процессов, заблокированных при вводе-выводе, поскольку занятые или остановленные системы ввода-вывода увеличивают среднюю загрузку, даже если ЦП не используется. Кроме того, нагрузка вычисляется как экспоненциально затухающая/взвешенная скользящая средняя числа нагрузки. Обратите внимание, что вычисляется среднее.

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

psutil

В Интернете можно найти ряд статей об использовании ЦП на компьютерах с Linux. Многие из них используют время безотказной работы или w, которые не являются лучшими способами определения загрузки ЦП, особенно при тестировании приложения HPC, использующего большинство ядер.

В этой статье я использую psutil, кроссплатформенную библиотеку для сбора информации о запущенных процессах и использовании системы. В настоящее время он поддерживает Linux, Windows, OS X, FreeBSD и Solaris; имеет очень простой в использовании набор функций; и может использоваться для написания всевозможных полезных инструментов. Например, автор psutil написал первоклассныйинструмент в паре сотен строк Python.

В документации по пустилке обсуждается несколько функций для сбора статистики ЦП, в частности время ЦП и процентное соотношение. Более того, эта статистика может быть собрана с заданными пользователем интервалами как для всей системы (всех ядер), так и для каждого ядра в отдельности. Таким образом, psutil — отличный инструмент для сбора статистики использования ЦП.

В качестве примера того, что можно сделать с помощью psutil для сбора статистики использования ЦП, была написана простая программа на Python, которая собирает статистику ЦП и отображает ее с помощью Matplotlib (листинг 1). Программа является просто примером сбора статистики ЦП с некоторыми значениями, жестко запрограммированными.

На моем Ubuntu 16.04 я запускаю программу, которая относительно дорогая с точки зрения использования ЦП. Это занимает довольно много времени, и, как следствие, другие задачи (например, просмотр веб-страниц) становятся медленнее. Я искал способ улучшить вычислительную мощность, если это возможно, и в то же время лучше знать, что происходит в моем ноутбуке.

При этом я обнаружил, что если я задаю вопрос top , запущенная программа показывает загрузку ЦП на 100 %, в то время как когда я открываю системный монитор, загрузка ЦП составляет всего ~ 25 % на вкладке «Процессы». Кроме того, на вкладке «Ресурсы» системного монитора отображаются 4 ЦП, использование которых меняется от ~5 до ~100% для каждого из них:

Использование ЦП

Результат lscpu:

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

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

2 ответа 2

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

Вкратце: нет. Программа однопоточная.

Top может отображать использование ЦП двумя способами: насыщение на ЦП или долю от общего числа. Если у вас четырехъядерная система, в верхней части может отображаться режим Irix:

Кроме того, для многопроцессорных сред, если режим Irix отключен, top будет работать в режиме Solaris, где использование ЦП задачей будет делиться на общее количество ЦП. Вы переключаете режимы Irix/Solaris с помощью интерактивной команды `I'.

Вы можете переключить это, нажав I вверху. Поскольку у вас четыре ядра ЦП, использование делится на четыре, и вы покажете 25%. Если вы включите режим Irix, он покажет 100%.

Ваше приложение является однопоточным. Он выполняет последовательный поток на одном ядре ЦП. Если у вас есть исходный код, вы можете изменить это. Однако обычно это нетривиальная задача, и в зависимости от задачи это может быть невыполнимо.

В Linux есть планировщик, который распределяет запущенные потоки по разным ЦП/ядрам.


Большое спасибо. Можете ли вы сказать, как вы узнали, что программа является однопоточной?Кроме того, что такое «планировщик», о котором вы упоминаете в конце своего ответа?

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

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

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

Загрузка ЦП – 100 % против 25 %

Согласно lscpu , ваш ЦП имеет четыре ядра:

top использует 100 % на ядро, поэтому, если у вас четырехъядерный процессор, это 400 %. Вы полностью используете одно ядро, так что это 100% из 400%. Системный монитор использует 100% для всего (или, возможно, для реального процессора, я не уверен). Одно ядро ​​— это четверть из четырех доступных ядер, поэтому в системном мониторе оно отображается как 25 % использования.

Значительное замедление при использовании одного ядра

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

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

Изменение приоритета задачи

Вы можете использовать nice с высоким значением, например 15, чтобы задача уступила место другим задачам, требующим ЦП:

Замедление задачи

Вы можете попробовать изменить программу на высокое значение, например 15, и использовать программу cpulimit (в пакете cpulimit APT), чтобы уменьшить использование ЦП, пока она разрешена для запуска.

Пример замедления аргументов программы до 60 % загрузки ЦП и использования значения приятности, равного 15:

Использование нескольких ядер

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

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

Есть и другие возможности.

Сочетание использования нескольких ядер с замедлением задачи и установкой значения приятности

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

Сб, 07 ноября 2020 г., 00:50

Я не могу найти подходящий документ или сообщение, в котором объяснялось бы, как лучше распределить нагрузку между несколькими ядрами CCR. Я намерен использовать модель CCR1009 с медными портами. Мне нужно только 3 порта из этого, один для WAN и два для LAN. Эти два порта LAN будут связаны (LACP) с MII для мониторинга канала, а затем подключены к двум отдельным коммутаторам (членам стека) для обеспечения отказоустойчивости.

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

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

Могу ли я также обратиться за советом / руководством к @sindy и @mkx, пожалуйста?

Сб, 07 ноября 2020 г., 17:03

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

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

Не пишите романы, опубликуйте /export hide-sensitive file=x. Используйте функцию поиска и замены в своем любимом текстовом редакторе, чтобы систематически заменять все вхождения каждого общедоступного IP-адреса, потенциально идентифицирующего вас по отличительному шаблону, такому как my.public.ip.1.

Сб, 07 ноября 2020 г., 22:11

Спасибо, Синди, за ваш вклад.

Полезно знать, что несколько ядер автоматически используются для плоскости данных. В любом случае, меня не беспокоил трафик уровня управления, независимо от того, использует ли он одно ядро ​​или несколько, но определенно мне хотелось бы, чтобы все ядра или, по крайней мере, несколько ядер наверняка использовались для пользовательского трафика. Я где-то читал, что требуется ручное вмешательство, и что версия 7 ROS, которая разрабатывалась в течение нескольких лет, была необходима для фактического использования SMP (хотя Linux в течение многих лет автоматически использует несколько ядер) и что оборудование CCR архитектура была разработана для использования версии 7, которая до сих пор недоступна.

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

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

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

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

Оба компьютера работают под управлением Windows 10. У моего домашнего компьютера другой процессор и другая материнская плата (ASUS ROG 11-го выпуска).

Кажется, это относится к любому процессу, но пример, на котором я только что протестировал его, представляет собой сценарий R, который я написал. На обоих ПК работает один и тот же скрипт R, одна и та же версия R, и разные подходы к распределению нагрузки на процессор. Хуже всего то, что мой домашний ПК всегда использует CPU0 для подобных вещей.

Я надеюсь, что есть настройка BIOS, которую я могу применить на своем домашнем ПК, чтобы он равномерно распределял нагрузку. Есть?

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

"Я надеюсь, что есть настройка BIOS, которую я могу применить на своем домашнем ПК, чтобы он равномерно распределял нагрузку" — зачем вам это нужно? Из эстетических соображений? Если вас беспокоит преждевременное сгорание ЦП, могу сказать, что по моему опыту большинство компьютеров заменяют по другим причинам.

3 ответа 3

Я считаю, что наиболее вероятным виновником является то, что на вашем домашнем компьютере используется функция планировщика Windows 10, широко известная как поддержка "предпочтительного ядра", которая отдает приоритет высокопроизводительным ядрам над низкопроизводительными. До 2018 года ЦП для настольных ПК, как правило, можно было доверить выполнение потока с одинаковой скоростью, независимо от того, на какое ядро ​​вы его поставили. Даже если одно ядро ​​теоретически способно работать на более высокой частоте при заданном напряжении, чем другое ядро, ЦП не предназначен для этого.

Только с появлением в 2018 году процессоров AMD Zen+ Ryzen эта ситуация стала широкомасштабной. С этими моделями AMD начала позволять процессорам с ядрами разного качества разгоняться до разных тактовых частот в зависимости от того, какие ядра находятся под нагрузкой. Это оказалось в значительной степени неэффективным, когда планировщик переключал поток на каждое ядро ​​независимо от профиля производительности. Снижение производительности усугублялось архитектурой AMD, в которой ядра были разделены на группы, называемые «CCX»; передача потока от одного ядра к другому внутри CCX выполняется быстрее, чем его распределение между разными CCX.

ЦП Intel "Extreme Edition" также имеют такую ​​явную поддержку смешанной производительности. Они называют это технологией Intel Turbo Boost Max 3.0. Intel заявляет, что самой ранней версией Windows 10, поддерживающей это, является «RS5», которая выглядит как 1809.

Благодаря технологии Intel® Turbo Boost Max 3.0 производительность малопоточных приложений оптимизируется за счет определения самых быстрых ядер вашего процессора и направления на них наиболее важных рабочих нагрузок.

До 2019 года все версии Windows игнорировали эти факты и распределяли потоки одинаково по всем физическим ядрам процессоров AMD. Windows 10 версии 1903 включает обновленный планировщик, который знает о модулях AMD CCX и пытается удерживать потоки в одном и том же модуле. ссылка

Улучшения призваны оказать особое влияние на задачи, использующие лишь несколько ядер. Теперь потоки будут реже переключаться между отдельными CCX.

В Windows 10 версии 1909 внесены дополнительные улучшения в планировщик, теперь он информирует о ситуации со смешанной производительностью ядра в функции, которая называется «Оптимизированная оптимизация ядер ЦП». ссылка

В недавнем сообщении в блоге Windows Insider Microsoft заявила, что Windows 10 19H2 будет включать оптимизацию распределения инструкций по этим привилегированным ядрам.

Я признаю, что не уверен на 100 % в своем понимании этой временной шкалы, и предпочитаемые ядра могут использоваться в более ранних версиях, но найти конкретную информацию об этом оказалось на удивление сложно. Большинство новостных сообщений, похоже, соглашаются с тем, что поддержка «предпочтительного ядра» является совершенно новой для 1909 года, несмотря на формулировку, подразумевающую, что она присутствовала в более ранних версиях.

Архитектура ARM с 2011 года явно поддерживала конфигурацию со смешанной производительностью, подобную этой, называемую big.LITTLE. Сборка Windows 10, работающая на ARM, была выпущена в 2017 году, а поддержка big.LITTLE была включена с самого начала или, по крайней мере, к 2018 году. Кажется, это хорошо сочетается с добавлением поддержки для нашей современной ситуации с Intel и AMD.

Кроме того, логические ядра исключаются только до тех пор, пока они не потребуются, потому что они припаркованы, а не потому, что сам планировщик что-то понимает о них. ссылка

Core Parking поддерживается только в Windows Server 2008 R2. Однако алгоритм и инфраструктура Core Parking также используются для балансировки производительности процессоров между логическими процессорами в клиентских системах Windows 7 и процессорами, поддерживающими технологию Intel Hyper-Threading.

Читайте также: