Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лаб-02.doc
Скачиваний:
3
Добавлен:
14.08.2019
Размер:
88.58 Кб
Скачать

Кафедра СКС

Лабораторная работа №2

ДонГТУ

СКС-08-2

Знакомство с MPI. Функции для двухточечного обмена сообщениями (блокирующие).

Белик Александр

Цель лабораторной работы

Получить основы многопоточного программирования с использованием библиотеки MPI.

Научится использовать механизмы передачи сообщений типа точка-точка с использованием различных функций.

 

Порядок выполнения работы

1.     В приведенных заданиях дописать и исправить приведенные фрагменты кода.

2.     Произвести компиляцию и запуск программ (./zadanie).

3.     получить индивидуальное задание для защиты.

 

Содержание отчета

1.    Группа ФИО.

2.    Тема лабораторной работы.

3.    Цель лабораторной работы.

4.    Содержание файлов с кодом програм.

Теория.

Трансляция MPI-программ

Утилиты трансляции и сборки находятся в каталоге /user/locla/mpich1/bin. Его следует включить в путь поиска исполняемых файлов.

Для трансляции и компоновки программ на языке C++ используется команда mpiCC, для трансляции программ на языке C— команда mpicc.

Информацию о ключах можно найти на справочных страницах MPICH (для их просмотра применяют команду man). Пример применения команды:

mpicc -o test1 test1.c

 

Для компиляции программ желательно использовать makefile

Пример содержания makefile:

 

CC=/usr/local/mpich1/bin/mpicc NAME=svv all:$(NAME) clean $(NAME): $(NAME).o         $(CC) $(NAME).c -lm -o $@ $(NAME)o: $(NAME).c         $(CC) -c $(NAME).c clean:         rm ./*.o

 

Пояснения:

строка для определения макроса компиляции программыCC=/usr/local/mpich1/bin/mpicc

строка где определяется имя программ и исходного файла NAME=svv

 

Выполнение mpi-программ

Для выполнения MPI-программ в MPICH используется загрузчик приложений mpirun. Он запускает указанное количество копий программы. Команда запуска:

mpiexec -np n [ключи MPI] программа [ключи и аргументы программы]

где п — число запускаемых процессов. Некоторые ключи MPI (они указываются перед именем исполняемого файла программы) приведены в таблице:

 

Ключ

Описание

-h

Краткая информация о команде

-machinefile name_файл

Для     запуска     программы     использовать компьютеров из указанного файла

 Для запуска программ можно использовать специальный скрипт например такого содержимого:

#!/bin/sh mpiexec -machinefile ./machines -np 3 ./svv > ../res

В нашем случае скрипт это просто текстовый файл (обычно для него используется расширение .sh) для которого указаны права не исполнение (chmod 7?? name.sh).

В этом примере три запускаемых экземпляра программы.

Простейшие функции mpi

       MPI_Init(int *argc, char ** argv)

Производит инициализацию MPI. Должна быть первой из вызываемых MPI функций. В нее передаются адреса аргументов функции main().

Командой mpirun один и тот же исполняемый файл (точнее, файлы с одним и тем же именем в рабочей директории на разных узлах) запускаются на исполнение. Поскольку SPMD распараллеливание предполагает разделение работы между одновременно работающими устройствами, эти устройства должны выполнять различные части программы. Нет никакого смысла в том, что все устройства выполнят абсолютно одни и те же действия.

Когда исполняемый файл запускается, соответствующий процесс должен получить какой-то отличительный признак, по которому этот процесс будет идентифицироваться. Таким признаком является ранг(номер) процесса. Ранг служит двум целям: процесс определяет свою часть работы, зная свой ранг, и при обмене сообщениями между двумя процессами, эти процессам необходимо знать ранги друг друга.

Кроме того, почти всегда необходимо знать общее число процессов программы. Для этого используется следующая пара функций:

MPI_Comm_rank(MPI_Comm comm, int* rank)

записывает по адресу rank ранг вызвавшего процесса в коммуникаторе comm В разных коммуникаторах один и тот же процесс может иметь различные ранги.

MPI_Comm_size(MPI_Comm comm, int* size)

записывает по адресу size общее число процессов в коммуникаторе comm.

MPI_Finalize()

Производит корректное завершение среды MPI. После вызова этой функции нельзя вызывать другие функции MPI. Эта функция обязательно должна вызываться до завершения программы.

Первая программа "Hello, mpi world!"

#include "mpi.h" #include <stdio.h> int main(int argc, char ** argv) {         int i, myrank,ranksize;         MPI_Status status;                  MPI_Init (&argc, &argv); /* initialize MPI-system */         MPI_Comm_rank (MPI_COMM_WORLD, &myrank); /* my place in MPI system */         MPI_Comm_size (MPI_COMM_WORLD, &ranksize); /* size of MPI system */           if (myrank == 0) /* I am the MASTER */         {                 printf("Master %d of %d work\n", myrank,ranksize);         }         else             {                  printf ("Worker %d of %d  work \n", myrank,ranksize);         }          MPI_Finalize (); } // end MAIN function // end of hello.c program

 

Двухточечные блокирующие обмены

Участниками двухточечного обмена являются два процесса: процесс-отправитель и процесс-получатель. Блокирующие операции двухточечного обмена приостанавливают выполнение вызывающего процесса. Он переходит в состояние ожидания завершения передачи данных. Блокировка гарантирует выполнение действий в заданном порядке, обеспечивая предсказуемость поведения программы. С другой стороны, она создает условия для возникновения тупиковых ситуаций, когда оба процесса-участника обмена блокируются одновременно.

 Функция MPI_Send.

int MPI_Send(void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm)

Отправляет данные, находящиеся по адресу buf в количестве count типаdatatype процессу с рангом dest с тэгом сообщения tag. Посылка сообщения происходит в коммуникаторе comm. Параметр tag необходим для того, чтобы отличать сообщения от одного и того же процесса, либо сообщения от разных процессов, если принимающий процесс ожидает сообщение от любого процесса.

Функция MPI_Recv.

int MPI_Recv(void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Status *status)

Принимает данные и записывает их по адресу buf в количестве count типаdatatype от процесса с рангом dest с тэгом сообщения tag. Прием сообщения происходит в коммуникаторе comm. По адресу status записывается информация о прошедшем приеме сообщения.

typedef struct MPI_Status{

    int count;           //Сколько байт получено

    int cancelled; //Была ли передача прервана

    int MPI_SOURCE;      //От кого сообщение

    int MPI_TAG;   //Тэг сообщения

    int MPI_ERROR; //Код ошибки

} MPI_Status;

В качестве параметров source и tag могут быть переданы константыMPI_ANY_SOURCE и MPI_ANY_TAG соответственно.Значение MPI_ANY_SOURCEпараметра dest означает прием сообщения от любого процесса коммуникатора, а значениеMPI_ANY_TAG означает прием сообщения с произвольным тэгом.

Функции MPI_Send и MPI_Recv являются блокирующими. Возвращение изMPI_Send не происходит до тех пор, пока данные сообщения не будут скопированы во внутренний буфер MPI. MPI_Recv возвращает управление только после того, как сообщение было принято.

Пример

 1 #include <mpi.h>  2 #include <stdio.h>  3 int main (int argc, char *argv[]) {  4     int ProcNum, ProcRank, tmp, i;  5     MPI_Status status;  6     MPI_Init ( &argc, &argv );  7     MPI_Comm_size (MPI_COMM_WORLD, &ProcNum);  8     MPI_Comm_rank (MPI_COMM_WORLD, &ProcRank);  9     if(ProcRank == 0){ 10         printf("Hello world from process %i \n", ProcRank); 11         for(i = 1; i < ProcNum; i++){ 12            MPI_Recv(&tmp,1,MPI_INT,MPI_ANY_SOURCE,0,MPI_COMM_WORLD, &status); 13             printf("Hello world from process %i \n", tmp); 14         } 15     }else{ 16         MPI_Send(&ProcRank,1,MPI_INT,0,0,MPI_COMM_WORLD); 17     } 18     MPI_Finalize(); 19     return 0; 20 } 

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]