Н.В. Вдовикина, А.В. Казунин, И.В. Машечкин, А.Н. Терехин - Системное программное обеспечение - взаимодействие процессов (2002), страница 22
Описание файла
Документ из архива "Н.В. Вдовикина, А.В. Казунин, И.В. Машечкин, А.Н. Терехин - Системное программное обеспечение - взаимодействие процессов (2002)", который расположен в категории "". Всё это находится в предмете "операционные системы" из 3 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Онлайн просмотр документа "Н.В. Вдовикина, А.В. Казунин, И.В. Машечкин, А.Н. Терехин - Системное программное обеспечение - взаимодействие процессов (2002)"
Текст 22 страницы из документа "Н.В. Вдовикина, А.В. Казунин, И.В. Машечкин, А.Н. Терехин - Системное программное обеспечение - взаимодействие процессов (2002)"
int MPI_Alltoall(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm);
Параметры этой функции аналогичны параметрам MPI_Allgather().
Рис. 26 Работа функции MPI_Alltoall()
Помимо рассмотренных выше функций, библиотека MPI предоставляет так называемые «векторные» аналоги функций MPI_Scatter(), MPI_Gather(), MPI_Allgather() и MPI_Alltoall(), позволяющие разным ветвям пересылать или получать части массива разных длин, однако их подробное рассмотрение выходит за рамки данного пособия.
Коллективный обмен, совмещенный с обработкой данных.
Во многих случаях после сбора данных от всех ветвей непосредственно следует некоторая обработка полученных данных, например, их суммирование, или нахождение максимума и т.п. Библиотека MPI предоставляет несколько коллективных функций, которые позволяют совместить прием данных от всех ветвей и их обработку. Простейшей из этих функций является MPI_Reduce():
#include <mpi.h>
int MPI_Reduce(void* sendbuf, void* recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm);
Функция MPI_Reduce() является своего рода расширением функции MPI_Gather(): ветвь с номером root является получателем данных, отправителями являются все ветви. Параметры sendbuf, datatype, count имеют смысл для всех ветвей и задают адрес буфера с данными для отправки, тип отправляемых данных и их количество. Тип и количество данных должны совпадать во всех ветвях. Однако в процессе получения данных над ними поэлементно производится операция, задаваемая параметром op, результат которой заносится в соответствующий элемент буфера recvbuf ветви с номером root. Так, например, если параметр op равен константе MPI_SUM, что означает суммирование элементов, то в i-й элемент буфера recvbuf ветви с номером root будет записана сумма i-х элементов буферов sendbuf всех ветвей. Параметр recvbuf имеет смысл лишь для ветви с номером root, для всех остальных ветвей он игнорируется.
Для описания операций в MPI введен специальный тип MPI_Op. MPI предоставляет ряд констант этого типа, описывающих стандартные операции, такие как суммирование (MPI_SUM), умножение (MPI_PROD), вычисление максимума и минимума (MPI_MAX и MPI_MIN) и т.д. Кроме того, у программиста существует возможность описывать новые операции.
Функция MPI_Allreduce() представляет собой аналог MPI_Reduce() с той лишь разницей, что результирующий массив формируется на всех ветвях (и, соответственно, параметр recvbuf также должен быть задан на всех ветвях):
#include <mpi.h>
int MPI_Allreduce(void* sendbuf, void* recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm);
Функция MPI_Reduce_scatter() сочетает в себе возможности MPI_Reduce() и MPI_Scatter():
#include <mpi.h>
int MPI_Reduce_scatter(void* sendbuf, void* recvbuf, int *recvcounts, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm);
В процессе ее выполнения сначала над массивами sendbuf поэлементно производится операция, задаваемая параметром op, а затем результирующий массив разделяется на N частей, где N – количество ветвей в коммуникационном контексте, и каждая из ветвей получает в буфере recvbuf свою часть в соответствии со своим номером. Элементы массива recvcounts задают количество элементов, которое должно быть отправлено каждой ветви, что позволяет каждой ветви получать порции данных разной длины.
Наконец, функция MPI_scan() представляет собой некоторое сужение функции MPI_AllReduce():
#include <mpi.h>
int MPI_Scan(void* sendbuf, void* recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm);
В буфере recvbuf ветви с номером i после возврата из этой функции будет находиться результат поэлементного применения операции op к буферам sendbuf ветвей с номерами от 0 до i включительно. Очевидно, что в буфере recvbuf ветви с номером N-1 будет получен тот же результат, что и для аналогичного вызова MPI_Allreduce().
-
MPI: применение коллективных коммуникаций.
В данном примере производится приближенное вычисление числа π путем численного интегрирования на отрезке методом прямоугольников. Количество точек в разбиении определяет пользователь. Ветвь с номером 0 осуществляет ввод данных от пользователя, а затем, по окончании вычислений, - сбор данных от всех ветвей и вывод результата.
#include <mpi.h>
#include <stdio.h>
int main(int argc, char **argv)
{
int size, rank, N, i;
double h, sum, x, global_pi;
MPI_Init(&argc, &argv); /* Инициализируем библиотеку */
MPI_Comm_size(MPI_COMM_WORLD, &size);
/* Узнаем количество задач в запущенном приложении... */
MPI_Comm_rank (MPI_COMM_WORLD, &rank);
/* ...и свой собственный номер: от 0 до (size-1) */
if (rank == 0) {
/* ветвь с номером 0 определяет количество итераций... */
printf("Please, enter the total iteration count:\n");
scanf("%d", &N);
}
/*... и рассылает это число всем ветвям */
MPI_Bcast(&N, 1, MPI_INT, 0, MPI_COMM_WORLD);
h = 1.0 / N;
sum = 0.0;
/* вычисление частичной суммы */
for (i = rank + 1; i <= N; i += size) {
x = h * (i - 0.5);
sum += f(x);
}
sum = h * sum;
/* суммирование результата на ветви с номером 0 */
MPI_Reduce(&sum, &global_pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
if (rank == 0) {
printf("The result is %.10f\n", global_pi);
}
MPI_Finalize();
return 0;
}
8Алфавитный указатель упоминаемых библиотечных функций и системных вызовов.
_exit() 51
accept() 133
alarm() 43
bind() 131
connect() 132
creat() 70
exec(), семейство 47
exit(), функция 52
fcntl() 47, 81
fork() 42
ftok(), функция 101
getpid() 45
getppid() 45
kill() 67
listen() 133
longjmp() 92
mkfifo() 89
mknod() 89
MPI_Abort() 155
MPI_Allgather() 176
MPI_Allreduce() 179
MPI_Alltoall() 177
MPI_Barrier() 155
MPI_Bcast() 174
MPI_Bsend() 161
MPI_Comm_rank() 154
MPI_Comm_size() 154
MPI_Finalise() 155
MPI_Gather() 175
MPI_Get_count() 163
MPI_Ibsend() 167
MPI_Init() 154
MPI_Irecv() 166
MPI_Irsend() 167
MPI_Isend() 166
MPI_Issend() 167
MPI_Probe() 164
MPI_Recv() 162
MPI_Reduce() 178
MPI_Reduce_scatter() 179
MPI_Rsend() 161
MPI_Scan() 179
MPI_Scatter() 174
MPI_Send() 160
MPI_Ssend() 161
MPI_Test() 168
MPI_Testall() 169
MPI_Testany() 168
MPI_Testsome() 169
MPI_Wait() 168
MPI_Waitall() 169
MPI_Waitany() 168
MPI_Waitsome() 168
msgctl() 107
msgget() 105
msgrcv() 106
msgsnd() 105
nice() 60
pipe() 80
ptrace() 94
recv() 135
recvfrom() 136
semctl() 121
semget() 118
semop() 119
send() 134
sendto() 136
setjmp() 92
shmat() 115
shmctl() 116
shmdt() 115
shmget() 114
shutdown() 136
sigaction() 78
sigaddset() 76
sigdelset() 76
sigemptyset() 76
sigfillset() 76
sigismember() 76
signal() 68
sigpending() 76
sigprocmask() 75
socket() 129
unlink() 71
wait() 52
9Список литературы
-
Д.Цикритзис, Ф.Бернстайн. Операционные системы. Москва, Мир, 1977.
-
Э.С.Таненбаум. Современные операционные системы, 2-е издание. Санкт-Петербург, Издательский дом Питер, 2002.
-
П.Кейлингер. Элементы операционных систем. Москва, Мир, 1985.
-
Ч.Хоар. Взаимодействующие последовательные процессы. Москва , Мир, 1989.
-
Pate S.D. UNIX Internals. A Practical Approach. Addison-Wesley Longman, 1997.
-
К.Кристиан. Введение в операционную систему UNIX. Москва, Финансы и статистика. 1985.
-
Б.К.Керниган, Р.Пайк. UNIX – универсальная среда программирования. Москва, Финансы и статистика, 1992.
-
М.Дансмур, Г.Дейвис. Операционная система UNIX и программирование на языке Си. Москва, Радио и связь, 1989.
-
Т.Чан. Системное программирование на С++ для UNIX. Киев, Издательская группа BHV, 1997.
-
М.Устюгов. Введение в TCP/IP. Москва, .МГУ, 1997.
-
Б.Керниган, Д.Ритчи. Язык программирования Си. Издание 3-е, исправленное. Санкт-Петербург, Невский Диалект, 2001.
-
И.В.Машечкин, М.И.Петровский, П.Д.Скулачев, А.Н.Терехин. Системное Программное Обеспечение: файловые системы ОС Unix и Windows NT. Москва, Диалог-МГУ,1997.
-
А.Робачевский Операционная система UNIX. Санкт-Петербург, BHV-Санкт-Петербург, 1998
-
К.Хэвиленд, Д.Грей, Б.Салама. Системное программирование в UNIX. Москва, ДМК, 2000.
-
Н.Д.Васюкова, И.В.Машечкин, В.В.Тюляева, Е.М.Шляховая. Краткий конспект семинарских занятий по языку Си. Москва, МГУ, 1999.
-
В.Столлингс. Операционные системы. 4-ое издание. Москва, Издательский дом Вильямс, 2002.
1 Отметим, что детальное рассмотрение многих конкретных алгоритмов планирования выходит за рамки данного пособия.
2 Оригинальные обозначения P и V, данные Дейкстрой и получившие широкое распространение в литературе, являются сокращениями голландских слов proberen – проверить и verhogen – увеличить
3 Под сегментом здесь мы понимаем область памяти, которой система управляет как единым целым
4 Существуют и исключения из этого правила. Далее в этом пособии, рассказывая о системных вызовах, мы будем оговаривать такие исключения особо.
5 Эти процессы создаются во время начальной загрузки системы, механизм которой будет подробно рассмотрен ниже
6 Существует шесть различных системных вызовов exec(), отличающихся параметрами, которые будут описаны ниже.
7 при условии, разумеется, что у данного процесса имеются достаточные права для доступа к конкретному ресурсу, через который осуществляется взаимодействие
8 Следует заметить, что в разных версиях UNIX имена сигналов могут различаться.
9 Несмотря на это, как уже говорилось, сами сигналы, ожидающие своей обработки родительским процессом на момент порождения потомка, в том числе и блокированные, не наследуются потомком
10 это правило не является обязательным, но для корректной организации двустороннего обмена через один канал требуется дополнительная синхронизация
11 аббревиатура IPC – это сокращение от английского interprocess communication
12 Заметим, что данный аргумент может принимать не только указанные два значения, например, тип сокета SOCK_SEQPACKET обозначает соединение с установлением виртуального канала со всеми вытекающими отсюда свойствами, но при этом сохраняются границы сообщений; однако данный тип сокетов не поддерживается ни в домене AF_UNIX, ни в домене AF_INET, поэтому мы его здесь рассматривать не будем
13 Отметим, что, как уже говорилось, при использовании сокетов с установлением виртуального соединения границы сообщений не сохраняются, поэтому приложение, принимающее сообщения, может принимать данные совсем не теми же порциями, какими они были посланы. Вся работа по интерпретации сообщений возлагается на приложение.
14 MPI – сокращение от Message Passing Interface, т.е. «Механизм (или интерфейс) передачи сообщений»
15 Аббревиатура MPP представляет собой сокращение от «Massive Parallel Processing»
16 Аббревиатура SMP является сокращением фразы «Symmetric Multi Processing»
17 Аббревиатура NUMA расшифровывается как «Non-Unified Memory Access», что в буквальном переводе и означает «неоднородный доступ к памяти». Часто используется также обозначение «ccNUMA», что означает «cache-coherent NUMA», или система с неоднородным доступом к памяти с поддержкой когерентности (т.е. согласованности) кэшей
18 Заметим, что в версии стандарта MPI-2 описывается возможность динамического порождения ветвей, однако на момент написания данного пособия нам неизвестно ни об одной реализации MPI, в которой поддерживалось бы динамическое порождение ветвей, поэтому далее мы будем рассматривать только модель со статическим порождением ветвей в момент запуска приложения.
0