Введение.
Для чего все это? В этой серии статей мы поговорим о параллельное программирование .
- Часть 1. MPI - Введение и первая программа.
- Часть 2. MPI - Учимся контролировать процессы.
- Часть 3. MPI. Как взаимодействуют процессы? Сообщения «точка-точка».
Сражаться.
Введение Довольно часто сложнейшие алгоритмы требуют огромного количества вычислительных ресурсов в реальных задачах, когда программист пишет код в стандартном понимании.
процедурный или Объектно-ориентированное программирование (ООП) , то для особо требовательных алгоритмических задач, работающих с большим объемом данных и требующих минимизации времени выполнения задачи, необходимо провести оптимизацию.
В основном используется 2 типа оптимизация или их смесь: векторизация И распараллеливание расчеты.
Насколько они разные? Вычисления выполняются на процессоре, процессор использует специальные «хранилища» данных, называемые регистрами.
Регистры процессора напрямую связаны с логическими элементами и требуют гораздо меньше времени для выполнения операций над данными, чем данные из оперативной памяти и тем более на жестком диске, поскольку для последнего передача данных занимает достаточно большую часть времени.
Также в процессорах есть область памяти, называемая Кэш; в нем хранятся те значения, которые сейчас участвуют в расчетах или будут участвовать в них в ближайшем будущем, то есть самые важные данные.
Задача оптимизации алгоритма сводится к правильному построению последовательности операций и оптимальному размещению данных в Кэше, минимизации количества возможных пересылок данных из памяти.
Так в чем же разница между векторизацией и параллельными вычислениями? Векторизация – позволяет выполнять операции над заданными целочисленными векторами.
Например для С++ : если мы используем AVX инструкции, то у нас есть 256-битные векторы, в которые мы можем поместить элементы float32. Оказывается, мы можем собрать 2 вектора из (256/32) = 8 значений float32. Затем выполните над ними одну операцию за такт, хотя если бы мы этого не сделали, то вполне возможно, что подобные вычисления завершились бы за 8 операций, а то и больше, если принять во внимание вычисление индексов конкретных элементов.
Однако есть одна проблема: компиляторы сейчас достаточно умны и неплохо справляются с оптимизацией такого рода самостоятельно, поэтому большая часть усилий уходит на правильную организацию данных.
Распараллеливание позволяет использовать не только вычислительные возможности одного процессора, но и множества процессоров, в том числе в системах с распределенной памятью и т. д. В таких системах, как правило, вычислительных мощностей гораздо больше, но нужно уметь управлять все это и правильно организовать параллельную работу над конкретными потоками.
Главная часть
В настоящее время существует множество технологий, позволяющих легко организовать параллельные вычисления, одной из самых популярных на данный момент является ИМБ .MPI — интерфейс передачи сообщений (интерфейс передачи сообщений).
Название носит семантический характер, что будет наглядно выражено в последующих статьях, а пока вам нужно знать только основной способ взаимодействия параллельных процессов в такой системе — передачу сообщений между ними.
Это означает, что наши потоки будут взаимодействовать друг с другом при обработке данных, но как — это вопрос реализации.
Существует два основных стиля создания параллельных программ: MIMD (множественные инструкции, несколько данных - Множественный поток инструкций, Множественный поток данных) и SPMD (одна программа, несколько данных) - Одна программа, несколько потоков данных).
Если сильно упростить, первая модель берет разные исходные коды программы и запускает их в разных потоках, а вторая модель берет один исходный код и запускает его во всех выделенных потоках.
Программы, написанные в соответствии со стилем МИМД довольно сложны в отладке из-за своей архитектуры, поэтому чаще используется модель СПМД .
В ИМБ можно использовать и то, и другое, но по стандарту (в зависимости от реализации, конечно) используется модель СПМД .
Монтаж
Поскольку ИМБ — библиотека, то ее нужно связать с компилятором.Каждая среда делает это по-своему и в зависимости от компилятора.
Лично я работал на Убунту Баджи 20.04 ЛТС и я вам расскажу инструкцию по установке именно для него.
В командной строке введите следующие команды:
Первая команда обновляет менеджер пакетов, вторая устанавливает компилятор.[user-name]$ sudo apt-get update [user-name]$ sudo apt-get install gcc [user-name]$ sudo apt-get install mpich
GCC , если его нет в системе, третья программа устанавливает компилятор, через который мы собственно и будем работать C\C++&MPI код.
Первые шаги.
программа MPI — это набор параллельных взаимодействующих процессов, каждый из которых работает в своей выделенной области памяти.
По сути это Н независимые программы, которые общаются друг с другом во время работы.
В ИМБ большинство типов данных уже переопределены и начинаются с сокращения MPI_[Имя] , это станет ясно позже.
Чтобы понять, что происходит дальше, нужно дать определение нескольким терминам: Коммуникатор — объект, через который общается определенная группа сгенерированных процессов.
В C++/C это тип данных MPI_Comm .
Коммуникатор может объединять несколько процессов путем передачи сообщений между ними, при этом коммуникаторов может быть несколько; образуемые ими группы могут либо не пересекаться, либо пересекаться частично.
При запуске программы все процессы работают под единым коммуникатором с именем MPI_COMM_МИР .
Помимо него есть еще коммуникаторы MPI_COMM_SELF , MPI_COMM_NULL , которые содержат только текущий процесс и ни одного процесса соответственно.
Сообщение - набор данных некоторого типа, который передается во время процесса коммуникации.
Каждое сообщение имеет несколько атрибутов, таких как номер процесса отправки, номер процесса получателя, идентификатор сообщения, коммуникатор и тег.
Тег публикации - неотрицательное целое число от 0 до 32767 (В зависимости от реализации.
Максимально возможное значение тега хранится в константе MPI_TAG_UB ).
В этом примере мы не будем использовать передачу данных, а лишь ознакомимся с основами процедур MPI. Чтобы иметь возможность использовать большинство процедур MPI, любая программа должна иметь следующие процедуры: int MPI_Init(int *argc, char ***argv);
int MPI_Finalize(void);
Первая процедура предназначена для инициализации параллельной части программы; все остальные процедуры, за исключением некоторых специальных, можно вызвать только после вызова процедуры MPI_Init, Эта функция принимает аргументы командной строки, с помощью которых система может передавать процессу некоторые параметры запуска.
Вторая процедура предназначена для завершения параллельной части программы.
Для того, чтобы проверить работу программы, реализуем самую примитивную программу в С++ с использованием ИМБ .
#include <stdio.h>
#include "mpi.h"
int main(int argc, char **argv)
{
printf("Before MPI_INIT\n");
MPI_Init(&argc, &argv);
printf("Parallel sect\n");
MPI_Finalize();
printf("After MPI_FINALIZE\n");
return 0;
}
Для запуска этой программы сохраняем нашу запись в файл с любым именем и расширением *.
cpp , после чего выполняем в консоли следующие действия (В моем случае код находится в файле main.cpp ): [user-name]$ mpic++ main.cpp -o main
[user-name]$ mpiexec -n 2 .
/main
Первая команда скомпилирует нашу программу MPI, а вторая позволит нам запустить ее.
Обратите внимание, что мы передаем параметры -n 2 во второй строке.
Зачем это нужно? Таким образом мы сообщаем исполнителю, что нужно запустить 2 параллельных процесса.
Программа просто напечатает несколько строк в зависимости от указанного вами количества процессов.
Не пугайтесь, если строки «До…» и "После.
" будет отображаться более одного раза, в зависимости от реализации ИМБ программа может работать параллельный и внешние процедуры Инициализировать-Финализировать.
Нижняя граница
В этой небольшой статье на примере простейшей программы мы научились запускать C++-файлы с MPI-кодом и разобрались, что это за зверь ИМБ и с чем его едят. В дальнейших уроках мы рассмотрим более полезные программы и, наконец, перейдем к общению между процессами.Теги: #Алгоритмы #C++ #оптимизация #Параллельное программирование #mpi #многопоточные приложения