Прочитал статью «Основы MPI для «чайников»» и понял, что статья новичка способна отпугнуть.
Первое время не было единого стандарта (API) для параллельных вычислений и программистам приходилось писать для каждого кластера архитектурно-специфический код. Но, как известно, программисты люди рациональные и быстро было решено организовать стандарты (самые известные — MPI, OpenMP).
MPI — Message Passing Interface. Это специфический API, который реализуют производители кластеров для того, чтобы можно было легко переносить программы с кластера на кластер не изменяя ни байта исходного кода(!).
Параллельная программа должна эффективно использовать вычислительные мощности и коммуникационную среду. В MPI вся работа по распределению нагрузки на узлы и сеть ложатся на программиста и для максимальной производительности необходимо знать особенности конкретного кластера. MPI очень элегантно решает вопрос топологии сети: имеются понятия коммуникаторов — группы процессов, которые можно пронумеровать в соответствии с топологией сети (для этого используется функция MPI_Cart_create, которая позволяет задать любую топологию от решётки до гиперкуба).
Некоторые примеры в учебных пособиях весьма синтетические — в них считается какой-нибудь ряд в пределах стандартного типа (например, double), что на практике вычисляется за время много меньшее того, которое тратится на инициализацию и передачу чего-либо по сети (вычисление числа pi в double на двух компьютерах с Gigabit Ethernet примерно в два раза медленнее вычисления на одном компьютере). Однако, MPI позволяет использовать многоядерные процессоры (что почему-то многие забывают), а между ядрами скорость передачи совершенно другого порядка, поэтому всегда нужно знать архитектуру и топологию системы.
Про теорию можно много писать, но лучше постигать теорию соразмерно с практикой.
Для начала установим какую-нибудь реализацию MPI на свой компьютер. Одной из самых распространённых реализаций MPI является MPICH (MPI Chameleon).
В убунте устанавливается в одну строчку:
Напишем простенькую программку, которая ничего полезного не делает:
Скомпилируем эту программку:
Попробуем запустить:
И (если еще не настроили демон mpd) получим сообщение о том, что демон mpd не запущен.
При попытке запустить mpd будет сказано об отсутствии настроек (почему, собственно, не запускается демон)
Секретное слово нужно только для подключения узлов. Если мы будем подключать ещё компьютеры, то надо будет и на них ставить MPICH и надо будет занести узел в список узлов, а также не будет лишним настроить подключение по ssh с использованием ключей (для общения с узлами).
Если всё сделано правильно, то получим примерно такой вывод:
MPI_Init — обязательна для вызова, так как выполняет инициализацию библиотеки MPI.
MPI_COMM_WORLD — идентификатор глобального коммуникатора, содержащего все процессы.
MPI_Comm_rank — возвращает идентификатор (номер, ранг) процесса в рамках заданного коммуникатора.
Почему выводим на экран только при ранге, равном 0? Просто этот процесс как раз соответствует по умолчанию тому, который имеет доступ к консоли того терминала, с которого производился запуск. Мы можем использовать и любой другой, но так просто удобнее.
Можно написать параллельную программу не имея почти никаких знаний о параллельном программировании, но написание эффективных программ является трудоёмким процессом выбора алгоритма и его реализации, подгонки под систему и так далее. Но если начать писать простенькие программки и при этом читать спецификации и литературу о вычислительных системах (об их архитектуре, коммуникационных средах и прочем), то со временем, %username%, будешь способен подчинить себе даже такие страшные машины как те, которые представлены в списке топ-500
Теория
Начнем с начала
Первое время не было единого стандарта (API) для параллельных вычислений и программистам приходилось писать для каждого кластера архитектурно-специфический код. Но, как известно, программисты люди рациональные и быстро было решено организовать стандарты (самые известные — MPI, OpenMP).
MPI — Message Passing Interface. Это специфический API, который реализуют производители кластеров для того, чтобы можно было легко переносить программы с кластера на кластер не изменяя ни байта исходного кода(!).
Параллельная программа должна эффективно использовать вычислительные мощности и коммуникационную среду. В MPI вся работа по распределению нагрузки на узлы и сеть ложатся на программиста и для максимальной производительности необходимо знать особенности конкретного кластера. MPI очень элегантно решает вопрос топологии сети: имеются понятия коммуникаторов — группы процессов, которые можно пронумеровать в соответствии с топологией сети (для этого используется функция MPI_Cart_create, которая позволяет задать любую топологию от решётки до гиперкуба).
Целесообразность распараллеливания
Некоторые примеры в учебных пособиях весьма синтетические — в них считается какой-нибудь ряд в пределах стандартного типа (например, double), что на практике вычисляется за время много меньшее того, которое тратится на инициализацию и передачу чего-либо по сети (вычисление числа pi в double на двух компьютерах с Gigabit Ethernet примерно в два раза медленнее вычисления на одном компьютере). Однако, MPI позволяет использовать многоядерные процессоры (что почему-то многие забывают), а между ядрами скорость передачи совершенно другого порядка, поэтому всегда нужно знать архитектуру и топологию системы.
Практика
Про теорию можно много писать, но лучше постигать теорию соразмерно с практикой.
Для начала установим какую-нибудь реализацию MPI на свой компьютер. Одной из самых распространённых реализаций MPI является MPICH (MPI Chameleon).
Установка
В убунте устанавливается в одну строчку:
sudo apt-get install mpich2
Напишем простенькую программку, которая ничего полезного не делает:
#include <stdio.h>
#include <mpi.h>
int main (int argc, char* argv[])
{
int errCode;
if ((errCode = MPI_Init(&argc, &argv)) != 0)
{
return errCode;
}
int myRank;
MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
if (myRank == 0)
{
printf("It works!\n");
}
MPI_Finalize();
return 0;
}
* This source code was highlighted with Source Code Highlighter.
Скомпилируем эту программку:
mpicc -o test.bin ./test.c
Попробуем запустить:
mpirun ./test.bin
И (если еще не настроили демон mpd) получим сообщение о том, что демон mpd не запущен.
mpiexec: cannot connect to local mpd (/tmp/mpd2.console_valery); possible causes:
1. no mpd is running on this host
2. an mpd is running but was started without a "console" (-n option)
In case 1, you can start an mpd on this host with:
mpd &
and you will be able to run jobs just on this host.
For more details on starting mpds on a set of hosts, see
the MPICH2 Installation Guide.
При попытке запустить mpd будет сказано об отсутствии настроек (почему, собственно, не запускается демон)
configuration file /home/valery/.mpd.conf not found
A file named .mpd.conf file must be present in the user's home
directory (/etc/mpd.conf if root) with read and write access
only for the user, and must contain at least a line with:
MPD_SECRETWORD=<secretword>
One way to safely create this file is to do the following:
cd $HOME
touch .mpd.conf
chmod 600 .mpd.conf
and then use an editor to insert a line like
MPD_SECRETWORD=mr45-j9z
into the file. (Of course use some other secret word than mr45-j9z.)
Секретное слово нужно только для подключения узлов. Если мы будем подключать ещё компьютеры, то надо будет и на них ставить MPICH и надо будет занести узел в список узлов, а также не будет лишним настроить подключение по ssh с использованием ключей (для общения с узлами).
Если всё сделано правильно, то получим примерно такой вывод:
$ mpirun ./test.bin
It works!
MPI_Init — обязательна для вызова, так как выполняет инициализацию библиотеки MPI.
MPI_COMM_WORLD — идентификатор глобального коммуникатора, содержащего все процессы.
MPI_Comm_rank — возвращает идентификатор (номер, ранг) процесса в рамках заданного коммуникатора.
Почему выводим на экран только при ранге, равном 0? Просто этот процесс как раз соответствует по умолчанию тому, который имеет доступ к консоли того терминала, с которого производился запуск. Мы можем использовать и любой другой, но так просто удобнее.
Вместо вывода
Можно написать параллельную программу не имея почти никаких знаний о параллельном программировании, но написание эффективных программ является трудоёмким процессом выбора алгоритма и его реализации, подгонки под систему и так далее. Но если начать писать простенькие программки и при этом читать спецификации и литературу о вычислительных системах (об их архитектуре, коммуникационных средах и прочем), то со временем, %username%, будешь способен подчинить себе даже такие страшные машины как те, которые представлены в списке топ-500