Планирование ядра для 1024 процессоров - PullRequest
13 голосов
/ 11 апреля 2009

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

Ответы [ 8 ]

15 голосов
/ 11 апреля 2009

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

6 голосов
/ 18 апреля 2009

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

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

Сколько нужно IPC (межпроцессное взаимодействие)?
Они действительно должны быть потоками или процессами?
Если они являются процессами, это нормально, если они должны общаться друг с другом через сокеты, а не с помощью общей памяти?
Что такое архитектура памяти? Вы прямой SMP с 1024 ядрами, или здесь есть какая-то другая NUMA (Неоднородная архитектура памяти) или MMP? Каковы ваши таблицы страниц?

Зная только самую маленькую информацию о системах Azul, я бы предположил, что у вас очень мало IPC, и что простая модель «запустить одно ядро ​​на ядро» может действительно сработать. Если процессам необходимо общаться друг с другом, они могут создавать сокеты и таким образом передавать данные. Ваше оборудование поддерживает эту модель? (Скорее всего, в конечном итоге вам понадобится один IP-адрес на ядро, и при 1024 IP-аддерах это может быть проблематично, хотя все они могут быть NAT, и, возможно, это не такая уж большая проблема). Конечно, эта модель может привести к некоторым неэффективным действиям, таким как дополнительные таблицы страниц, и значительному увеличению объема оперативной памяти, и может даже не поддерживаться вашей аппаратной системой.

Даже если «1 ядро ​​на ядро» не работает, вы можете запустить ядро ​​1024/8, и все будет в порядке, позволяя каждому ядру контролировать 8 физических процессоров.

Тем не менее, если вы хотите запустить 1 поток на ядро ​​в традиционной машине SMP с 1024 ядрами (и только несколькими физическими процессорами), то я ожидаю, что старомодный планировщик O (1) - это то, что вам нужно , Вполне вероятно, что ваш процессор [0] завершит работу на ядре почти на 100% и будет выполнять обработку прерываний, но это прекрасно для этого случая использования, если вам не требуется более одного ядра для обработки вашей рабочей нагрузки.

6 голосов
/ 15 апреля 2009

Создание масштаба для Linux было долгим и продолжающимся проектом. Первое ядро ​​Linux с поддержкой нескольких процессоров имело единственную блокировку, защищающую все ядро ​​(Big Kernel Lock, BKL), которая была простой, но с ограниченной масштабируемостью.

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

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

Кроме того, некоторые алгоритмы выбираются с учетом масштабируемости. Например. некоторые данные в основном для чтения защищены с помощью Read-Copy-Update (RCU) вместо традиционных мьютексов; это позволяет читателям продолжить работу во время одновременного обновления.

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

5 голосов
/ 11 апреля 2009

Мое необразованное предположение могло бы состоять в том, что для каждого процессора существует очередь выполнения и алгоритм кражи работы, когда процессор простаивает. Я мог видеть, что это работает в модели M: N, где на процессор приходится один процесс, а в качестве рабочих элементов используются легковесные процессы. Тогда это будет похоже на пул потоков для кражи работы, такой как в библиотеке fork-join Java-7.

Если вы действительно хотите это знать, выберите «Solaris Internals» или покопайтесь в коде ядра Solaris. Я все еще читаю Design & Impl из FreeBSD, с Solaris Internals, следующим в моем списке, так что все, что я могу сделать, это сделать дикие догадки.

1 голос
/ 16 апреля 2009

Самый простой способ сделать это - привязать каждый процесс / поток к нескольким CPUS, и тогда только эти ЦПУ должны будут бороться за блокировку в этом потоке. Очевидно, что должен быть какой-то способ перемещать потоки, чтобы выровнять нагрузку, но в архитектуре NUMA вы должны максимально уменьшить это.

1 голос
/ 14 апреля 2009

Модификация ОС - это одно, но использование неизмененного кода приложения - пустая трата оборудования. При превышении определенного предела (в зависимости от аппаратного обеспечения) усилия по обеспечению согласованности и синхронизации для выполнения универсального кода просто слишком велики. Вы можете сделать это, но это будет очень дорого. Со стороны ОС вам понадобится сложная модель сродства, то есть, чтобы не перепрыгивать процессоры только потому, что ваш занят. Планирование потоков на основе аппаратной топологии - взаимодействие потоков на процессорах, которые «близки», чтобы минимизировать штрафы. Простое воровство работы не является хорошим решением, вы должны учитывать топологию. Одним из решений является иерархический кража работы - красть работу на расстоянии, разделять топологию на сектора и пытаться красть сначала у ближайших. Немного касаясь вопроса блокировки; вы все равно будете использовать спин-блокировки и тому подобное, но с использованием совершенно разных реализаций. Это, вероятно, самая запатентованная область в CS в наши дни. Но, опять же, вам нужно будет программировать специально для такого масштабного масштаба. Или вы просто будете его недооценивать. Никакие автоматические «параллелизаторы» не сделают это за вас.

1 голос
/ 14 апреля 2009

Я почти уверен, что SGI Altix, который у нас работает (который использует ccNUMA), использует специальное оборудование для обеспечения согласованности кэша.

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

в массиве из 256 процессоров вам понадобится 768 МБ оперативной памяти только для хранения битов аннулирования кэша. Кэш-память 12 МБ / 128 байт на строку кэша * 256² ядер.

0 голосов
/ 03 июня 2009

Даже на двухъядерных системах Intel я уверен, что Linux уже может обрабатывать «тысячи» потоков с собственными потоками posix.

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

...