Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Пособие по MPI (реферат).doc
Скачиваний:
61
Добавлен:
28.06.2014
Размер:
124.42 Кб
Скачать

--------------------------------------------------

5. Пример использования mpi_Bcast

Broadcast - передача сообщения от одного процесса ко всем остальным процессам группы, включая его самого. Схематически broadcast можно изобразить следующим образом:

int MPI_Bcast(void *buff, int count, MPI_Datatype datatype, int root, MPI_Comm comm), где

  • buff - адрес начала буфера, хранящего передаваемое сообщение

  • count - количество передаваемых элементов

  • datatype - тип передаваемых элементов

  • root - номер корневого процесса, т.е. номер процесса от которого будет передаваться сообщение всем остальным процессам

  • comm - идентификатор группы

Пример. Каждый неrootпроцесс в буфереsbufхранит строку "I am not root", аroot-процесс кладет себе в буферsbufстроку "Hello from root" и рассылает ее при помощиMPI_Bcastвсем остальным. В результате, у каждого неrootпроцесса в буфере оказывается именно это сообщение.

# include <mpi.h>

# include <stdio.h>

# include <string.h>

int main(int argc, char** argv)

{

int numtasks, rank, root;

char sbuf[20];

strcpy(sbuf, "I am not root\0");

root = 1;

MPI_Init(&argc,&argv);

MPI_Comm_size(MPI_COMM_WORLD, &numtasks);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

if(rank == root) strcpy(sbuf, "Hello from root\0");

MPI_Bcast(sbuf, 16, MPI_CHAR, root, MPI_COMM_WORLD);

if(rank == root) strcpy(sbuf, "I am root\0");

printf("I am %d. Message received: %s\n", rank, sbuf);

MPI_Finalize();

return 0;

}

Результат выполнения программы на 5 процессах:

I am 0. Message received: Hello from root

I am 3. Message received: Hello from root

I am 4. Message received: Hello from root

I am 1. Message received: I am root

I am 2. Message received: Hello from root

--------------------------------------------------------------------------

6. Пример использования mpi_Gatherv и mpi_Scatterv

Функция MPI_Gatherv:

int MPI_Gatherv (void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int *recvcnts, int *displs, MPI_Datatype recvtype, int root, MPI_Comm comm), где

  • sendbuf - Адрес, по которому находятся отправляемые данные

  • sendcount - Число отправляемых данных (в каждом процессе — свое)

  • sendtype - Тип отправляемых данных

  • recvcounts - Целочисленный массив размера, равного числу процессов в коммуникаторе; каждый элемент этого массива содержит число элементов, принимаемых от процесса с рангом, равным номеру этого элемента.

  • displs - Целочисленный массив размера, равного числу процессов в коммуникаторе. i-тый элемент определяет смещение (в элементах) относительно адреса recvbuf, по которому разместить данные, приходящие от процесса с рангом i. (имеет значение только в процессе с рангомroot)

  • recvtype - Тип принимаемых данных (имеет значение только в процессе с рангом root)

  • root - ранг процесса, который принимает данные.

  • comm-communicator(handle)

  • OUTrecvbuf- Адрес, по которому принимаются данные. (имеет значение только в процессе с рангомroot)

Пример. Здесь каждый процесс посылает 100 чисел типа int корневому процессу, но каждое множество (100 элементов) размещается с некоторым шагом (stride) относительно конца размещения предыдущего множества. Чтобы получить этот эффект нужно использовать MPI_GATHERV и аргумент displs. Полагаем, что stride > 100.

MPI_Comm comm;

int gsize,sendarray[100];

int root, *rbuf, stride;

int *displs,i,*rcounts;

...

MPI_Comm_size(comm, &gsize);

rbuf = (int *)malloc(gsize*stride*sizeof(int));

displs = (int *)malloc(gsize*sizeof(int));

rcounts = (int *)malloc(gsize*sizeof(int));

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

displs[i] = i*stride;

rcounts[i] = 100;

}

MPI_Gatherv(sendarray, 100, MPI_INT, rbuf, rcounts, displs,

MPI_INT, root, comm);

Функция MPI_Scatterv:

MPI_SCATTERV(sendbuf, sendcounts, displs, sendtype, recvbuf, recvcount, ecvtype, root, comm)

IN

sendbuf

адрес буфера посылки (альтернатива, используется только корневым процессом)

IN

sendcounts

целочисленный массив (размера группы), определяющий число элементов, для отправки каждому процессу

IN

displs

целочисленный массив (размера группы). Элемент i указывает смещение (относительно sendbuf, из которого берутся данные для процесса take the i)

IN

sendtype

тип элементов посылающего буфера (дескриптор)

OUT

recvbuf

адрес принимающего буфера (альтернатива)

IN

recvcount

число элементов в посылающем буфере (целое)

IN

recvtype

тип данных элементов принимающего буфера (дескриптор)

IN

root

номер посылающего процесса (целое)

IN

comm

коммуникатор (дескриптор)

Пример.Корневой процесс рассылает множества из 100 чисел типа int остальным процессам, но множества размещены в посылающем буфере с шагом stride, поэтому нужно использовать MPI_Scatterv. Полагаем stride > 100.

MPI_Comm comm;

int gsize,*sendbuf;

int root, rbuf[100], i, *displs, *scounts;

...

MPI_Comm_size(comm, &gsize);

sendbuf = (int*)malloc(gsize*stride*sizeof(int));

...

displs = (int*)malloc(gsize*sizeof(int));

scounts = (int*)malloc(gsize*sizeof(int));

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

displs[i] = i*stride;

scounts[i] = 100;

}

MPI_Scatterv(sendbuf, scounts, displs, MPI_INT, rbuf, 100,

MPI_INT, root, comm);

9