АНТОН БОРИСОВ
Знакомимся с HPC-кластером OpenMosix
Большую часть времени ПЭВМ, скажем честно, простаивает. Средняя загрузка не превышает 20%. Но как только начинается сборка приложений, например на C++, или оцифровка видео-, аудиофайлов, то становится очевидным недостаток вычислительных ресурсов. Основная идея HPC-кластеров – задействовать ресурсы, свободные на других узлах кластера.
Что такое кластер
Кластер – это две или более самостоятельные системы, объединенные в единое целое посредством специального программного и аппаратного обеспечения. Основное звено кластера – это единичный компьютер, называемый узлом. Кластеры могут расти – «масштабироваться» – путем добавления новых узлов. При этом синергетическое целое мощнее, нежели отдельный узел. Изменения в структуре кластера, например, появление и удаление узлов из состава кластера (по разным причинам – авария или, наоборот, восстановление после критической ситуации) фиксируется всеми оставшимися/новыми узлами.
Типы кластеров
На сегодняшний момент широко известны и распространены 3 типа кластеров – отказоустойчивые (например, LifeKeeper – см. [1]), с балансировкой загрузки (Load-Balancing) и высокопроизводительные (High-Perfomance Computing):
- Отказоустойчивый кластер состоит из двух или более узлов, между которыми существует выделенное соединение (heartbeat), которое используется для обмена служебной информацией между узлами. Как только какой-либо из узлов перестает функционировать, то второй (резервный) узел берет его функции на себя.
- Задача кластера с балансировкой нагрузки заключается в том, чтобы перенаправить запрос, скажем к веб-серверу, к наименее загруженному в данный момент времени узлу. По существу, этот тип кластера можно также назвать отказоустойчивым, только с дополнительным функционалом балансировки и с большим количеством узлов.
- В высокопроизводительном кластере узлы сконфигурированы таким образом, чтобы общая производительность была максимальной. В этом типе кластера присутствуют и балансировочные механизмы – задания распределяются между узлами. Самое интересное в таком типе кластера – факторизация процесса (разбиение задачи на несколько параллельных подзадач). Процесс не ожидает освобождения CPU, а запускает свои подзадачи на разных узлах.
Суперкомпьютеры и кластеры
Традиционно ресурсоемкие математические вычисления выполнялись на суперкомпьютерах. Они выпускались определенным количеством производителей и организация, которая хотела купить суперкомпьютер, должна была обладать немалым финансовым ресурсом. Естественно, что большинство университетов не могли себе позволить такого рода дорогую игрушку, поэтому в их недрах начала создаваться концепция кластера для академических кругов. Цель данной концепции – подготовить условия для распараллеливания задачи между узлами, передать обработку подзадач на узлы и затем собрать результаты каждой подзадачи. Кластер предполагалось собирать на PC-платформе, благо она становилась всё более и более распространенным явлением и по сути дешевой.
Кластерные модели
Существует несколько методов распараллеливания – N(UMA), DSM, PVM и MPI. Некоторые из этих схем реализованы аппаратно, другие программно. Бывают и смешанные решения:
- (N)UMA ((Non-)Uniform Memory Access) – узлы имеют доступ к общей памяти, где выполняется код. Стоит отметить, что в Linux-ядре есть NUMA-реализация.
- DSM (Distributed Shared memory) реализовано как программно, так и аппаратно. Концепция этого метода заключается в предоставлении уровня абстракции для физически распределенной памяти.
- MPI (Message Passing Interface, интерфейс передачи сообщений) – это открытая спецификация для создания библиотек передачи сообщений. В частности, библиотека MPICH – самое известное решение на базе MPI. Другое известное решение – библиотека LAM.
- PVM (Parallel Virtual Machine) является собратом MPI. Фунционирует PVM в пользовательском пространстве, поэтому каких-то модификаций на уровне ядра не требуется. Пользователь с достаточными правами может запустить PVM.
Сущность OpenMosix
Пакет OpenMosix – это патчи к ядру Linux. На момент написания этого материала существуют патчи для ядра 2.4.26 и для ветки 2.6. Так как OpenMosix реализован в виде патчей, то сохраняется полная совместимость между программами, файлами и другими ресурсами в Linux.
Обычный пользователь может и не заметить изменений между Linux-машиной и OpenMosix-кластером, ибо последний будет расматриваться как рядовая Linux-машина, только немного производительнее. Внутренний механизм балансировки прозрачно производит миграцию процессов на узлы кластера. Оптимальная загрузка кластера вычисляется динамически через определенные промежутки времени. Вы также можете произвести нужную подстройку параметров кластера. Прозрачный механизм миграции играет интересную роль – из-за него весь кластер выглядит как большая SMP-машина со множеством процессоров (каждый узел в роли процессора). В рамках OpenMosix разработана файловая система (oMFS) для HPC-приложений, которая в отличие от NFS поддерживает целостность ссылок, атрибуты времени и кеширование.
Сегодня в нашем обзоре в качестве узлов кластера будут выступать 3 машины:
- Intel(R) Pentium(R) 4 CPU 1.80 ГГц (256 Мб ОЗУ)
- Intel Pentium III (Katmai) 602.149 МГц (256 Мб ОЗУ)
- Intel(R) Pentium(R) 4 CPU 3.00 ГГц (128 Мб ОЗУ)
Все узлы соединены через хаб (100 МБит) в единое пространство. Операционная система, OC Linux, первоначально установлена на самой быстрой машине, а затем была клонирована на все остальные. Стоит отметить, что при установке, помимо базовых пакетов, также следует выбрать и QT-библиотеку (на базе QT мы впоследствии соберем утилиты мониторинга кластера).
Итак, первый шаг по установке и настройке ПЭВМ с ядром по умолчанию пропускаем. Следует настроить SSH-сервис, т.к. благодаря ему мы будем управлять узлами.
Далее заберем ядро (2.4.26) с включенными патчами для OpenMosix (32 Мб):
wget http://citkit.dl.sourceforge.net/sourceforge/openmosix/openmosix-kernel-source-2.4.26-openmosix1.i386.rpm
Для экономии трафика можно взять только патчи и наложить их на оригинальное ядро с kernel.org самостоятельно (200 Кб):
wget http://citkit.dl.sourceforge.net/sourceforge/openmosix/openMosix-2.4.26-1.bz2
# rpm -ih --nodeps openmosix-kernel-source-2.4.26-openmosix1.i386.rpm
# cd /usr/src/linux-2.4.26-openmosix1/
# make xconfig
Ставим галочки для компонентов OpenMosix (рис. 1), остальные компоненты для ядра не изменяем, сохраняем конфигурацию и собираем ядро.
# makedep&& make && make bzImage && make modules
# make modules_install
Добавляем нужную опцию в загрузчик. В случае lilo:
image = /boot/mosix-bzImage
root = /dev/sda1
label = om.Linux
read-only
# /sbin/lilo -v
И перезагрузка.
Рисунок 1. Компоненты ядра, отвечающие за функционирование OpenMosix
Для управления и тюнинга узлов в OpenMosix предусмотрен специальный пакет утилит – openmosix-tools. Установим его.
wget http://citkit.dl.sourceforge.net/sourceforge/openmosix/openmosix-tools-0.3.6-2.tar.gz
# tar xzvf openmosix-tools-0.3.6-2.tar.gz
# cd openmosix-tools-0.3.6-2
# ./configure --prefix=/opt/OpenMosix --with-kerneldir=/usr/src/linux-2.4.26-openmosix1
# make && make install
После установки этого пакета есть два варианта, каким именно образом узлы будут сообщать друг другу о своих характеристиках (загрузка, вычислительная мощность) и координатах (IP-адрес). Либо указать жестко в файле /etc/openmosix.map, либо положиться на сервис автоопределения узлов (omdiscd). Структура файла openmosix.map представлена ниже:
# MOSIX-# IP number-of-nodes
# ============================
1 10.0.0.1 1
100 0.0.0.100 1
В первой колонке указывается номер узла (в моем случае первый узел имеет номер 1, второй – 100), во второй колонке IP-адрес, в третьей колонке – количество узлов в диапазоне. Т.е. предполагая, что первые пять узлов имеют последовательные адреса от 10.0.0.1 до 10.0.0.5 смысла их перечислять нет. Стоит только указать, что количество узлов равно в этом случае 5.
1 10.0.0.1 5
Так раздаются адреса статически. А для их динамического определения будет использоваться файл /etc/openmosix/openmosix.config, где прописываются такие параметры, как:
- AUTODISCIF – имя интерфейса, через который производит автопоиск (если на узле несколько сетевых интерфейсов).
- MYOMID – номер данного узла.
- MIGRATE – разрешать ли процессам миграцию с данного узла или нет.
- MFS – использовать Mosix FileSystem или нет.
Я пошел по пути динамического определения узлов и для этого включил старт автоматического определения omdiscd – добавил в /etc/rc.d/rc.local строку:
/opt/OpenMosix/sbin/omdiscd -i eth0
Таким образом, при последовательном старте узлов вы можете отслеживать в логах процесс формирования кластера:
Jul 26 22:01:57 athlon kernel: openMosix #1 is at IP address 10.0.0.1
Jul 26 22:01:57 athlon omdiscd[1996]: Notified kernel to activate openMosix
Jul 26 22:02:55 athlon kernel: eth0: Setting full-duplex based on MII #1 link partner capability of 45e1.
Jul 26 22:04:11 athlon kernel: openMosix configuration changed: This is openMosix #1 (of 2 configured)
Jul 26 22:04:11 athlon kernel: openMosix #1 is at IP address 10.0.0.1
Jul 26 22:04:11 athlon kernel: openMosix #100 is at IP address 10.0.0.100
|
Для того чтобы системные процессы (те, что отвечают за загрузку и выключение узла) не мигрировали на другие узлы, используем в файле /etc/inittab такую конструкцию: строки с участием директории rc.d:
si:S:sysinit:/etc/rc.d/rc.S
перепишем так:
si:S:sysinit:/bin/mosrun -h /etc/rc.d/rc.S
что дословно означает «запускать стартовый скрипт rc.S на домашнем узле».
Также следует поменять строки, где участвует rc.d, а также строку:
ca::ctrlaltdel:/sbin/shutdown -t5 -r now
которая будет выглядеть так:
ca::ctrlaltdel:/bin/mosrun -h /sbin/shutdown -t5 -r now
Все готово, чтобы первый настроенный узел клонировать на другие машины. Воспользуйтесь либо командой dd, либо программой Norton Ghost. Затем в клонированных узлах поменять IP-адреса, hostname, и дело в шляпе.
Для тестирования производительности сформированного кластера я решил проверить, за какое время будет собран MPlayer [2].
Тестируем быстродействие
Как я проводил замеры. Когда кластер обнаруживает новый узел, он создает в виртуальном каталоге /proc/hpc/nodes новую ветку, совпадающую с номером обнаруженного узла. Следует отметить, что весь каталог /proc/hpc относится к функционированию OpenMosix. Таким образом, если появляется новый узел с номером XXX, то автоматически появляется каталог /proc/hpc/nodes/XXX, в котором хранятся файлы с характеристиками данного узла. В частности, содержимое файла load нас и будет интересовать. Производительность узлов в OpenMosix оценивается по сравнению с виртуальной ПЭВМ класса Celeron 1 ГГц, поэтому не удивляйтесь, когда увидите, что производительность конкретного узла, например, равняется 20000. Это означает, что по сравнению с эталонным 1 ГГц данный узел в 2 раза производительнее.
Итак, производим калькуляцию. Сохраним данный скрипт, использующийся в наших подсчетах в дальнейшем.
#!/bin/sh
NODE1=/proc/hpc/nodes/573
NODE2=/proc/hpc/nodes/574
NODE3=/proc/hpc/nodes/575
FILENAME=hpc_load.txt
i=0
while true
do
DateStr='date +%H-%M-%S'
Load1='cat $NODE1/load'
Load2='cat $NODE2/load'
Load3='cat $NODE3/load'
echo "$DateStr ($i): $Load1, $Load2, $Load3" >> $FILENAME
echo "Time: $DateStr ($i). Load: $Load1, $Load2, $Load3";
i='expr $i + 1';
sleep 1s;
done
Скрипт получился простеньким для понимания. Нагрузку «в попугаях» мы трансформируем в график, где посмотрим, какое участие принял каждый конкретный узел в процессе сборки.
Так как считается, что кластер в нашем случае – это единое пространство с увеличенным количеством процессоров, то используем данный факт. Сначала посчитаем время сборки, когда работает только один узел, самый быстрый. Предварительно распакуем MPlayer:
# wget MPlayer
# tar xzvf MPlayer
# cd MPlayer
# ./configure
Теперь запускаем наш скрипт collect_hpc_load.sh и считаем время:
# time make dep
# time make
real 0m19.068s
user 0m2.570s
sys 0m16.410s
real 5m11.963s
user 3m44.950s
sys 1m26.410s
|
Включаем узел с самым медленным CPU. Теперь производим подсчет.
real 0m20.693s
user 0m2.670s
sys 0m17.450s
real 5m17.013s
user 4m5.820s
sys 1m43.620s
|
Получили еще худший результат. Почему? Очень просто – у нас сформировалось много процессов, но с маленькими вычислительными запросами. Общее время миграции по 100-Мбитной сети плюс время компиляции превысило предыдущий результат.
Включаем третий узел с 1.8 ГГц CPU. Посмотрим на цифры.
real 0m24.860s
user 0m2.800s
sys 0m17.610s
real 4m18.754s
user 4m17.620s
sys 2m16.540s
|
Отлично. А что произойдет при отключении самого медленного узла? Отключаем, проверяем.
real 0m23.539s
user 0m3.260s
sys 0m17.580s
real 4m24.304s
user 4m18.270s
sys 2m14.320s
|
Выигрыш от медленного узла составил примерно 6 секунд. Как говорится – спорный результат. Стоит ли овчинка выделки – а именно, нужен ли третий узел? Очевидно стоит отказаться в пользу двухузловой модели.
Полученные результаты удобнее анализировать графически. Импорт в OpenOffice и дальнейшее преобразование в диаграммы закончилось получением этих рисунков. Синим цветом отмечен узел на базе Pentium 4 CPU 3 ГГц, красным – узел Pentium 4 CPU 1.8 ГГц, белым – Pentuim 3 CPU 600 МГц (рис. 2-5).
Рисунок 2. Загрузка кластера при одноузловом варианте
Рисунок 3. Загрузка кластера при двухузловом варианте (оба узла Pentium 4)
Рисунок 4. Загрузка кластера при двухузловом варианте (один из узлов Pentium 3)
Рисунок 5. Загрузка кластера при трехузловом варианте
Утилиты мониторинга
Как производить текущий мониторинг загрузки? К счастью, у OpenMosix достаточно широкая аудитория пользователей, благодаря которым появились утилиты визуального контроля и управления. Нужный нам сейчас пакет называется openmosixview.
# wget openmosixview-1.5.tar.gz
# tar xzvf openmosixview-1.5.tar.gz
# cd openmosixview-1.5
Данное ПО написано на QT – надеюсь, вы его поставили, не забыли. Оно состоит из следующих программ:
- openMosixview – приложение для мониторинга и управления кластера.
- openMosixprocs – приложение, показывающее процессы и их свойства.
- openMosixcollector – сервис по сбору статистики.
- openMosixanalyzer – приложение для анализа данных, собранных сервисом статистики.
- openMosixhistory – приложение, для просмотра миграций процессов в определенный момент времени.
- openMosixpidlog – приложение для мониторинга единичных процессов.
- 3dmosmon – приложение для объемного мониторинга кластера.
К сожалению, у меня последняя программа не захотела собираться. Решение оказалось простым – при компиляции приложения 3dmosmon следует заменить инициализацию переменных в файле materials.h из вида:
static material_struct whiteMaterials = {
{1.0, 1.0, 1.0, 1.0},
{0.0, 0.0, 0.0, 1.0},
{1.0, 1.0, 1.0, 1.0},
{20.0}
};
в вид:
static material_struct whiteMaterials = {
{1.0, 1.0, 1.0, 1.0},
{0.0, 0.0, 0.0, 1.0},
{1.0, 1.0, 1.0, 1.0}, 20.0
};
А для приложения mosstatd добавить ключи, чтобы строка выглядела следующим образом (красным шрифтом отмечены добавленные параметры):
gcc -I/usr/src/linux-2.4.26-openmosix1/include/ -I/usr/local/openmosix-tools/include/ -o mosstatd -L/usr/local/openmosix-tools/lib/ -lmos mosstatd.c
В итоге, запустив предварительно сервис сбора статистики mosstatd (например, через инициализационный скрипт /etc/rc.d/rc.local), мы сможем отслеживать загрузку кластера в виде трехмерного изображения (см. рис. 6).
# 3dmosmon localhost
Рисунок 6. Трехмерное изображение загрузки кластера
Сборка остальных программ достаточно тривиальна:
# cd openmosixview
# make
# ./openmosixview
По такому же принципу собираются и остальные утилиты.
openMosixview – наглядный пример, какие узлы в данный момент загружены и общая картина по производительности (см. рис. 7).
Рисунок 7. Визуальная картина загрузки посредством утилиты openMosixview
Приведена ситуация, когда отключен наименее производительный узел. Отключение узла от кластера отображается индикатором красного цвета.
Графическая утилита openmosixmigmon позволяет, не утруждая себя поисками PID конкретного процесса, перебросить его выполнение на другой узел (см. рис. 8).
Рисунок 8. Контроль за миграцией процессов в кластере
В частности, некоторые процессы с головного узла уже насильно мигрированы к соседям и используют их вычислительные мощности.
Следующая интересная утилита из данного пакета называется openMosixanalyzer. Видна нагрузка как в целом на кластер, так и на отдельные узлы за определенный момент времени (см. рис. 9).
Рисунок 9. Статистика по загрузке кластера в определенное время
А чтобы такая статистика велась на постоянной основе, придуман сервис openMosixcollector, как видим из названия, его работа заключается в сборе данных и сохранении их на диске.
Запускается он просто – «openmosixcollector -d» – работает в качестве сервиса. Собранная информация раз в сутки сбрасывается в директорию /tmp/openmosixcollector_ДАТА_ВРЕМЯ.
Давайте теперь ознакомимся с утилитами по настройке кластера.
mosctl – утилита для просмотра/редактирования параметров узла.
Рассмотрим характерные конструкции на основе данной утилиты.
# mosctl –help
Usage: mosctl command
Available commands: stay/nostay, lstay/nolstay, block/noblock, quiet/noquiet,
mfs/nomfs, expel, bring, gettune, getdecay,
whois [mosix_no|IP-address|hostname],
getload [node-number], getspeed [node-number],
status [node-number], getmem [node-number],
getfree [node-number], getutil [node-number],
getyard, setyard [node-type], setspeed speed,
setdecay interval(seconds) slow(/1000) fast(/1000),
isup [node-number]
|
- mosctl whois node0 – выводит IP-адрес узла node0;
- mosctl getload node0 – выводит загрузку узла node0;
- mosctl getspeed node0 – выводит скоростную характеристику узла node0;
- mosctl gettune – выводит показатели для данного узла;
- mosctl bring – передает сигнал мигрированным процессам для возврата на домашний узел.
Как видите, тот пример, что мы рассмотрели и использовали в своей работе, можно переписать намного нагляднее при использовании утилиты mosctl.
# moslimit –help
Usage: moslimit command
Available commands:
setloadlimit [numeric-value], setcpulimit [numeric-value],
setllimitmode [numeric-value], setcpulimitmode [numeric-value],
getloadlimit [node-number], getcpulimit [node-number],
getllimitmode [node-number], getcpulimitmode [node-number],
getloadlocal [node-number], getcpulocal [node-number],
getloadremote [node-number], getcpuremote [node-number]
|
Для миграции процессов в пределах кластера предназначена утилита migrate.
# migrate –help
Usage: migrate pid {OpenMosix-ID|home|balance} |
А вот список процессов, который мы сможем увидеть при запуске утилиты ompsinfo.
root@node0:~# ompsinfo
CMD PID NODE NMIGS LOCK CANTMOVE
init 1 0 0 0 system
keventd 2 0 0 0 clone_vm
ksoftirqd_CPU0 3 0 0 0 clone_vm
kswapd 4 0 0 0 clone_vm
bdflush 5 0 0 0 clone_vm
kupdated 6 0 0 0 clone_vm
khubd 8 0 0 0 clone_vm
kjournald 10 0 0 0 clone_vm
oM_migd 11 0 0 0 system, clone_vm
oM_infoD 12 0 0 0 system, clone_vm, rt_sched
memsorter 13 0 0 0 system, clone_vm
syslogd 62 0 0 1 migratable but locked
klogd 65 0 0 1 migratable but locked
inetd 340 0 0 1 migratable but locked
sshd 343 0 0 0 migratable
crond 351 0 0 1 migratable but locked
gpm 360 0 0 1 migratable but locked
agetty 362 0 0 0 migratable
agetty 363 0 0 0 migratable
agetty 364 0 0 0 migratable
agetty 365 0 0 0 migratable
agetty 366 0 0 0 migratable
agetty 367 0 0 0 migratable
omdiscd 398 0 0 0 migratable
mosstatd 476 0 0 0 migratable
sshd 2778 0 0 0 migratable
bash 2780 0 0 0 migratable
ompsinfo 2852 0 0 0 migratable
|
Утилита mosmon предназначена для визуального отображения текущей загрузки кластера. Она скомпилирована на основе библиотеки ncurses, поэтому текстовой консоли вполне будет достаточно для ее запуска.
Для запуска заданий предназначена утилита mosrun. С ее помощью можно указать, к какому типу процессов принадлежит наше задание. Либо это CPU-intensive, т.е. задание, использующее процессорные ресурсы, либо I/O-intensive – задание, где основной упор делается на процесс ввода/вывода.
Usage: mosrun [-{h|OpenMosix_ID|-jID1-ID2[,ID3-ID4]...} [-F] ] -{l|L|k}
[-{c|i|n|s|f | ([-d dec] [-t tt])} [-{e|E}] [-{r|R}] ]
[-z] prog [args]..
|
Утилита showmap выводит список узлов кластера.
root@node0:~# showmap
My Node-Id: 0x023d
Base Node-Id Address Count
------------ ---------------- -----
0x023d 192.168.2.61 1
0x023f 192.168.2.63 1
|
Сервис, отвечающий за динамическое определение узлов кластера. В частности, когда на узле используется несколько сетевых интерфейсов, следует явно указать, по какому из них проводить идентификацию узлов.
omdiscd-i eth0
Выводы
Как и в любом аспекте нашей жизни можно найти минусы и плюсы, так и решения на базе OpenMosix-кластера содержат некие «узкие» точки. В частности, оцифровка звуковых файлов из формата .wav в формат .mp3 показала, что общее время процесса обработки на кластере превысило аналогичное время на одной ПЭВМ. Повлияла на столь странный результат низкоскоростная среда передачи данных – 100-мегабитная сеть. В целом применение OpenMosix-кластеров целесообразно в тех случаях, когда требуется использовать задачи с высокими интенсивными вычислительными запросами, например сборка программного обеспечения (как показано в этой статье), симуляторы погоды, обработка геофизических данных, математических моделей и в других подобных ситуациях.
Ссылки, литература:
- Борисов А. «Стальной глаз на страже жизни». HA-кластер LifeKeeper компании SteelEye. – Журнал «Системный администратор», №7, 2004 г. – 43-49 с (http://www.samag.ru/cgi-bin/go.pl?q=articles;n=07.2004;a=10).
- http://www.mplayerhq.hu.
- http://openmosix.sourceforge.net.
- http://www-128.ibm.com/developerworks/eserver/articles/openmosix.html.
- http://howto.x-tend.be/openMosixWiki.
- http://howto.x-tend.be/openMosix-LCA2005.
- http://tab.snarc.org/article/om_internals.xhtml.
- http://www.samag.com/documents/s=9658/sam0505a/0505a.html.