Планирование ядра для 1024 процессоров
Azul Systems имеет устройство, поддерживающее тысячи кеш-когерентных процессоров. Мне хотелось бы узнать, какие изменения должны произойти в операционной системе, чтобы запланировать тысячи одновременно работающих потоков.
Ответы
Ответ 1
Вы спрашиваете о возможных изменениях ОС, поэтому я предполагаю, что за этими усилиями будет создана значительная инженерная команда.
Есть также несколько частей поясняющей информации, которые помогут определить параметры проблемы:
Сколько IPC (взаимодействие между процессами) вам нужно?
Действительно ли они должны быть потоками, или они могут быть процессами?
Если это процессы, все в порядке, если они должны разговаривать друг с другом через сокеты, а не с помощью общей памяти?
Что такое архитектура памяти? Вы прямо SMP с 1024 ядрами, или есть какая-то другая NUMA (неравномерная архитектура памяти) или MMP, идущая здесь? Каковы ваши таблицы страниц?
Зная только самую маленькую информацию о системах Azul, я бы предположил, что у вас очень мало IPC, и что простая модель "запускать одно ядро на ядро" может действительно работать нормально. Если процессы должны взаимодействовать друг с другом, тогда они могут создавать сокеты и передавать данные таким образом. Поддерживает ли ваше оборудование эту модель? (Вероятно, в конечном итоге вам понадобится один IP-адрес для каждого ядра, а при 1024 IP-аддирах это может быть проблематичным, хотя все они могут быть NAT'd, и, возможно, это не так уж и важно). Если курс, эта модель привела бы к некоторой неэффективности, например, к дополнительным страницам таблиц, а также к изрядной доле оперативной памяти и даже не поддерживалась вашей аппаратной системой.
Даже если "1 ядро на ядро" не работает, вы можете запустить ядра 1024/8 и быть в порядке, позволяя каждому ядру управлять 8 физическими процессорами.
Тем не менее, если вы хотите запустить 1 поток на ядро в традиционной машине SMP с 1024 ядрами (и только несколькими физическими процессорами), то я бы ожидал, что старомодный планировщик O (1) - это то, что вы хотите, Вероятно, ваш процессор [0] окажется почти на 100% в ядре и сделает обработку прерываний, но это просто отлично подходит для этого случая использования, если вам не нужно больше 1 ядра для обработки вашей рабочей нагрузки.
Ответ 2
Планирование тысяч потоков не имеет большого значения, но планирование их на сотни процессоров. Что вам нужно, в первую очередь, - это очень мелкозернистая блокировка или, тем не менее, блокирующие данные структуры и алгоритмы. Вы просто не можете позволить 200 процессорам ждать, пока один процессор выполняет критический раздел.
Ответ 3
Создание шкалы для Linux было длительным и текущим проектом. В первом многопроцессорном ядре Linux было единственное блокирование защиты всего ядра (Big Kernel Lock, BKL), которое было простым, но ограниченным масштабируемостью.
Впоследствии блокировка была сделана более мелкозернистой, то есть существует множество замков (тыс.?), каждая из которых покрывает только небольшую часть данных. Тем не менее, существуют ограничения в отношении того, как далеко это можно сделать, поскольку мелкозернистая блокировка имеет тенденцию быть сложной, и блокировка накладных расходов начинает доставлять преимущество в производительности, особенно учитывая, что большинство многопроцессорных Linux-систем имеют относительно небольшое количество процессоров.
Другое дело, что, насколько это возможно, ядро использует структуры данных per-cpu. Это очень важно, так как это позволяет избежать проблем с когерентностью кеширования с общими данными, и, конечно, нет накладных расходов на блокировку. Например. каждый процессор запускает собственный планировщик процессов, требуя только случайной глобальной синхронизации.
Кроме того, некоторые алгоритмы выбираются с учетом масштабируемости. Например. некоторые данные, предназначенные для чтения, защищены с помощью Read-Copy-Update (RCU) вместо традиционных мьютексов; это позволяет читателям работать во время параллельного обновления.
Как и в случае с памятью, Linux пытается выделить память из той же NUMA node, что и там, где выполняется процесс. Это обеспечивает лучшую пропускную способность памяти и латентность для приложений.
Ответ 4
Мое необразованное предположение состояло бы в том, что на процессор есть очередь выполнения и алгоритм обработки работы, когда процессор простаивает. Я мог видеть, что это работает в модели M: N, где в процессе работы есть один процесс за процессор и легкие процессы. Тогда это будет похоже на работу с кратким потоком, например, в библиотеке fork-join в Java-7.
Если вы действительно хотите узнать, зайдите в Solaris Internals или выкопайте код ядра Solaris. Я все еще читаю Design and Impl of FreeBSD, а Internals Solaris является следующим в моем списке, поэтому все, что я могу сделать, это сделать дикие догадки atm.
Ответ 5
Я уверен, что SGI Altix, который у нас есть на работе (который делает ccNUMA), использует специальное оборудование для когерентности кэша.
Существует огромная надстройка, связанная с хранением 4 МБ кэша на каждый когерентный. Это вряд ли произойдет только в программном обеспечении.
в массиве из 256 процессоров вам потребуется 768mb ram только для хранения битов кэша-недействительности.
12 МБ кэша /128 байт на строку кэша * 256 м ядер.
Ответ 6
Модификация ОС - это одно, но использование неизмененного кода приложения - это трата оборудования. При переходе на какой-то предел (в зависимости от аппаратного обеспечения) усилия по сохранению согласованности и синхронизации для выполнения общего кода просто слишком велики. Вы можете это сделать, но это будет очень дорого.
Со стороны ОС вам понадобится сложная аффинная модель, т.е. Не прыгать с процессоров только потому, что ваша занята. Планирование потоков на основе аппаратной топологии - взаимодействие потоков на процессорах, которые "близки" для минимизации штрафов. Простая кража работы не является хорошим решением, вы должны учитывать топологию. Одним из решений является иерархическая кража работы - кража работы по расстоянию, разделение топологии на сектора и попытка кражи с самого начала.
Прикосновение к проблеме блокировки; вы все равно будете использовать спин-блокировки и такие, но используя совершенно разные реализации. Это, вероятно, самая запатентованная область в CS в эти дни.
Но, опять же, вам нужно будет программировать специально для такого масштабного масштаба. Или вы просто не используете его. Никакие автоматические "параллелизаторы" не сделают это для вас.
Ответ 7
Самый простой способ сделать это - связать каждый процесс/поток с несколькими CPUS, и тогда только эти процессоры должны будут конкурировать за блокировку этого потока. Очевидно, что нужно будет каким-то образом перемещать потоки для выравнивания нагрузки, но в архитектуре NUMA вам следует как можно меньше минимизировать это.
Ответ 8
Даже в двухъядерных системах Intel я уверен, что Linux уже может обрабатывать "тысячи" потоков с помощью собственных потоков posix.
(Glibc и ядро должны быть настроены для поддержки этого, однако, я считаю, что большинство систем в настоящее время имеют это по умолчанию сейчас).