Планирование ядра для 1024 процессоров

Вот пример использования MAT2CELL. Он делит изображение на плит N-by-M и обрабатывает случай, когда размер изображения не равномерно делится на количество фрагментов.

%# 2D grayscale image
I = imread('coins.png');

%# desird number of horizontal/vertical tiles to divide the image into
numBlkH = 4;
numBlkW = 4;

%# compute size of each tile in pixels
[imgH,imgW,~] = size(I);
szBlkH = [repmat(fix(imgH/numBlkH),1,numBlkH-1) imgH-fix(imgH/numBlkH)*(numBlkH-1)];
szBlkW = [repmat(fix(imgW/numBlkW),1,numBlkW-1) imgW-fix(imgW/numBlkW)*(numBlkW-1)];

%# divide into tiles, and linearize using a row-major order
C = mat2cell(I, szBlkH, szBlkW)';
C = C(:);

%# display tiles i subplots
figure, imshow(I)
figure
for i=1:numBlkH*numBlkW
    subplot(numBlkH,numBlkW,i), imshow( C{i} )
end

Входное изображение и результирующие фрагменты:

input_image [/g0] tiles [/g1]

13
задан McGovernTheory 10 April 2009 в 20:34
поделиться

8 ответов

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

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

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

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

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

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

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

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

6
ответ дан 1 December 2019 в 19:32
поделиться

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

15
ответ дан 1 December 2019 в 19:32
поделиться

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

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

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

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

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

это позволяет читателям продолжать работу во время одновременного обновления.

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

это позволяет читателям продолжать работу во время одновременного обновления.

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

6
ответ дан 1 December 2019 в 19:32
поделиться

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

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

5
ответ дан 1 December 2019 в 19:32
поделиться

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

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

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

1
ответ дан 1 December 2019 в 19:32
поделиться

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

1
ответ дан 1 December 2019 в 19:32
поделиться

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

1
ответ дан 1 December 2019 в 19:32
поделиться

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

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

0
ответ дан 1 December 2019 в 19:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: