The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

Каталог документации / Раздел "Программирование, языки" / Оглавление документа
next up previous contents
Next: Рассылка Up: Сборка данных Previous: Сборка данных   Contents

Примеры использования функций MPI_GATHER, MPI_GATHERV

Пример 4.2 Сбор 100 целых чисел с каждого процесса группы в корневой процесс (рис. 4.2).

    MPI_Comm comm;
    int gsize, sendarray[100];
    int root, *rbuf;
    ...
    MPI_Comm_size(comm, &gsize);
    rbuf = (int *)malloc(gsize*100*sizeof(int));
    MPI_Gather(sendarray, 100, MPI_INT, rbuf, 100, MPI_INT, root, comm);

Пример 4.3 Предыдущий пример модифицирован - только корневой процесс выделяет память для буфера приема.

    MPI_Comm comm;
    int gsize,sendarray[100];
    int root, myrank, *rbuf;
    ...
    MPI_Comm_rank(comm, myrank);
    if (myrank == root) {
       MPI_Comm_size(comm, &gsize);
       rbuf = (int *)malloc(gsize*100*sizeof(int));
    }
    MPI_Gather(sendarray, 100, MPI_INT, rbuf, 100, MPI_INT, root, comm);

Пример 4.4. Программа делает то же, что и в предыдущем примере, но использует производные типы данных. Отметим, что тип не может быть полным множеством gsize*100 чисел типа int, поскольку соответствующие типы определены попарно между каждым процессом, участвующим в сборе данных, и корневым процессом.

    MPI_Comm comm;
    int gsize,sendarray[100];
    int root, *rbuf;
    MPI_Datatype rtype;
    ...
    MPI_Comm_size(comm, &gsize);
    MPI_Type_contiguous(100, MPI_INT, &rtype);
    MPI_Type_commit(&rtype);
    rbuf = (int *)malloc(gsize*100*sizeof(int));
    MPI_Gather(sendarray, 100, MPI_INT, rbuf, 1, rtype, root, comm);

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

    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);

Отметим, что программа неверна, если stride < 100.

\includegraphics[width=5.77in,height=2.82in]{Ch4figure3.eps}

Пример 4.6. Со стороны процесса-получателя пример такой же, как и 4.5, но посылается 100 чисел типа int из 0-го столбца C-массива 100x150 чисел типа int (рис. 4.4).

    MPI_Comm comm;
    int gsize,sendarray[100][150];
    int root, *rbuf, stride;
    MPI_Datatype stype;
    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;
    }
    /* Create datatype for 1 column of array
     */
    MPI_Type_vector(100, 1, 150, MPI\_INT, &stype);
    MPI_Type_commit(&stype);
    MPI_Gatherv(sendarray, 1, stype, rbuf, rcounts, displs, MPI_INT, root, 
comm);

\includegraphics[width=5.83in,height=2.99in]{Ch4figure4.eps}

Пример 4.7 Процесс i посылает (100-i) чисел типа int из i-ого столбца C - массива 100x150 чисел типа int на языке Си (рис.4.5)

MPI_Comm comm;
int gsize,sendarray[100][150],*sptr;
int root, *rbuf, stride, myrank;
MPI_Datatype stype;
int *displs,i,*rcounts;
...
MPI_Comm_size(comm, &gsize);
MPI_Comm_rank(comm, &myrank);
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-i;     /* отличие от предыдущего примера */
}
/* создается тип данных для посылаемого столбца */

MPI_Type_vector(100-myrank, 1, 150, MPI_INT, &stype);
MPI_Type_commit(&stype);
/* sptr есть адрес начала  столбца "myrank"
 */
sptr = &sendarray[0][myrank];
MPI_Gatherv(sptr, 1, stype, rbuf, rcounts, displs, MPI_INT,
    root, comm);

Отметим, что из каждого процесса получено различное количество данных.

\includegraphics[width=5.33in,height=2.84in]{Ch4figure5.eps}

Пример 4.8. Пример такой же, как и 4.7, но содержит отличие на передающей стороне. Создается тип данных с корректным страйдом на передающей стороне для чтения столбца массива на языке Си. Подобная вещь была сделана в примере 3.33, раздел 3.12.7.

    MPI_Comm comm;
    int gsize, sendarray[100][150], *sptr;
    int root, *rbuf, stride, myrank, disp[2], blocklen[2];
    MPI_Datatype stype,type[2];
    int *displs,i,*rcounts;
    ...
    MPI_Comm_size(comm, &gsize);
    MPI_Comm_rank(comm, &myrank);
    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-i;
    }
    /* создается тип данных для одного числа типа int с расширением на
         полню строку
     */
    disp[0] = 0;       disp[1] = 150*sizeof(int);
    type[0] = MPI_INT; type[1] = MPI_UB;
    blocklen[0] = 1;   blocklen[1] = 1;
    MPI_Type_struct(2, blocklen, disp, type, &stype);
    MPI_Type_commit(&stype);
    sptr = &sendarray[0][myrank];
    MPI_Gatherv(sptr, 100-myrank, stype, rbuf, rcounts, displs,
    MPI_INT, root, comm);

Пример 4.9 Такой же, как пример 4.7 на передающей стороне, но на приемной стороне устанавливается страйд между принимаемыми блоками, изменяющийся от блока к блоку (рис.4.6).

    MPI_Comm comm;
    int gsize,sendarray[100][150],*sptr;
    int root, *rbuf, *stride, myrank, bufsize;
    MPI_Datatype stype;
    int *displs,i,*rcounts,offset;

    ...

    MPI_Comm_size(comm, &gsize);
    MPI_Comm_rank(comm, &myrank);

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

    /* сначала устанавливаются вектора displs и rcounts
     */
    displs = (int *)malloc(gsize*sizeof(int));
    rcounts = (int *)malloc(gsize*sizeof(int));
    offset = 0;
    for (i=0; i<gsize; ++i) {
        displs[i] = offset;
        offset += stride[i];
        rcounts[i] = 100-i;
    }
    /* теперь легко получается требуемый размер буфера для rbuf
     */
    bufsize = displs[gsize-1]+rcounts[gsize-1];
    rbuf = (int *)malloc(bufsize*sizeof(int));
    /* создается тип данных для посылаемого столбца
     */
    MPI_Type_vector(100-myrank, 1, 150, MPI_INT, &stype);
    MPI_Type_commit(&stype);
    sptr = &sendarray[0][myrank];
    MPI_Gatherv(sptr, 1, stype, rbuf, rcounts, displs, MPI_INT, root, comm);

\includegraphics[width=5.77in,height=2.82in]{Ch4figure7.eps}

\includegraphics[width=5.44in,height=2.78in]{Ch4figure6.eps}

Пример 4.10 В этом примере процесс i посылает num чисел типа int из i-го столбца массива 100x150 чисел типа int на языке Си. Усложнение состоит в том, что различные значения num неизвестны корневому процессу, так что требуется сначала выполнить отдельную операцию gather, чтобы найти их. Данные на приемной стороне размещаются непрерывно.

    MPI_Comm comm;
    int gsize,sendarray[100][150],*sptr;
    int root, *rbuf, stride, myrank, disp[2], blocklen[2];
    MPI_Datatype stype,types[2];
    int *displs,i,*rcounts,num;
    ...
    MPI_Comm_size(comm, &gsize);
    MPI_Comm_rank(comm, &myrank);

    /* снчала собираются nums для root
     */
    rcounts = (int *)malloc(gsize*sizeof(int));
    MPI_Gather(&num, 1, MPI_INT, rcounts, 1, MPI_INT, root, comm);

    /* root теперь имеет правильные rcounts, это позволяет установить
       displs[] так, чтобы данные на приемной стороне размещались
       непрерывно (или на основе конкатенации)
     */
    displs = (int *)malloc(gsize*sizeof(int));
    displs[0] = 0;
    for (i=1; i<gsize; ++i) {
        displs[i] = displs[i-1]+rcounts[i-1];
    }
    /* создается буфер получения
     */
    rbuf = (int *)malloc(gsize*(displs[gsize-1]+rcounts[gsize-1])
    *sizeof(int));
    /* создается тип данных для единственной int с расширением на полную
       строку
     */
    disp[0] = 0;       disp[1] = 150*sizeof(int);
    type[0] = MPI_INT; type[1] = MPI_UB;
    blocklen[0] = 1;   blocklen[1] = 1;
    MPI_Type_struct(2, blocklen, disp, type, &stype);
    MPI_Type_commit(&stype);
    sptr = &sendarray[0][myrank];
    MPI_Gatherv(sptr, num, stype, rbuf, rcounts, displs, MPI_INT,
    root, comm);



Alex Otwagin 2002-12-10



Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру