Привет, Хабр! Меня зовут Максим, в YADRO я разрабатываю методики тестирования аппаратных средств. В этой статье я подробно опишу, как процессоры обмениваются данными в многопроцессорных системах Intel. Расскажу, как здесь выбирать процессор с учетом количества линков UPI (Ultra Path Interconnect) и почему иногда даже мощные серверные процессоры не спасают от тормозов запущенного на них софта.
В материале я буду объяснять базовые понятия, так что он вполне сгодится даже для первого знакомства с темой — аппаратных инженеров, программистов, сисадминов и всех, кому интересна компьютерная архитектура.
Что такое Ultra Path Interconnect (UPI)
Чтобы разобраться в теме, стоит начать с основного определения. Ultra Path Interconnect (UPI) — это высокоскоростное межпроцессорное соединение, разработанное Intel для высокопроизводительной связи с низкой задержкой в многопроцессорных системах с общим адресным пространством. Процессоры с поддержкой UPI на данный момент поддерживают от двух до четырех таких соединений.
Технология UPI пришла на смену QPI (QuickPath Interconnect) в 2017 году и широко применяется в платформах Intel Xeon Skylake-SP.
Ключевые отличия UPI от QPI
Объем памяти на сокет и пропускная способность ввода-вывода у Intel очень быстро приблизились к пределам масштабируемости QPI, поэтому ей на смену и пришел UPI. Как и с большинством межсоединений, компания могла бы просто ускорить QPI за счет большего напряжения и частоты соединения, но все равно столкнулась бы с точкой убывающей отдачи. Так что был сделан выбор в пользу нового стандарта.
В чем принципиальная разница между стандартами? QPI требует статического предоставления ресурсов на целевом объекте до того, как обслужит запросы сообщений. UPI же реализует более адаптивный подход: запускает запросы, ожидающие, пока ресурсы станут доступны на целевом объекте.
Другие преимущества UPI по сравнению с QPI:
Меньше энергопотребление. В состоянии низкого энергопотребления UPI потребляет на треть меньше, чем QPI в том же состоянии.
Быстрее передача данных. Уже со старта UPI обеспечивает до 10,4 ГТ/с (гигатранзакций в секунду) на каждый линк. QPI за свою историю смог вырасти только до 9,6 ГТ/c. Сегодня скорость Intel UPI в последней версии 3.0 составляет уже 16-20 ГТ/с.
Больше пропускная способность (+4–21% на канал) и более низкая задержка — за счет более современной архитектуры UPI.
Как работает UPI
UPI является соединением point-to-point (точка-точка) и позволяет процессорам обмениваться данными напрямую, без общей шины или других промежуточных устройств. Так уменьшается задержка и увеличивается пропускная способность связи между процессорами. В системах же, где процессоры не имеют прямого соединения, данные придется отправлять через общую шину или другое промежуточное устройство, что увеличивает задержки и снижает производительность. Быстрая передача данных особенно важна в многопроцессорных системах, где несколько процессоров должны работать вместе для выполнения сложных задач.


UPI используют в многопроцессорных системах с общим адресным пространством, где несколько процессоров могут обращаться к одной и той же оперативной памяти. Здесь UPI обеспечивает когерентность оперативной памяти. Она особенно важна в системах, где несколько процессоров работают вместе над задачами с доступом к общим данным. С UPI данные оперативной памяти остаются согласованными и актуальными, даже когда несколько процессоров работают с ними одновременно.
Для эффективного управления кешем и оперативной памятью с целью сохранения когерентности UPI использует механизмы Combined caching and home agent (CCHA) и Directory-based coherence.
Combined caching and home agent (CCHA)
Каждый процессор в UPI имеет собственный L1- и L2-кеш, а также доступ к общему кешу L3 (LLC) всех процессоров. Однако процессоры должны убедиться, что данные, к которым они обращаются, актуальны и согласованы. Находить изменения в данных других кешей и соответственно обновлять свой локальный кеш процессорам помогает CCHA.
В предыдущих линейках процессоров Intel Xeon был предусмотрен распределенный агент кеширования Intel QPI, расположенный на каждом ядре, и централизованный агент Intel QPI Home, расположенный на каждом контроллере памяти. Теперь в актуальных процессорах семейства Intel Xeon Scalable реализован комбинированный CHA (CCHA), который распределен по всем ядрам и банкам LLC и поэтому автоматически масштабируется с ростом количества ядер и банков LLC.
Работа CCHA реализуется через процессы snoop request и snoop response. Snoop request (запрос на поиск) позволяет процессору отправить запрос в сеть, чтобы узнать, есть ли данные, к которым он хочет обратиться, в кеше другого процессора. Если данные есть, то другой процессор отправляет ответ на запрос, содержащий актуальные данные. Snoop response (ответ на поиск) позволяет процессору обновить свои кеши, если данные, к которым он хочет обратиться, были изменены в другом кеше. Так CHA поддерживает когерентность оперативной памяти, позволяя процессорам обновлять свои кеши и обеспечивать доступ к актуальным данным.
В работе CCHA необходимо учитывать еще один важный аспект — «грязные» строки. Это строки кеша, содержащие измененные данные, которые еще не были выгружены обратно в оперативную память. Они появляются, когда процессор уже изменил данные в кеше, но еще не выгрузил их обратно в память. Для достижения когерентности все «грязные» строки нужно в память выгрузить. Для этого используются механизмы write-through и write-back.
Write-through записывает данные в кеш и одновременно выгружает их обратно в оперативную память. Это гарантирует, что данные в кеше и в оперативной памяти всегда актуальны и согласованы. Write-back записывает данные в кеш, но не выгружает их сразу обратно в оперативную память. Вместо этого данные остаются в кеше до тех пор, пока не будут выгружены обратно в память.
Directory-based coherence
Directory-based coherence обеспечивает согласованность данных в памяти между всеми процессорами в системе. В рамках directory-based coherence процессоры хранят информацию о состоянии своих кешей в специальной структуре данных directory. В результате с помощью directory находить нужную информацию становится проще и быстрее. Уменьшается количество запросов и ответов, необходимое для поддержания когерентности кеша, повышается эффективность работы системы.

Архитектура NUMA
Для эффективного управления памятью в многопроцессорных системах используют архитектуру NUMA (Non-Uniform Memory Access). Здесь каждый процессор имеет свой кеш и контроллер оперативной памяти, что вместе образует NUMA-ноду. Любой процессор может обращаться к любому участку единого адресного пространства даже в памяти другой NUMA-ноды. В этом случае запрос будет выполнен через межпроцессорную шину и соответствующий контроллер памяти. Это уменьшает конфликты доступа к памяти и повышает эффективность использования памяти. Если процессору нужны данные, которые не хранятся в его кеше, то он также отправляет запрос по межпроцессорной шине.
Естественно, доступ к удаленной памяти оказывается гораздо медленнее, чем к локальной. Оттуда и название архитектуры – «неоднородный доступ к памяти».

Sub-NUMA — режим кластеризации для эффективного управления оперативной памятью
UPI также поддерживает режим кластеризации и слежения Sub-NUMA, который позволяет объединять несколько процессоров в sub-NUMA-ноду. На несколько NUMA-нод можно разбить и единый процессор. Это позволит чуть более эффективно использовать его ресурсы, но потребует ПО, которое способно корректно работать с большим количеством NUMA-нод.
Как количество линков UPI в CPU влияет на его работу в многопроцессорных системах
Процессоры могут иметь разное количество UPI-линков — 0, 2, 3, 4, — что значительно влияет на их возможность работы в многопроцессорных системах. Вне зависимости от количества UPI-линков у каждого процессора есть заданное производителем ограничение на количество поддерживаемых сокетов.
Это ограничение нужно учитывать при проектировании системы. Например, процессоры с двумя UPI-линками обычно поддерживают только двухпроцессорные системы, а процессоры с тремя или четырьмя UPI-линками могут поддерживать более сложные конфигурации, включая четырехпроцессорные и восьмипроцессорные системы. Рассмотрим разные варианты подробнее.
Процессоры без UPI-линков (CPU UPI Link = 0) могут работать только в однопроцессорных системах. Они не предназначены для многопроцессорных конфигураций и не могут быть соединены с другими процессорами для совместной работы. Такие процессоры используются в системах, где не требуется высокая масштабируемость.
Процессоры с двумя UPI-линками (CPU UPI Link = 2) могут работать в двухпроцессорных системах с увеличенной общей производительностью. Однако в четырехпроцессорных системах такие процессоры могут быть соединены только в кольцевую топологию, что приводит к низкой пропускной способности. Это ограничивает их использование в подобных конфигурациях.
Процессоры с тремя UPI-линками (CPU UPI Link = 3) могут работать в четырехпроцессорных системах, обеспечивая более высокую пропускную способность и гибкость в топологии соединения. Это позволяет создавать более сложные и производительные многопроцессорные конфигурации. В таких системах процессоры могут быть соединены в кольцевую топологию или топологию «каждый с каждым» (crossbar) — последняя обеспечивает максимальную пропускную способность и минимальную задержку.
Процессоры с четырьмя UPI-линками (CPU UPI Link = 4) могут работать в системах с 2, 4 или 8 процессорами, обеспечивая максимальную пропускную способность и масштабируемость. Это позволяет создавать высокопроизводительные вычислительные кластеры, где процессоры могут быть соединены в полносвязную топологию. Такие системы обеспечивают максимальную производительность и эффективность.
Различия между разными процессорами в двухпроцессорных системах зависят от нагрузки. Если она распределена по нодам и каждая нода работает с обращениями в основном к локальной памяти, то разница минимальна. Если же есть активное взаимодействие между процессорами — например, в базе данных, что активно обращается к памяти соседнего процессора, — разница будет значительной. Процессоры с большим количеством UPI-линков дадут более высокую производительность и меньшую задержку.
Таким образом, количество UPI-линков играет ключевую роль в определении возможностей процессора для работы в многопроцессорных системах и влияет на общую производительность и масштабируемость системы.

Как организована передача данных по UPI
Ядро процессора отправляет запрос доступа к данным в LLC (Last Level Cache). Если данные есть в LLC, то они передаются в кеш ядра. Если данных в LLC нет, то запрос направляется в UPI.
UPI формирует пакет запроса с информацией о запросе, включающей адрес данных, тип запроса (чтение или запись). Пакет запроса кодируется, для обеспечения целостности данных добавляется контрольная сумма.
-
Пакет запроса передается через UPI в виде цифрового электрического сигнала.
Пакет запроса кодируется в последовательность логических сигналов 0 и 1 с помощью специального алгоритма.
Закодированные данные преобразуются в серию импульсов электрического тока, которые представляют собой последовательность логических сигналов 0 и 1.
Импульсы с высокой скоростью идут по линиям UPI, что позволяет передавать большие объемы данных между процессорами.
-
Пакет запроса принимается целевым процессором, который проверяет контрольную сумму и декодирует пакет запроса. Если пакет запроса корректен, то процессор-ответчик обрабатывает запрос и формирует пакет ответа.
Импульсы принимаются на другом конце UPI и преобразуются обратно в пакет запроса.
Пакет запроса декодируется из последовательности логических сигналов 0 и 1 в исходные данные.
Пакет ответа содержит данные, которые запрашивались ядром процессора. Он кодируется, к нему добавляется контрольная сумма для обеспечения целостности данных.
Пакет ответа принимается ядром процессора, которое проверяет контрольную сумму и декодирует пакет ответа. Если пакет ответа корректен, то ядро процессора обрабатывает данные и использует их для выполнения инструкций.
Если данные, которые были переданы через UPI, актуальны, то они обновляются в LLC и кеше ядра. Впоследствии актуальные данные в кеше могут быть использованы другими ядрами локального процессора и другими процессорами для выполнения инструкций независимо от изменений памяти и LLC.
Протестировать работу UPI на серверном «железе» вы можете самостоятельно с помощью JTAG-отладчика, набора кабелей, а также ноутбука с набором специализированных утилит Intel.
Если вам интересна область аппаратного тестирования, обратите внимание на наши вакансии: