1.04k likes | 1.33k Views
Антонов Александр Сергеевич , к.ф.-м.н., с.н.с. лаборатории Параллельных информационных технологий НИВЦ МГУ. Технология программирования MPI. В операциях коллективного взаимодействия процессов участвуют все процессы коммуникатора !
E N D
Антонов Александр Сергеевич, к.ф.-м.н., с.н.с. лаборатории Параллельных информационных технологий НИВЦ МГУ Технология программирования MPI
В операциях коллективного взаимодействия процессов участвуют все процессы коммуникатора! Как и для блокирующих процедур, возврат означает то, что разрешен свободный доступ к буферу приема или посылки. Сообщения, вызванные коллективными операциями, не пересекутся с другими сообщениями. MPI
Нельзя рассчитывать на синхронизацию процессов с помощью коллективных операций. Если какой-то процесс завершил свое участие в коллективной операции, то это не означает ни того, что данная операция завершена другими процессами коммуникатора, ни даже того, что она ими начата (если это возможно по смыслу операции). MPI
int MPI_Barrier(MPI_Comm comm) Работа процессов блокируется до тех пор, пока все оставшиеся процессы коммуникатора commне выполнят эту процедуру. Все процессы должны вызвать MPI_Barrier, хотя реально исполненные вызовы различными процессами коммуникатора могут быть расположены в разных местах программы. MPI
int MPI_Bcast(void *buf, int count, MPI_Datatype datatype, int root, MPI_Comm comm) Рассылка сообщения от процессаrootвсем процессам данного коммуникатора. Значения параметровcount, datatype, rootиcommдолжны быть одинаковыми у всех процессов. MPI
MPI данные процессы
int MPI_Gather(void *sbuf, int scount, MPI_Datatype stype, void *rbuf, int rcount, MPI_Datatype rtype, int root, MPI_Comm comm) Сборка данных из массивов sbufсо всех процессов в буфереrbufпроцессаroot. Данные сохраняются в порядке возрастания номеров процессов. MPI
На процессе root существенными являются значения всех параметров, а на остальных процессах — только значения параметров sbuf, scount, stype, rootи comm. Значения параметров rootи comm должны быть одинаковыми у всех процессов. Параметр rcount у процесса root обозначает число элементов типа rtype, принимаемых от каждого процесса. MPI
MPI данные процессы
int MPI_Gatherv(void *sbuf, int scount, MPI_Datatype stype, void *rbuf, int *rcounts, int *displs, MPI_Datatype rtype, int root, MPI_Comm comm) Сборка различного количества данных из массивов sbuf. Порядок расположения задает массив displs. MPI
rcounts – целочисленный массив, содержащий количество элементов, передаваемых от каждого процесса (индекс равен рангу адресата, длина равна числу процессов в коммуникаторе). displs – целочисленный массив, содержащий смещения относительно начала массива rbuf (индекс равен рангу адресата, длина равна числу процессов в коммуникаторе). MPI
int MPI_Scatter(void *sbuf, int scount, MPI_Datatype stype, void *rbuf, int rcount, MPI_Datatype rtype, int root, MPI_Comm comm) Рассылка данных из массива sbufпроцесса root вмассивы rbufвсех процессов. Данные рассылаются в порядке возрастания номеров процессов. MPI
На процессе root существенными являются значения всех параметров, а на всех остальных процессах — только значения параметров rbuf, rcount, rtype, source и comm. Значения параметров sourceи commдолжны быть одинаковыми у всех процессов. MPI
MPI данные процессы
float sbuf[SIZE][SIZE], rbuf[SIZE]; if(rank == 0) for(i=0; i<SIZE; i++) for (j=0; j<SIZE; j++) sbuf[i][j]=…; if (numtasks == SIZE) MPI_Scatter(sbuf, SIZE, MPI_FLOAT, rbuf, SIZE, MPI_FLOAT, 0, MPI_COMM_WORLD); MPI
int MPI_Scatterv(void *sbuf, int *scounts, int *displs, MPI_Datatype stype, void *rbuf, int rcount, MPI_Datatype rtype, int root, MPI_Comm comm) Рассылка различного количества данныхиз массива sbuf. Начало рассылаемых порций задает массив displs. MPI
scounts – целочисленный массив, содержащий количество элементов, передаваемых каждому процессу (индекс равен рангу адресата, длина равна числу процессов в коммуникаторе). displs – целочисленный массив, содержащий смещения относительно начала массива sbuf (индекс равен рангу адресата, длина равна числу процессов в коммуникаторе). MPI
int MPI_Allgather(void *sbuf, int scount, MPI_Datatype stype, void *rbuf, int rcount, MPI_Datatype rtype, MPI_Comm comm) Сборка данных из массивов sbufсо всех процессов в буфереrbufкаждого процесса. Данные сохраняются в порядке возрастания номеров процессов. MPI
MPI данные процессы
int MPI_Allgatherv(void *sbuf, int scount, MPI_Datatype stype, void *rbuf, int *rcounts, int *displs, MPI_Datatype rtype, MPI_Comm comm) Сборка на всех процессах различного количества данныхиз sbuf. Порядок расположения задает массив displs. MPI
int MPI_Alltoall(void *sbuf, int scount, MPI_Datatype stype, void *rbuf, int rcount, MPI_Datatype rtype, MPI_Comm comm) Рассылка каждым процессом различных данных всем другим процессам. j-й блок данных i-го процесса попадает в i-й блок j-го процесса. MPI
MPI данные процессы
int MPI_Alltoallv(void *sbuf, int scount, MPI_Datatype stype, void *rbuf, int rcount, MPI_Datatype rtype, MPI_Comm comm) Рассылка со всех процессов различного количества данныхвсем другим процессам. MPI
int MPI_Reduce(void *sbuf, void *rbuf, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm) Выполнение countнезависимых глобальных операций opнад соответствующими элементами массивов sbuf.Результат получается в массиве rbufпроцесса root. MPI
Типы предопределенных глобальных операций: MPI_MAX, MPI_MIN – максимальное и минимальное значения; MPI_SUM, MPI_PROD – глобальная сумма и глобальное произведение; MPI_LAND, MPI_LOR, MPI_LXOR – логические “И”, “ИЛИ”, искл. “ИЛИ”; MPI_BAND, MPI_BOR, MPI_BXOR – побитовые “И”, “ИЛИ”, искл. “ИЛИ” MPI
int MPI_Allreduce(void *sbuf, void *rbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm) Выполнение countнезависимых глобальных операций opнад соответствующими элементами массивов sbuf.Результат получается в массиве rbufкаждого процесса. MPI
for(i=0; i<n; i++) s[i]=0.0; for(i=0; i<n; i++) for(j=0; j<m; j++) s[i]=s[i]+a[i][j]; MPI_Allreduce(s, r, n, MPI_FLOAT, MPI_SUM, MPI_COMM_WORLD); MPI
int MPI_Reduce_scatter(void *sbuf, void *rbuf, int *rcounts, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm) Выполнение rcounts(i) независимых глобальных операций opнад соответствующими элементами массивов sbuf. MPI
Сначала выполняются глобальные операции, затем результат рассылается по процессам. i-й процесс получает rcounts(i) значений результата и помещает в массив rbuf. MPI
int MPI_Scan(void *sbuf, void *rbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm) Выполнение count независимых частичных глобальных операций opнад соответствующими элементами массивов sbuf. MPI
i-й процесс выполняет глобальную операцию над соответствующими элементами массива sbuf процессов 0…i и помещает результат в массив rbuf. Окончательный результат глобальной операции получается в массиве rbuf последнего процесса. MPI
int MPI_Op_create (MPI_User_function *func, int commute, MPI_Op *op) Создание пользовательской глобальной операции. Если commute=1, то операция должна быть коммутативной и ассоциативной. Иначе порядок фиксируется по увеличению номеров процессов. MPI
typedef void MPI_User_function (void *invec, void *inoutvec, int *len, MPI_Datatype type) Интерфейс пользовательской функции. int MPI_Op_free(MPI_Op *op) Уничтожение пользовательской глобальной операции. MPI
Группа – упорядоченное множество процессов. Каждому процессу в группе сопоставлено целое число – ранг. MPI_GROUP_EMPTY – пустая группа. MPI_GROUP_NULL – значение, используемое для ошибочной группы. Новую группу можно создать только из уже существующих групп или коммуникаторов. MPI
Коммуникатор – контекст обмена группы. В операциях обмена используются только коммуникаторы! MPI_COMM_WORLD – коммуникатор для всех процессов приложения. MPI_COMM_NULL – значение, используемое для ошибочного коммуникатора. MPI_COMM_SELF – коммуникатор, включающий только вызвавший процесс. MPI
int MPI_Comm_group(MPI_Comm comm, MPI_Group *group) Получение группы group, соответствующей коммуникатору comm. MPI
int MPI_Group_incl(MPI_Group group, int n, int *ranks, MPI_Group *newgroup) Создание группы newgroup из n процессов группы group с рангами ranks(0),…,ranks(n-1), причем рангу ranks(i) в старой группе соответствует ранг i в новой группе. При n=0 создается пустая группа MPI_GROUP_EMPTY. MPI
int MPI_Group_excl(MPI_Group group, int n, int *ranks, MPI_Group *newgroup) Создание группы newgroup из процессов группы group, исключая процессы с рангами ranks(0),…,ranks(n-1), причем порядок процессов в новой группе соответствует порядку процессов в старой группе. MPI
int MPI_Group_intersection (MPI_Group group1, MPI_Group group2, MPI_Group *newgroup) Создание группы newgroup из пересечения групп group1и group2. MPI
int MPI_Group_union(MPI_Group group1, MPI_Group group2, MPI_Group *newgroup) Создание группы newgroup из объединения групп group1и group2. MPI
int MPI_Group_difference (MPI_Group group1, MPI_Group group2, MPI_Group *newgroup) Создание группы newgroup из разности групп group1и group2. MPI
int MPI_Group_free(MPI_Group *group) Уничтожение группы group. Переменная group принимает значение MPI_GROUP_NULL. MPI
int MPI_Group_size(MPI_Group group, int *size) int MPI_Group_rank(MPI_Group group, int *rank) Определение количества процессов и номера процесса в группе. Если процесс не входит в группу, то возвращается значение MPI_UNDEFINED. MPI
int MPI_Group_translate_ranks (MPI_Group group1, int n, int *ranks1, MPI_Group group2, int *ranks2) В массиве ranks2 возвращаются ранги в группе group2 процессов с рангами ranks1 в группе group1. MPI
int MPI_Group_compare(MPI_Group group1, MPI_Group group2, int *result) Сравнение групп group1и group2. Если совпадают, то возвращается значение MPI_IDENT. Если отличаются только рангами процессов, то возвращается значение MPI_SIMILAR. Иначе возвращается значение MPI_UNEQAL. MPI
int MPI_Comm_dup(MPI_Comm comm, MPI_Comm *newcomm) Создание нового коммуникатора newcomm с той же группой процессов и атрибутами, что и у коммуникатора comm. MPI
int MPI_Comm_create(MPI_Comm comm, MPI_Group group, MPI_Comm *newcomm) Создание нового коммуникатора newcomm из коммуникатора comm с группой процессов group. Вызов должен стоять во всех процессах коммуникатора comm. На процессах, не принадлежащих group вернется значение MPI_COMM_NULL. MPI
MPI_Comm_group(MPI_COMM_WORLD, &group); for(i=0; i<nprocs/2; i++) ranks[i]=i; if (rank < nprocs/2) MPI_Group_incl(group, nprocs/2, ranks, &new_group); else MPI_Group_excl(group, nprocs/2, ranks, &new_group); MPI
MPI_Comm_create(MPI_COMM_WORLD, new_group, &new_comm); MPI_Allreduce(sbuf, rbuf, 1, MPI_INT, MPI_SUM, new_comm); MPI_Group_rank(new_group, &new_rank); printf("rank= %d newrank= %d rbuf= %d \n", rank, newrank, rbuf); MPI
int MPI_Comm_split(MPI_Comm comm, int color, int key, MPI_Comm *newcomm) Разбиение коммуникатора comm на несколько по числу значений параметра color. В одну подгруппу попадают процессы с одним значением color. Процессы с бОльшим значением keyполучат больший ранг. MPI