Комунікатори та операції з ними. 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Комунікатори та операції з ними.



Комунiкатор надає окремий контекст обмiну процесiв деякої групи. Контекст забезпечує можливiсть незалежних обмiнiв даними. Кожнiй групi процесiв може вiдповiдати кiлька ко- мунiкаторiв, але кожен комунiкатор у будь-який момент часу однозначно вiдповiдає тiльки однiй групi

Наступнi комунiкатори створюються вiдразу пiсля виклику MPI_init:

• MPI_COMM_WORLD – комунiкатор котрий мiстить всi процеси додатку;

• MPI_COMM_NULL – значення, що використовується для помилкового комунiкато- ра; • MPI_COMM_SELF – комунiкатор котрий мiстить тiльки процес котрий його вико- ристав.

Створення комунiкатора є колективною операцiєю i вимагає операцiї мiжпроцесорного обмiну, тому такi функцiї мають викликатися всiма процесами деякого iснуючого комунi- катора.

int MPI_Comm_dup(MPI_Comm comm, MPI_Comm newcomm); - Створення нового комунiкатора newcomm з тiєю ж групою процесiв що i comm та такими ж атрибутами.

int MPI_Comm_create(MPI_Comm comm, MPI_Group group, MPI_Comm newcomm); Створення нового комунiкатора newcomm з процесiв групи group яка має бути пiд- множиною групи пов’язаної з комунiкаторм comm. Виклик повен бути здiйсненний зi всiх процесiв комунiкатора comm. В процесас якi не належать до групи group буде повернуто MPI_COMM_NULL.

int MPI_Comm_split(MPI_Comm comm, int color, int key, MPI_Comm newcomm); - Розбиття комунiкатора comm на кiлька нових комунiкаторiв по числу значень параме- тра color. В один комунiкатор потрапляють процеси з одним значенням color. Процеси з великим значенням параметра key отримають бiльший ранг в новiй групi, при однаковому значеннi параметра key порядок нумерацiї процесiв вибирається системою.

 

Декатрова топологія в MPI.

 

Топологiя – це механiзм спiвставлення процесам деякого комунiкатора альтернативної схеми адресацiї. В МРI топологiї вiртуальнi, тобто вони не пов’язанi з фiзичною топологiєю комунiкацiйної мережi. Топологiя використовується програмiстом для бiльш зручного по- значення процесiв, i таким чином, наближення паралельної програми до структури матема- тичного алгоритму. Крiм того, топологiя може використовуватися системою для оптимiзацiї розподiлу процесiв за фiзичними процесорами використовуваного паралельного комп’ютера за допомогою змiни порядку нумерацiї процесiв усерединi комунiкатора.

 

В МРI передбачено два типи топологiй:

• декартова топологiя (прямокутна решiтка довiльної розмiрностi);

• топологiя графа.

 

int MPI_Topo_test(MPI_Comm comm, int status); Функцiя визначення типу топологiї, пов’язаної з комунiкатором comm.

 

int MPI_Cart_create(MPI_Comm comm_old, int ndims, const int dims[], const int periods [], int reorder, MPI_Comm comm_cart); Створення комунiкатора comm_cart, що володiє декартовою топологiєю, з процесiв ко- мунiкатора comm_old

 

int MPI_Cart_coords(MPI_Comm comm, int rank, int maxdims, int coords[]); - Визначення декартових координат процеса по його рану rank в комунiкаторi comm. Вiдрахунок координат в кожному вимiрi починається з нуля.

int MPI_Cart_rank(MPI_Comm comm, const int coords[], int rank); - Визначення рангу процеса rank за його декартовими координатами coords.

int MPI_Cart_get(MPI_Comm comm, int maxdims, int dims[], int periods[], int coords[]); -Одержання iнформацiї про декартову топологiю котра пов’язана з комунiкатором comm та координат в нiй прцесу, що виклика дану функцiю. maxdims – задає розмiрнiсть топо- логiї. dims – повертає кiлькiсть процесiв для кожого вимiру. periods – перiодичнiсть по кожному вимiру. coords – координати процесу в декартовiй топологiї.

int MPI_Cart_shift(MPI_Comm comm, int direction, int disp, int rank_source, int rank_dest); Отримання номерiв посилаючого rank_source i приймаючого rank_dest процесiв в де- картовiй топологiї комунiкатора comm для здiйснення зсуву уздовж вимiру direction на величину disp.

 

 

Топологія графа в MPI.

int MPI_Graph_create(MPI_Comm comm_old, int nnodes, const int index[], const int edges[], int reorder, MPI_Comm comm_graph);

 

Створення, на основi комунiкатора comm_old, комунiкатора comm_graph з топологiєю графа. Параметер nnodes задає кiлькiсть вершин графа, index – задає сумарну кiлькiсть сусiдiв для перших вершин. Масив edges мiстить впорядкований список процесiв сусiдiв для всiх вершин. reorder – логiчний параметр, що визначає, чи системi дозволено мiняти порядок нумерацiї процесiв для оптимiзацiї розподiлу процесiв за фiзичними процесорам використовуваного паралельного комп’ютера.Фкнуцiя MPI_Graph_create є колективною, отже повинна бути викликана з кожного ппроцесу комунiкатора comm. Якщо кiлькiсть процесiв в комунiкаторi comm_graph мен- ша вiд кiлькостi у вихiдному екомунiкаторi comm – деяким процесам може повернутись значення MPI_COMM_NULL, а якщо бiльша – виклик буде помилковим.

 

Для опису такого графа необхiдно заповнити наступнi структури: index[] = {2, 3, 4, 6}; edges[] = {1, 3, 0, 3, 0, 2};

пiсля цього можна створювати топологiю графа (необхiдно не менше чотирьох процесiв). int

MPI_Graph_neighbors_count(MPI_Comm comm, int rank, int nneighbors); Визначає кiлькiсть сусiдiв nneighbors прцесу з рангом rank в топологiї графа.

int MPI_Graph_neighbors(MPI_Comm comm, int rank, int maxneighbors, int neighbors[]); Визначеня рангiв безпосереднiх сусiдiв процесу з рангом rank, ранги сусiдiв повертаю- ться в масивi neighbors*+. int MPI_Graphdims_get(MPI_Comm comm, int nnodes, int nedges); - Визначення кiлькостi веошин nnodes та ребер nedges в топологiї графа пов’язаної з комунiкатором comm.

int MPI_Graph_get(MPI_Comm comm, int maxindex, int maxedges, int index[], int edges[]); 3

Отримання iнформацiї про топологiю графа, котра пов’язана з комунiкатором comm. В масивах index та edges повертається опис топологiї, maxindex, maxedges – мiстять обмеже- ння на розмiри вiдповiдних масивiв (можна одержати за допомогою MPI_Graphdims_get).

 

1. Написати приклад MPI програми котра надрукує номера процесів та імена процесорів на котрих працює. Навести команди компіляції та запуску MPI програми.

#include <mpi.h>

#include <stdio.h>

int main(int argc, char **argv)

{ int size, rank, i;

MPI_Init(&argc, &argv);

MPI_Comm_size(MPI_COMM_WORLD, &size);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

char processor_name[MPI_MAX_PROCESSOR_NAME];

int name_len;

MPI_Get_processor_name(processor_name, &name_len);

if(rank == 0) printf("Total processes count = %d\n", size);

printf("I am %d process from %d (%s) processes!\n", rank, size, processor_name);

MPI_Finalize();

return 0; }

 

2. Написати приклад обміну між двома процесами з використанням функцій блокованого обміну.

#include <mpi.h>

#include <stdio.h>

int main(int argc, char **argv)

{ int nproc, my_rank;

MPI_Init(&argc, &argv);

MPI_Comm_size(MPI_COMM_WORLD, &nproc);

MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

if (my_rank == 0) {

MPI_Send ("Hello proces 1!", 15, MPI_CHAR, 1, 77, MPI_COMM_WORLD);

printf("Message send by proc %d.\n", my_rank);

} else if (my_rank == 1) { char recv_buffer[15];

MPI_Status status;

 

MPI_Recv (recv_buffer, 15, MPI_CHAR, 0, 77, MPI_COMM_WORLD, &status); printf("Message received by proc %d.\n", my_rank); printf("Message: %s\n", recv_buffer);

} MPI_Finalize(); return 0; }

3. Написати приклад обміну між парними та непарними процесами з використанням функцій блокованого обміну.

#include <mpi.h>

#include <stdio.h>

int main(int argc, char **argv)

{ int nproc, my_rank;

 

MPI_Init(&argc, &argv);

MPI_Comm_size(MPI_COMM_WORLD, &nproc);

MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

if (my_rank%2 == 0) {

 

char str[] = "Hello proces %d!"; char str2[20];

 

sprintf(str2,str,my_rank + 1);

 

MPI_Send (str2, 20, MPI_CHAR, my_rank + 1, 77, MPI_COMM_WORLD);

printf("Message send by proc %d.\n", my_rank);

}

else if (my_rank%2 == 1) {

 

char recv_buffer[15];

MPI_Status status;

 

MPI_Recv (recv_buffer, 20, MPI_CHAR, my_rank - 1, 77, MPI_COMM_WORLD,

&status);

printf("Message received by proc %d.\n", my_rank); printf("Message: %s\n", recv_buffer);

 

}

 

MPI_Finalize();

 

return 0;

}

 

 

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

 

#include <mpi.h>

#include <stdio.h>

int main(int argc, char **argv)

{ int nproc, my_rank;

 

MPI_Init(&argc, &argv);

MPI_Comm_size(MPI_COMM_WORLD, &nproc);

MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

if (my_rank == 0) {

 

MPI_Request request;

MPI_Status status;

 

MPI_Isend ("Hello proces 1!", 15, MPI_CHAR, 1, 77,

MPI_COMM_WORLD, &request);

MPI_Wait (&request, &status); printf("Message send by proc %d.\n", my_rank);

} else if (my_rank == 1) {

 

char recv_buffer[15]; MPI_Request request;

MPI_Status status;

 

MPI_Irecv (recv_buffer, 15, MPI_CHAR, 0, 77, MPI_COMM_WORLD,

&request);

printf("Message received by proc %d.\n", my_rank); MPI_Wait (&request, &status); printf("Message: %s\n", recv_buffer);

 

}

 

MPI_Finalize();

return 0;

}

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

 

#include <mpi.h>

#include <stdio.h>

int main(int argc, char **argv)

{ int nproc, my_rank;

MPI_Init(&argc, &argv);

MPI_Comm_size(MPI_COMM_WORLD, &nproc);

MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

if (my_rank%2 == 0) {

 

char str[] = "Hello proces %d!"; char str2[20];

sprintf(str2,str,my_rank + 1);

 

MPI_Request request;

MPI_Status status;

 

MPI_Isend (str2, 20, MPI_CHAR, my_rank + 1, 77,

MPI_COMM_WORLD, &request);

MPI_Wait (&request, &status);

printf("Message send by proc %d.\n", my_rank);

} else if (my_rank%2 == 1) {

 

char recv_buffer[20]; MPI_Request request;

MPI_Status status;

 

MPI_Irecv (recv_buffer, 20, MPI_CHAR, my_rank - 1, 77,

MPI_COMM_WORLD, &request);

printf("Message received by proc %d.\n", my_rank); MPI_Wait (&request, &status); printf("Message: %s\n", recv_buffer);

}

 

MPI_Finalize();

return 0;

}

6. Написати приклад створення MPI структури з трьома полями.

#include <stdio.h>

#include <mpi.h>

#include <stdlib.h>

#include <stddef.h>

typedef struct{ char name[20]; int year; int mark; } UserStruct;

int main(int argc, char ** argv){

int NUMBER_OF_PROCS, RANK_OF_CURRENT, NEXT_RANK, PREV_RANK;

MPI_Status status;

UserStruct us;

MPI_Datatype us_type;

int len[4] = {10, 1, 1, 1};

MPI_Aint pos[4] = {offsetof(UserStruct, name), offsetof(UserStruct, year), offsetof(UserStruct, mark), sizeof(us) };

MPI_Init(&argc, &argv);

MPI_Datatype type[4] = {MPI_CHAR, MPI_INT, MPI_INT, MPI_UB};

MPI_Type_create_struct(4, len, pos, type, &us_type);

MPI_Type_commit(&us_type);

UserStruct send_buf = {"---------Ваше ім’я-----------", 1994, 4};

UserStruct recv_buf;

int size_of_data= 1, msg_tag = 55;

MPI_Comm_size(MPI_COMM_WORLD, &NUMBER_OF_PROCS);

MPI_Comm_rank(MPI_COMM_WORLD, &RANK_OF_CURRENT);

NEXT_RANK = RANK_OF_CURRENT == NUMBER_OF_PROCS - 1? MPI_PROC_NULL:

RANK_OF_CURRENT + 1;

PREV_RANK = RANK_OF_CURRENT == 0? MPI_PROC_NULL: RANK_OF_CURRENT - 1;

MPI_Sendrecv(&send_buf, size_of_data, us_type, NEXT_RANK, msg_tag,

&recv_buf, size_of_data, us_type, PREV_RANK, msg_tag,

MPI_COMM_WORLD, &status);

printf("Proc: %d, From: %d, To: %d, Name: %s, Year: %d, Mark: %d \n",

RANK_OF_CURRENT, PREV_RANK, NEXT_RANK, recv_buf.name, recv_buf.year, recv_buf.mark);

MPI_TYPE_FREE(&us_type)

MPI_Finalize();

return 0;

}

 

 

7. Написати приклад пересилки прийому запакованих типiв даних

#include "mpi.h"

#include <stdio.h>

 

int main(int argc, char *argv[])

{

int rank, size;

int i;

char c[100];

char buffer[110];

int position = 0;

MPI_Status status;

MPI_Init(&argc, &argv);

MPI_Comm_size(MPI_COMM_WORLD, &size);

if (size < 2)

{

printf("Please run with 2 processes.\n");fflush(stdout);

MPI_Finalize();

return 1;

}

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

 

if (rank == 0)

{

for (i=0; i<100; i++)

c[i] = i;

i = 123;

MPI_Pack(&i, 1, MPI_INT, buffer, 110, &position, MPI_COMM_WORLD);

MPI_Pack(c, 100, MPI_CHAR, buffer, 110, &position, MPI_COMM_WORLD);

MPI_Send(buffer, position, MPI_PACKED, 1, 100, MPI_COMM_WORLD);

}

if (rank == 1)

{

MPI_Recv(buffer, 110, MPI_PACKED, 0, 100, MPI_COMM_WORLD, &status);

MPI_Unpack(buffer, 110, &position, &i, 1, MPI_INT, MPI_COMM_WORLD);

MPI_Unpack(buffer, 110, &position, c, 100, MPI_CHAR, MPI_COMM_WORLD);

printf("i=%d\nc[0] = %d\n...\nc[99] = %d\n", i, (int)c[0], (int)c[99]);fflush(stdout);

}

 

MPI_Finalize();

return 0; }

8. Написати приклад обміну між всіма процесами з використанням функції MPI_Bcast.

#include <stdio.h>

#include <mpi.h>

#define N 5

int main(int argc, char** argv)

{

int rank, size;

char* msg;

MPI_Init(&argc, &argv);

MPI_Comm_size(MPI_COMM_WORLD, &size);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

if(rank == 0){ msg = "Heil to all!";

}

MPI_Barrier(MPI_COMM_WORLD);

MPI_Bcast(&msg, 11, MPI_CHAR, 0, MPI_COMM_WORLD);

 

if(rank!= 0)

{

printf("Proc %d received\t: %s \nProc %d says\t: Heil master process!\n", rank, msg, rank);

}

MPI_Finalize();

return 0;

}

 

9. Написати приклад додавання квадратних матриць з використанням колективних функцій.

#include <stdio.h>

#include <mpi.h>

#define N 5

int main(int argc, char** argv)

{

int rank, i, j, size; double Mtx1[N][N], Mtx2[N][N], Mtx_sum[N][N]; double row1[N], row2[N], row_sum[N];

MPI_Init(&argc, &argv);

MPI_Comm_size(MPI_COMM_WORLD, &size);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

if (rank == 0)

{

for (i=0; i<N; i++)

for (j=0; j<N; j++) {

Mtx1[i][j]=(i-2)*(j-5);

Mtx2[i][j]=(i-2)*(j-5);

} }

MPI_Scatter(Mtx1, N, MPI_DOUBLE, row1, N, MPI_DOUBLE, 0, MPI_COMM_WORLD);

MPI_Scatter(Mtx2, N, MPI_DOUBLE, row2, N, MPI_DOUBLE, 0,

MPI_COMM_WORLD);

for (i = 0; i < N; i++) {

row_sum[i] = row1[i] + row2[i]; if(rank == 0)printf("%d, max %lf\n", rank, row_sum[i]);

}

MPI_Gather(row_sum, N, MPI_DOUBLE, Mtx_sum, N, MPI_DOUBLE, 0,

MPI_COMM_WORLD);

 

if (rank == 0)

{

for (i=0; i<N; i++)

{

for (j=0; j<N; j++)

{

printf("%lf\t", Mtx_sum[i][j]);

}

printf("\n");

} }

 

MPI_Finalize(); return 0; }

 

10. Написати приклад знаходження суми максимальних елементiв рядкiв матриці з використанням колективних функцій.

#include <stdio.h>

#include <mpi.h>

#define N 5

int main(int argc, char** argv)

{

int rank, i, j, size; double Mtx[N][N], c[N]; double row[N]; double max_row, sum;

MPI_Init(&argc, &argv);

MPI_Comm_size(MPI_COMM_WORLD, &size);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

if (rank == 0)

{ for (i=0; i<N; i++)

for (j=0; j<N; j++)

Mtx[i][j]=(i-2)*(j-5);

}

MPI_Scatter(Mtx, N, MPI_DOUBLE, row, N, MPI_DOUBLE, 0, MPI_COMM_WORLD);

max_row = row[0];

for (i = 0; i < N; i++)

{

if (row[i]>max_row)

{ max_row = row[i]; } }

printf("%d, max %lf\n", rank, max_row);

MPI_Gather(&max_row, 1, MPI_DOUBLE, c, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);

if (rank == 0) { sum = 0;

for (i=0; i<N; i++)

sum += c[i];

printf("Sum of max row element: %lf \n",sum);

}

MPI_Finalize();

return 0; }

 

11. Написати приклад знаходження суми елементiв матриці з використанням функції MPI_Reduce.

#include <stdio.h>

#include <mpi.h>

#define N 5

int main(int argc, char** argv)

{

 

int rank, i, j, size; double Mtx[N][N], a[N], b[N];

 

MPI_Init(&argc, &argv);

 

MPI_Comm_size(MPI_COMM_WORLD, &size);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

 

for(i = 0; i < N; i++) for(j = 0; j < N; j++)

Mtx[i][j] = 1;//(i-2)*(j-5);

 

MPI_Barrier(MPI_COMM_WORLD);

 

MPI_Allreduce(Mtx, a, N, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);

MPI_Reduce(a, b, N, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);

 

if (rank==0) printf("Sum=%lf\n",b[0]);

 

MPI_Finalize();

 

return 0;

}

12. Написати приклад знаходження максимума елементiв вектора з використанням функції MPI_Reduce.

#include <stdio.h>

#include <mpi.h>

#define N 10

int main(int argc, char** argv)

{ int rank, i, size; double a[N], b[N];

 

MPI_Init(&argc, &argv);

 

MPI_Comm_size(MPI_COMM_WORLD, &size);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

 

for(i = 0; i < N; i++) a[i] = -(i-2)*(i-2);

MPI_Barrier(MPI_COMM_WORLD);

 

MPI_Reduce(a, b, N, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD);

 

if (rank==0) printf("Max=%lf\n",b[0]);

 

MPI_Finalize();

 

return 0;

}



Поделиться:


Последнее изменение этой страницы: 2017-01-20; просмотров: 305; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.15.6.77 (0.161 с.)