MPI

advertisement
Технология
программирования MPI
Антонов Александр Сергеевич,
к.ф.-м.н., с.н.с. лаборатории Параллельных
информационных технологий НИВЦ МГУ
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)
Выполнениеi 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
Процессы, которые не должны войти в
новые группы, указывают в качестве color
константу MPI_UNDEFINED. Им в
параметре newcomm вернется значение
MPI_COMM_NULL.
MPI_Comm_split(MPI_COMM_WORLD, rank%3,
rank, new_comm)
MPI
int MPI_Comm_free(MPI_Comm comm)
Удаление коммуникатора comm. Переменной
comm присваивается значение
MPI_COMM_NULL.
MPI
Топология – механизм сопоставления
процессам альтернативной схемы
адресации. В MPI топологии виртуальны, не
связаны с физической топологией сети.
Два типа топологий:
•декартова (прямоугольная решетка
произвольной размерности)
•топология графа.
MPI
int MPI_Cart_create(MPI_Comm
comm, int ndims, int *dims, int
*periods, int reorder, MPI_Comm
*comm_cart)
Создание декартовой топологии
comm_cart. ndims – размерность
декартовой решетки, dims – число
элементов в каждом измерении.
MPI
periods – массив из ndims элементов,
определяющий, является ли решетка
периодической вдоль каждого измерения.
reorder – при значении 1 системе
разрешено менять порядок нумерации
процессов.
Подпрограмма должна быть вызвана всеми
процессами коммуникатора.
Некоторым процессам может вернуться
значение MPI_COMM_NULL.
MPI
int MPI_Dims_create(nnodes,
ndims, dims)
Определение размеров dims для каждой из
ndims размерностей при создании
декартовой топологии для nnodes
процессов. dims(i) рассчитывается, если
перед вызовом функции оно равно 0, иначе
оставляется без изменений.
MPI
Размеры по разным размерностям
устанавливаются так, чтобы быть возможно
близкими друг к другу. Перед вызовом
функции значение nnodes должно быть
кратно произведению ненулевых значений
массива dims. Выходные значения массива
dims, переопределенные функцией, будут
упорядочены в порядке убывания.
MPI
int MPI_Cart_coords(MPI_Comm
comm, int rank, int maxdims, int
*coords)
Определение декартовых координат процесса
по его рангу. Координаты возвращаются в
массиве coords. Отсчет координат по
каждому измерению начинается с 0.
MPI
int MPI_Cart_rank(MPI_Comm comm,
int *coords, int *rank)
Определение ранга процесса по его
декартовым координатам. Для
периодических решеток координаты вне
допустимых интервалов пересчитываются,
для непериодических – ошибочны.
MPI
int MPI_Cart_sub(MPI_Comm comm,
int *dims, MPI_Comm *newcomm)
Расщепление коммуникатора comm на
подгруппы, соответствующие декартовым
подрешеткам меньшей размерности. i–ый
элемент массива равен 1, если i–ое
измерение должно остаться в подрешетке.
MPI
int MPI_Cartdim_get(MPI_Comm
comm, int *ndims)
Определение размерности декартовой
топологии коммуникатора comm.
MPI
int MPI_Cart_get(MPI_Comm comm,
int maxdims, int *dims, int
*periods, int *coords)
Получение информации о декартовой
топологии коммуникатора comm и
координатах в ней вызвавшего процесса.
MPI
int MPI_Cart_shift(MPI_Comm
comm, int direction, int disp,
int *source, int *dest)
Получение номеров посылающего (source)
и принимающего (dest) процессов в
декартовой топологии коммуникатора comm
для осуществления сдвига вдоль измерения
direction на величину disp.
MPI
Для периодических измерений
осуществляется циклический сдвиг, для
непериодических – линейный сдвиг.
Для n-мерной декартовой решетки значение
direction должно быть в пределах от 0
до n-1.
Значения source и dest можно
использовать, например, для обмена
функцией MPI_Sendrecv.
MPI
periods[0]=1;
periods[1]=1;
MPI_Cart_create(MPI_COMM_WORLD, 2, dims,
periods, 1, &comm);
MPI_Comm_rank(comm, &rank);
MPI_Cart_coords(comm, rank, 2, coords);
MPI_Cart_shift(comm, 0, shift, &source,
&dest);
MPI_Sendrecv_replace(a, 1, MPI_FLOAT, dest, 0,
source, 0, comm, &status);
MPI
int MPI_Graph_create(MPI_Comm
comm, int nnodes, int *index,
int *edges, int reorder,
MPI_Comm *comm_graph)
Создание топологии графа comm_graph.
nnodes – число вершин графа, index(i)
содержит суммарное количество соседей для
первых i вершин.
MPI
edges содержит упорядоченный список
номеров процессов-соседей.
reorder – при значении 1 системе
разрешено менять порядок нумерации
процессов.
Подпрограмма должна быть вызвана всеми
процессами коммуникатора.
Некоторым процессам может вернуться
значение MPI_COMM_NULL.
MPI
Процесс
0
1
2
3
Соседи
1, 3
0
3
0, 2
nnodes=4
index=2, 3, 4, 6
edges=1, 3, 0, 3, 0, 2
MPI
int MPI_Graph_neighbors_count
(MPI_Comm comm, int rank, int
*nneighbors)
Определение количества непосредственных
соседей данной вершины графа.
MPI
int MPI_Graph_neighbors(MPI_Comm
comm, int rank, int max, int
*neighbors)
Определение непосредственных соседей
данной вершины графа.
MPI
int MPI_Graphdims_get(MPI_Comm
comm, int *nnodes, int *nedges)
Определение числа вершин и числа ребер
графа.
MPI
int MPI_Graph_get(MPI_Comm comm,
int maxindex, int maxedges, int
*index, int *edges)
Определение информации о топологии графа.
MPI
int MPI_Topo_test(MPI_Comm comm,
int *type)
Определение типа топологии, связанной с
коммуникатором comm.
• MPI_GRAPH для графа
• MPI_CART для декартовой топологии
• MPI_UNDEFINED – нет связанной
топологии.
MPI
Сообщение – массив однотипных данных,
расположенных в последовательных ячейках
памяти.
Для пересылки разнотипных данных можно
использовать:
•Производные типы данных
•Упаковку данных
MPI
Производные типы данных создаются во
время выполнения программы с помощью
подпрограмм-конструкторов.
Создание типа:
•Конструирование типа
•Регистрация типа
MPI
Производный тип данных характеризуется
последовательностью базовых типов и
набором значений смещения относительно
начала буфера обмена.
Смещения могут быть как положительными,
так и отрицательными, не требуется их
упорядоченность.
MPI
int MPI_Type_contiguous(int
count, MPI_Datatype type,
MPI_Datatype *newtype)
Создание нового типа данных newtype,
состоящего из count последовательно
расположенных элементов базового типа
данных type.
MPI
int MPI_Type_vector(int count,
int blocklen, int stride,
MPI_Datatype type, MPI_Datatype
*newtype)
Создание нового типа данных newtype,
состоящего из count блоков по blocklen
элементов базового типа данных type.
Следующий блок начинается через stride
элементов после начала предыдущего.
MPI
count=2;
blocklen=3;
stride=5;
MPI_Type_vector(count, blocklen, stride,
MPI_DOUBLE, &newtype);
Создание нового типа данных (тип элемента,
количество элементов от начала буфера):
{(MPI_DOUBLE, 0), (MPI_DOUBLE, 1), (MPI_DOUBLE, 2),
(MPI_DOUBLE, 5), (MPI_DOUBLE, 6), (MPI_DOUBLE, 7)}
MPI
int MPI_Type_hvector(int count,
int blocklen, MPI_Aint stride,
MPI_Datatype type, MPI_Datatype
*newtype)
Создание нового типа данных newtype,
состоящего из count блоков по blocklen
элементов базового типа данных type.
Следующий блок начинается через stride
байт после начала предыдущего.
MPI
int MPI_Type_indexed(int count,
int *blocklens, int *displs,
MPI_Datatype type, MPI_Datatype
*newtype)
Создание нового типа данных newtype,
состоящего из count блоков по
blocklens(i) элементов базового типа
данных. i-й блок начинается через
displs(i) элементов с начала буфера.
MPI
for(i=0; i<n; i++){
blocklens[i]=n-i;
displs[i]=(n+1)*i;
}
MPI_Type_indexed(n, blocklens, displs,
MPI_DOUBLE, &newtype)
Создание нового типа данных для описания
верхнетреугольной матрицы.
MPI
int MPI_Type_hindexed(int count,
int *blocklens, MPI_Aint
*displs, MPI_Datatype type,
MPI_Datatype *newtype)
Создание нового типа данных newtype,
состоящего из count блоков по
blocklens(i) элементов базового типа
данных. i-й блок начинается через
displs(i) байт с начала буфера.
MPI
int MPI_Type_struct(int count,
int *blocklens, MPI_Aint
*displs, MPI_Datatype *types,
MPI_Datatype *newtype)
Создание структурного типа данных из
count блоков по blocklens(i) элементов
типа types(i). i-й блок начинается через
displs(i) байт.
MPI
blocklens[0]=3;
blocklens[1]=2;
types[0]=MPI_DOUBLE;
types[1]=MPI_CHAR;
displs[0]=0;
displs[1]=24;
MPI_Type_struct(2, blocklens, displs, types,
&newtype);
Создание нового типа данных (тип элемента,
количество байт от начала буфера):
{(MPI_DOUBLE, 0), (MPI_DOUBLE, 8), (MPI_DOUBLE, 16),
(MPI_CHAR, 24), (MPI_CHAR, 25)}
MPI
int MPI_Type_commit(MPI_Datatype
*datatype)
Регистрация созданного производного типа
данных datatype. После регистрации этот
тип данных можно использовать в операциях
обмена.
MPI
int MPI_Type_free(MPI_Datatype
*datatype)
Аннулирование производного типа данных
datatype. datatype устанавливается в
значение MPI_DATATYPE_NULL.
Производные от datatype типы данных
остаются. Предопределенные типы данных
не могут быть аннулированы.
MPI
int MPI_Type_size(MPI_Datatype
datatype, int *size)
Определение размера типа datatype в
байтах (объема памяти, занимаемого одним
элементом данного типа).
MPI
MPI_Type_lb(MPI_Datatype
datatype, MPI_Aint *displ)
Определение смещения displ в байтах
нижней границы элемента типа данных
datatype от базового адреса.
MPI
int MPI_Type_ub(MPI_Datatype
datatype, MPI_Aint *displ)
Определение смещения displ в байтах
верхней границы элемента типа данных
datatype от базового адреса.
MPI
int MPI_Type_extent(MPI_Datatype
datatype, MPI_Aint *extent)
Определение диапазона типа datatype в
байтах (разницы между верхней и нижней
границами элемента данного типа).
MPI
MPI_Address(void *location,
MPI_Aint *address)
Определение абсолютного байт-адреса
address размещения массива location в
оперативной памяти. Адрес отсчитывается от
базового адреса, значение которого
содержится в константе MPI_BOTTOM.
MPI
blocklens[0]=1;
blocklens[1]=1;
types[0]=MPI_DOUBLE;
types[1]=MPI_CHAR;
MPI_Address(dat1, address[0]);
displs[0]=address[0];
MPI_Address(dat2, address[1]);
displs[1]=address[1];
MPI_Type_struct(2, blocklens, displs, types,
&newtype);
MPI_Type_commit(newtype);
MPI_Send(MPI_BOTTOM, 1, newtype, dest, tag,
MPI_COMM_WORLD);
MPI
int MPI_Pack(void *inbuf, int
incount, MPI_Datatype datatype,
void *outbuf, int outsize, int
*position, MPI_Comm comm)
Упаковка incount элементов типа
datatype из массива inbuf в массив
outbuf со сдвигом position байт.
outbuf должен содержать хотя бы outsize
байт.
MPI
Параметр position увеличивается на
число байт, равное размеру записи.
Параметр comm указывает на коммуникатор,
в котором в дальнейшем будет пересылаться
сообщение.
MPI
int MPI_Unpack(void *inbuf, int
insize, int *position, void
*outbuf, int outcount,
MPI_Datatype datatype, MPI_Comm
comm)
Распаковка из массива inbuf со сдвигом
position байт в массив outbuf
outcount элементов типа datatype.
MPI
int MPI_Pack_size(int incount,
MPI_Datatype datatype, MPI_Comm
comm, int *size)
Определение необходимого объема памяти (в
байтах) для упаковки incount элементов
типа datatype.
MPI
float a[10];
char b[10], buf[100];
position=0;
if(rank == 0){
MPI_Pack(a, 10, MPI_FLOAT, buf, 100,
&position, MPI_COMM_WORLD);
MPI_Pack(b, 10, MPI_CHAR, buf, 100, &position,
MPI_COMM_WORLD);
MPI_BCAST(buf, 100, MPI_PACKED, 0,
MPI_COMM_WORLD);
}
MPI
else{
MPI_Bcast(buf, 100, MPI_PACKED, 0,
MPI_COMM_WORLD);
position=0;
MPI_Unpack(buf, 100, &position, &a, 10,
MPI_FLOAT, MPI_COMM_WORLD);
MPI_Unpack(buf, 100, &position, &b, 10,
MPI_CHAR, MPI_COMM_WORLD);
}
MPI
Задания:
•написать программу, в которой операция
глобального суммирования моделируется
схемой сдваивания (каскадная схема) с
использованием пересылок данных типа
точка-точка. Сравнить эффективность такого
моделирования с использованием функции
MPI_Reduce.
MPI
Задания:
•написать программу, в которой реализуется
распределенное вычисление скалярного
произведения двух больших векторов.
Исследовать зависимость ускорения
программы от числа процессоров для
различных длин векторов.
MPI
Литература
1. MPI: A Message-Passing Interface Standard (Version 1.1)
(http://parallel.ru/docs/Parallel/mpi1.1/mpi-report.html)
2. Воеводин В.В., Воеводин Вл.В. Параллельные вычисления.
СПб.: БХВ-Петербург, 2002.
3. Антонов А.С. Параллельное программирование с
использованием технологии MPI: Учебное пособие.-М.:
Изд-во МГУ, 2004.
4. Антонов А.С. Введение в параллельные вычисления
(методическое пособие). М.: Изд-во Физического
факультета МГУ, 2002.
MPI
Литература
5. Букатов А.А., Дацюк В.Н., Жегуло А.И. Программирование
многопроцессорных вычислительных систем. Ростов-наДону: Издательство ООО "ЦВВР", 2003.
6. Шпаковский Г.И., Серикова Н.В. Программирование для
многопроцессорных систем в стандарте MPI: Пособие.
Минск: БГУ, 2002.
7. Немнюгин С.А., Стесик О.Л. Параллельное
программирование для многопроцессорных
вычислительных систем. СПб.: БХВ-Петербург, 2002.
8. Корнеев В.Д. Параллельное программирование в MPI.
Новосибирск: Изд-во СО РАН, 2000.
Download