Автор работы: Пользователь скрыл имя, 05 Июня 2013 в 22:25, курсовая работа
В настоящее время проводится много исследований в области языков и сред параллельного программирования, целью которых является содействие параллельному программированию путем обеспечения поддержки на должном уровне абстракции. Однако, много эффективных технологий доступно уже сейчас.
Введение 4
1 Общие представления о параллельном программировании 6
2 Архитектура параллельных компьютеров 8
2.1 Развитие архитектуры компьютера 8
2.2 Организация памяти параллельных компьютеров 10
2.3 Сети межсоединений 15
2.3.1 Свойства сетей межсоединений. Статические сети межсоединений 16
2.3.2 Динамические сети межсоединений 19
3 Введение в программирование с использованием передачи сообщений 22
3.1 Введение в MPI 22
3.1.1 MPI-коммуникация типа «точка-точка» 25
3.1.2 Тупиковые ситуации при коммуникациях типа «точка-точка» 30
3.1.3 Неблокирующие операции и режимы коммуникации 33
3.1.4 Коммуникационный режим 35
3.2 Групповые коммуникационные операции 36
3.3 Группы процессов и коммуникаторы 41
3.3.1 Группы процессов в MPI 41
3.3.2 Топологии процессов 45
3.3.3 Временные и прерывающие процессы 49
4 Введение в потоковое программирование в OpenMP 50
4.1 Проблемы поточной обработки цикла 52
4.2 Условия гонок 52
4.3 Управление общими и приватными данными 53
4.4 Планирование и разбиение циклов 55
4.5 Библиотечные функции ОреnМР 57
4.6 Отладка 58
4.7 Производительность 59
4.8 Основные моменты 61
5 Протокол сеансового уровня SSH 63
6 Удаленный вход на кластер 66
7 Операционная система Linux 68
7.1 Интерфейс ОС Linux 68
7.2 Некоторые команды Linux 68
8 Компилирование последовательных программ (Fortran/C/C++) 71
9 Основные команды 72
10 Работа с кластером 74
Список использованных источников информации 83
MPI_Allgather (sbuf, 100, MPI_INT, rbuf, 100, MPI_INT, comm);
MPI_Allgatherv() является функцией, являющаяся векторным обобщением функции MPI_Allgather() (по аналогии с обобщением функции MPI_Gather()).
Операция мультинакопления (Multi-accumulation Operation)
При выполнении операции мультинакопления каждый процесс выполняет свою операцию накопления, для которой каждый процесс предоставляет свой блок данных. Такая операция в MPI имеет очень ограниченную функциональность: для всех операций накопления, выполняемых каждым процессом самостоятельно, каждый процесс предоставляет один и тот же блок данных.
На рисунке 4 показана работа операции мультинакопления.
Рисунок 4 – Операция мультинакопления
Каждый процесс аккумулирует один и тот же блок данных. Соответствующая данной операции MPI-функция имеет вид:
int MPI_Allreduce (void *sendbuf,
void *recvbuf,
int count,
MPI_Datatype type,
MPI_Op op,
MPI_Comm comm)
Общий обмен (Total Exchange)
Для осуществления общего обмена в MPI имеется функция
int MPI_Alltoall (void *sendbuf,
int sendcount,
MPI_Datatype sendtype,
void *recvbuf,
int recvcount,
MPI_Datatype recvtype,
MPI_Comm comm)
Здесь sendbuf – буфер передачи, в который каждый процесс сохраняет блок данных типа sendtype, состоящий из sendcount элементов и предназначаемый для всех процессов (включая себя). Блоки данных, получаемые от других процессов, сохраняются в буфер приема recvbuf. Полученные блоки сохраняются в порядке рангов передающих процессов. Для p процессов результат общего обмена также может быть достигнут, если каждый из p процессов выполнит p операций передачи
MPI_Send (sendbuf+i*sendcount*extent, sendcount, sendtype,i, my_rank, comm)
и p операций приема
MPI_Recv (recvbuf+i*recvcount*extent, recvcount, recvtype,
i, i, comm, &status),
где i – ранг процесса, .
MPI_Alltoallv() – векторная версия функции MPI_Alltoall().
При программировании групповых коммуникаций следует аккуратно применять соответствующие операции во избежание тупиковых ситуаций.
MPI позволяет строить подмножества процессов путем определения групп и коммуникаторов и осуществлять над ними различные операции (например, объединение или пересечение групп, сравнение групп). Эти операции позволяют строить сложные коммуникационные области, способствующие параллельным процессам эффективно обмениваться данными. Также в MPI имеются средства задания различных виртуальных топологий, обеспечивающие удобный механизм наименования процессов, связанных коммуникатором и являющиеся мощным средством отображения процессов на оборудование системы.
Группа процессов – упорядоченное множество процессов прикладной программы. Каждый процесс группы получает уникальный номер, также называемый рангом. Ранги процессов группы всегда начинаются с нуля и далее последовательно увеличиваются вплоть до числа процессов минус один. Процесс может быть членом нескольких групп, и ранг этого процесса в различных группах может отличаться. Для программиста группа процессов – объект типа MPI_Group, доступ к которому может быть получен с использованием дескриптора, который может быть индексом или ссылкой.
В предыдущих разделах мы всегда использовали предопределенный коммуникатор MPI_COMM_WORLD для коммуникаций. Этот коммуникатор включает в себя все процессы, принимающие участие в выполнении параллельной программы. MPI предоставляет несколько операций для построения дополнительных групп процессов и коммуникаторов. Все эти операции основаны на существующих группах и коммуникаторах. Предопределенный коммуникатор MPI_COMM_WORLD и соответствующая группа обычно используются в качестве начального задания. Путем вызова функции
int MPI_Comm_group (MPI_Comm comm, MPI_Group *group)
где comm – данный коммуникатор, можно получить указатель group на ранее определенный объект типа MPI_Group. Предопределенной является группа MPI_GROUP_EMPTY, обозначающая пустую группу процессов.
Рассмотрим операции над группами процессов.
Объединение существующих групп group1 и group2
int MPI_Group_union (MPI_Group group1,
MPI_Group group2,
MPI_Group *new_group)
Ранги в новой группе new_group устанавливаются так, что процессы группы group1 сохраняют свои ранги. Процессы группы group2, не находящиеся в группе group1, получают ранги, начиная с ранга последнего процесса группы group1 плюс один.
Пересечение двух групп
int MPI_Group_intersection (MPI_Group group1,
MPI_Group group2,
MPI_Group *new_group)
Процессы в группе new_group получают последовательные ранги, начиная с нуля.
Разность множеств двух групп
int MPI_Group_difference (MPI_Group group1,
MPI_Group group2,
MPI_Group *new_group)
Подгруппа new_group существующей группы group может быть получена путем вызова функции
int MPI_Group_incl (MPI_Group group,
int p,
int *ranks,
MPI_Group *new_group)
Здесь ranks – целочисленный массив, состоящий из p элементов. Ранги процессов группы-результата – от 0 до p-1.
Из данной группы можно удалить процессы путем вызова функции
int MPI_Group_excl (MPI_Group group,
int p,
int *ranks,
MPI_Group *new_group)
Этот вызов генерирует новую группу new_group, полученную из группы group путем удаления процессов с рангами ranks[0],…,ranks[p-1].
Доступ к структурам данных типа MPI_Group не может быть напрямую получен программистом. Но MPI предоставляет операции, позволяющие получить информацию о группах процессов. Размер size группы процессов можно узнать путем вызова функции
int MPI_Group_size (MPI_Group group, int *size)
Ранг rank вызывающего процесса группы может быть получен с помощью функции
int MPI_Group_rank (MPI_Group group, int *rank)
Функция
int MPI_Group_compare (MPI_Group group1, MPI_Group group2, int *res)
может быть использована для того, чтобы проверить, описывают ли два представления группы group1 и group2 одну и ту же группу. Если обе эти группы содержат одни и те же процессы в одном и том же порядке, то возвращается параметр res = MPI_IDENT. res = MPI_SIMILAR возвращается в случае, если обе группы содержат одни и те же процессы, но порядок процессов в группах отличается. res = MPI_UNEQUAL означает, что группы содержат различные процессы.
Функция
int MPI_Group_free (MPI_Group *group)
может быть использована с целью удаления группы. Дескриптор группы после этого установится в MPI_GROUP_NULL.
Рассмотрим операции над коммуникаторами.
В MPI имеется два типа коммуникаторов:
Новый интракоммуникатор данной группы процессов может быть сгенерирован путем вызова функции
int MPI_Comm_create (MPI_Comm comm,
MPI_Group group,
MPI_Comm *new_comm)
где comm определяет существующий коммуникатор. Параметр group должен определять группу процессов, являющуюся подмножеством группы процессов, ассоциированной с comm. Для корректного исполнения необходимо, чтобы все процессы коммуникатора comm вызывали MPI_Comm_create(), и чтобы все эти процессы имели одинаковые параметры group. В результате вызова функции каждый вызывающий процесс-член группы group получает в параметре new_comm указатель на новый коммуникатор.
MPI также предоставляет функции, позволяющие получить информацию о коммуникаторах. Размер size группы процессов, ассоциированной с коммуникатором comm, можно узнать путем вызова функции
int MPI_Comm_size (MPI_Comm comm, int *size)
Ранг rank процесса-члена группы, связанной с коммуникатором comm может быть получен путем вызова функции
int MPI_Comm_rank (MPI_Comm comm, int *rank)
Два коммуникатора можно сравнить:
int MPI_Comm_compare (MPI_Comm comm1, MPI_Comm comm2, int *res)
Результат сравнения возвращается в параметре res:
Для конструирования коммуникаторов MPI предоставляет операции копирования, удаления и разделения коммуникаторов на части:
int MPI_Comm_dup (MPI_Comm comm, MPI_Comm *new comm)
int MPI_Comm_free (MPI_Comm *comm)
int MPI_Comm_split ( MPI_Comm comm,
int color,
int key,
MPI_Comm *new_comm)
Результатом последней функции является разделение группы процессов, ассоциированной с коммутатором comm, на непересекающиеся подгруппы. Количество подгрупп определяется числом различных значений параметра color. Каждая подгруппа содержит все процессы с одинаковым значением color. В пределах каждой подгруппы процессы ранжируются в порядке, определенном параметром key. Если два процесса в подгруппе определяют одинаковые значения key, то используется порядок, имевший место в исходной группе. Если процесс коммуникатора comm определяет color = MPI_UNDEFINED, то он не станет членом ни одной из создаваемых групп. Каждый процесс коммуникатора comm получает указатель new_comm на коммуникатор подгруппы, содержащей процесс. Если определено color = MPI_UNDEFINED, то в качестве new_comm будет возвращено MPI_COMM_NULL.
Каждый процесс из некоторой группы процессов имеет уникальный ранг в пределах этой группы, который может быть использован для коммуникации с данным процессом. Однако часто полезно иметь альтернативное представление процесса и доступ к нему; это полезно тогда, когда алгоритм выполняет вычисления над двух- или трехмерной решеткой, узлы которой назначены различным процессам, и процессы обмениваются данными с соседними процессами в каждом измерении путем коммуникаций. MPI поддерживает логическое распределение процессов путем определения виртуальных топологий для интракоммуникаторов.
Виртуальная декартова структура
решетки для произвольного
int MPI_Cart_create (MPI_Comm comm,
int ndims,
int *dims,
int *periods,
int reorder,
MPI_Comm *new_comm)
Здесь comm – исходный коммутатор безо всякой топологии, ndims определяет количество измерений генерируемой решетки, dims – целочисленный массив размера ndims такой, что dims[i] – число процессов в измерении i. Логический массив periods размера ndims для каждого измерения определяет, является в данном измерении ли решетка периодической (1 или true) или нет (0 или false). Значение reorder = false соответствует тому, что процессы в новом коммуникаторе new_comm будут иметь такие же ранги, как и в коммуникаторе comm. Если reorder = true, то исполняющей системе разрешается изменить порядок процессов, например, с тем, чтобы достичь лучшего отображения топологии процессов на физическую сеть параллельной машины.
Пример. Рассмотрим коммуникатор с 12 процессами. Пусть ndims=2, dims[0]=3, dims[1]=4, periods[0]=periods[1]=0, reorder=0, тогда вызов
MPI_Cart_create (comm, ndims, dims, periods, reorder, &new_comm)
сгенерирует виртуальную решетку 3x4 со следующими рангами групп и координатами:
0 (0,0) |
1 (0,1) |
2 (0,2) |
3 (0,3) |
4 (1,0) |
5 (1,1) |
6 (1,2) |
7 (1,3) |
8 (2,0) |
9 (2,1) |
10 (2,2) |
11 (2,3) |
Декартовы координаты представлены в форме (строка, столбец). #
Чтобы помочь программисту выбрать сбалансированное распределение процессов для различных измерений, MPI предоставляет функцию
int MPI_Dims_create (int nnodes, int ndims, int *dims)
где ndims – число измерений решетки, nnodes – общее количество доступных процессов. Параметр dims – целочисленный массив размера ndims. Размерности устанавливаются так, чтобы быть близко друг к другу насколько возможно, используя соответствующий алгоритм делимости. Пользователь может ограничивать действие этой функции, определяя элементы массива dims. Если в dims[i] уже записано число, то функция не будет изменять количество узлов в измерении i; функция модифицирует только нулевые элементы массиве, т.е. где dims[i]=0.
При определении виртуальной топологии каждый процесс получает ранг группы и позицию в топологии, которая может быть указана в виде декартовых координат. Для перевода декартовых координат в ранг группы используется функция