The OpenNET Project / Index page

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

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

Примеры

Следующие примеры демонстрируют использование производных типов данных

Пример 3.30 Передача и прием секции 3D массива.

      REAL a(100,100,100), e(9,9,9)
      INTEGER oneslice, twoslice, threeslice, sizeofreal, myrank,
              ierr
      INTEGER status(MPI_STATUS_SIZE)

C      извлекает секцию a(1:17:2, 3:11, 2:10)
C      и запоминает ее в e(:,:,:).

      CALL MPI_COMM_RANK(MPI_COMM_WORLD, myrank)

      CALL MPI_TYPE_EXTENT(MPI_REAL, sizeofreal, ierr)

C     создает тип данных для секции 1D
      CALL MPI_TYPE_VECTOR(9, 1, 2, MPI_REAL, oneslice, ierr)

C     создает тип данных для секции 2D
      CALL MPI_TYPE_HVECTOR(9, 1, 100*sizeofreal, oneslice, twoslice,
                             ierr)

C     создает тип данных для секции в целом
      CALL MPI_TYPE_HVECTOR(9, 1, 100*100*sizeofreal, twoslice,
                             threeslice, ierr)

      CALL MPI_TYPE_COMMIT(threeslice, ierr)
      CALL MPI_SENDRECV(a(1,3,2), 1, threeslice, myrank, 0, e, 9*9*9,
                        MPI_REAL, myrank, 0, MPI_COMM_WORLD, status,
                        ierr)

Пример 3.31 Копирование (строгое) нижней треугольной части матрицы

      REAL a(100,100), b(100,100)
      INTEGER  disp(100), blocklen(100), ltype, myrank, ierr
      INTEGER status(MPI_STATUS_SIZE)

C     копирует нижнюю треугольную часть массива a
C     в нижнюю треугольную часть массива b

      CALL MPI_COMM_RANK(MPI_COMM_WORLD, myrank)
 
C     вычисляет начало и размер каждого столбца 
      DO i=1, 100 
        disp(i) = 100*(i-1) + i 
        block(i) = 100-i 
      END DO 
 
C     создает тип данных для нижней треугольной части 
      CALL MPI_TYPE_INDEXED(100, block, disp, MPI_REAL, ltype, ierr) 
 
      CALL MPI_TYPE_COMMIT(ltype, ierr) 
      CALL MPI_SENDRECV(a, 1, ltype, myrank, 0, b, 1, 
                    ltype, myrank, 0, MPI_COMM_WORLD, status, ierr)

Пример 3.32 Транспонирование матрицы.

      REAL a(100,100), b(100,100)
      INTEGER row, xpose, sizeofreal, myrank, ierr
      INTEGER status(MPI_STATUS_SIZE)

C     транспонирование матрицы  a в матрицу b

      CALL MPI_COMM_RANK(MPI_COMM_WORLD, myrank)

      CALL MPI_TYPE_EXTENT(MPI_REAL, sizeofreal, ierr)

C     создание типа данных для одной строки
      CALL MPI_TYPE_VECTOR(100, 1, 100, MPI_REAL, row, ierr)

C     создание типа данных для матрицы с расположением по строкам
      CALL MPI_TYPE_HVECTOR(100, 1, sizeofreal, row, xpose, ierr)

      CALL MPI_TYPE_COMMIT(xpose, ierr)

C     посылка матрицы с расположением по строкам и получение матрицы
С     с расположением по столбцам
      CALL MPI_SENDRECV(a, 1, xpose, myrank, 0, b, 100*100,
                MPI_REAL, myrank, 0, MPI_COMM_WORLD, status, ierr)

Пример 3.33 Другой подход к проблеме транспонирования:

      REAL a(100,100), b(100,100)
      INTEGER  disp(2), blocklen(2), type(2), row, row1, sizeofreal
      INTEGER  myrank, ierr
      INTEGER status(MPI_STATUS_SIZE)

      CALL MPI_COMM_RANK(MPI_COMM_WORLD, myrank)

C     транспонирование матрицы a в матрицу b

      CALL MPI_TYPE_EXTENT(MPI_REAL, sizeofreal, ierr)

C     создание типа данных для одной строки
      CALL MPI_TYPE_VECTOR(100, 1, 100, MPI_REAL, row, ierr)

C     создание типа данных для одной строки
      disp(1) = 0
      disp(2) = sizeofreal
      type(1)  = row
      type(2)  = MPI_UB
      blocklen(1)  = 1
      blocklen(2)  = 1
      CALL MPI_TYPE_STRUCT(2, blocklen, disp, type, row1, ierr)

      CALL MPI_TYPE_COMMIT(row1, ierr)

C     посылка 100 строк и получение с расположением по столбцам
      CALL MPI_SENDRECV(a, 100, row1, myrank, 0, b, 100*100,
                MPI_REAL, myrank, 0, MPI_COMM_WORLD, status, ierr)

Пример 3.34 Манипуляция с массивом структур.

struct Partstruct
   {
   int    class;  /* класс частицы */
   double d[6];   /* координаты частицы */
   char   b[7];   /* некоторая дополнительная информация */
   };

struct Partstruct    particle[1000];

int                  i, dest, rank;
MPI_Comm     comm;


/* построение типа данных описываемой структуры */

MPI_Datatype Particletype;
MPI_Datatype type[3] = {MPI_INT, MPI_DOUBLE, MPI_CHAR};
int          blocklen[3] = {1, 6, 7};
MPI_Aint     disp[3];
int          base;


/* вычисление смещений элементов структуры */

MPI_Address(particle, disp);
MPI_Address(particle[0].d, disp+1);
MPI_Address(particle[0].b, disp+2);
base = disp[0];
for (i=0; i <3; i++) disp[i] -= base;

MPI_Type_struct(3, blocklen, disp, type, &Particletype);

MPI_Datatype type1[4] = {MPI_INT, MPI_DOUBLE, MPI_CHAR, MPI_UB};
int          blocklen1[4] = {1, 6, 7, 1};
MPI_Aint     disp1[4];

/* вычисление смещений элементов структуры */

MPI_Address(particle, disp1);
MPI_Address(particle[0].d, disp1+1);
MPI_Address(particle[0].b, disp1+2);
MPI_Address(particle+1, disp1+3);
base = disp1[0];
for (i=0; i <4; i++) disp1[i] -= base;

/* построение типа данных описываемой структуры */

MPI_Type_struct(4, blocklen1, disp1, type1, &Particletype);


              /* 4.1:
        посылка массива целиком */

MPI_Type_commit(&Particletype);
MPI_Send(particle, 1000, Particletype, dest, tag, comm);


              /* 4.2:
        посылка только элементов класса нулевых частиц, предваряемых
        количеством таких элементов */

MPI_Datatype Zparticles;   /* тип данных, описывающий все частицы
                             класса нуль (необходимо повторное
                             вычисление , если класс изменяется) */
MPI_Datatype Ztype;

MPI_Aint     zdisp[1000];
int zblock[1000], j, k;
int zzblock[2] = {1,1};
MPI_Aint     zzdisp[2];
MPI_Datatype zztype[2];

/* вычисление смещений класса нулевых частиц */
j = 0;
for(i=0; i < 1000; i++)
  if (particle[i].class==0)
     {
     zdisp[j] = i;
     zblock[j] = 1;
     j++;
     } 
 
/* создание типа данных для класса нулевых частиц */ 
MPI_Type_indexed(j, zblock, zdisp, Particletype, &Zparticles); 
 
/* количество частиц */ 
MPI_Address(&j, zzdisp); 
MPI_Address(particle, zzdisp+1); 
zztype[0] = MPI_INT; 
zztype[1] = Zparticles; 
MPI_Type_struct(2, zzblock, zzdisp, zztype, &Ztype); 
 
MPI_Type_commit(&Ztype); 
MPI_Send(MPI_BOTTOM, 1, Ztype, dest, tag, comm); 
 
 
       /* возможно более эффективный путь определения Zparticles */ 
 
/* последовательные частицы с индексом нуль обрабатываются как один блок */ 
j=0; 
for (i=0; i < 1000; i++) 
  if (particle[i].index==0) 
    { 
    for (k=i+1; (k < 1000)&&(particle[k].index == 0) ; k++); 
    zdisp[j] = i;
    zblock[j] = k-i;
    j++; 
    i = k; 
    } 
MPI_Type_indexed(j, zblock, zdisp, Particletype, &Zparticles); 
 
 
                /* 4.3: 
          посылка первых двух координат всем элементам */ 
 
MPI_Datatype Allpairs;      /* datatype for all pairs of coordinates */ 
 
MPI_Aint sizeofentry; 
 
MPI_Type_extent(Particletype, &sizeofentry); 
 
     /* размер элемента также может быть вычислен  вычитанием адреса
        particle[0] из адреса particle[1] */
 
MPI_Type_hvector(1000, 2, sizeofentry, MPI_DOUBLE, &Allpairs); 
MPI_Type_commit(&Allpairs); 
MPI_Send(particle[0].d, 1, Allpairs, dest, tag, comm); 
 
      /* альтернативное решение для  4.3 */ 
 
MPI_Datatype Onepair;   /* тип данных для одной пары координат */ 
MPI_Aint disp2[3]; 
MPI_Datatype type2[3] = {MPI_LB, MPI_DOUBLE, MPI_UB}; 
int blocklen2[3] = {1, 2, 1}; 
 
MPI_Address(particle, disp2); 
MPI_Address(particle[0].d, disp2+1); 
MPI_Address(particle+1, disp2+2); 
base = disp2[0]; 
for (i=0; i<2; i++) disp2[i] -= base; 
 
MPI_Type_struct(3, blocklen2, disp2, type2, &Onepair); 
MPI_Type_commit(&Onepair); 
MPI_Send(particle[0].d, 1000, Onepair, dest, tag, comm);

Пример 3.35 Те же манипуляции, как и в предыдущем примере, но с использованием абсолютных адресов в типах данных.

struct Partstruct
   {
   int class;
   double d[6];
   char b[7];
   };

struct Partstruct particle[1000];

        /* строится тип данных, описывающий первый элемент массива */

MPI_Datatype Particletype;
MPI_Datatype type[3] = {MPI_INT, MPI_DOUBLE, MPI_CHAR};
int          block[3] = {1, 6, 7};
MPI_Aint     disp[3];
 
MPI_Address(particle, disp); 
MPI_Address(particle[0].d, disp+1); 
MPI_Address(particle[0].b, disp+2); 
MPI_Type_struct(3, block, disp, type, &Particletype); 
 
/* тип частицы описывает первый элемент массива - используя
 абсолютные адреса  */ 
 
                  /* 5.1: 
            посылка массива целиком */ 
 
MPI_Type_commit(&Particletype); 
MPI_Send(MPI_BOTTOM, 1000, Particletype, dest, tag, comm); 
 
 
                 /* 5.2: 
         посылка элементов класса нуль, 
         предваряемых числом таких элементов  */ 
 
MPI_Datatype Zparticles, Ztype; 
 
MPI_Aint zdisp[1000] 
int zblock[1000], i, j, k; 
int zzblock[2] = {1,1}; 
MPI_Datatype zztype[2];
MPI_Aint     zzdisp[2]; 
 
j=0; 
for (i=0; i < 1000; i++) 
  if (particle[i].index==0) 
    { 
    for (k=i+1; (k < 1000)&&(particle[k].index = 0) ; k++); 
    zdisp[j] = i; 
    zblock[j] = k-i; 
    j++; 
    i = k; 
    } 
MPI_Type_indexed(j, zblock, zdisp, Particletype, &Zparticles); 

/* Zparticles описывают частицы класса нуль, 
   используя их абсолютные адреса*/

/* количество частиц */ 
MPI_Address(&j, zzdisp); 
zzdisp[1] = MPI_BOTTOM; 
zztype[0] = MPI_INT; 
zztype[1] = Zparticles; 
MPI_Type_struct(2, zzblock, zzdisp, zztype, &Ztype); 
 
MPI_Type_commit(&Ztype); 
MPI_Send(MPI_BOTTOM, 1, Ztype, dest, tag, comm);

Пример 3.36 Обработка объединений (unions).

union { 
   int     ival; 
   float   fval; 
      } u[1000] 
 
int     utype;
 
/* все элементы  uмеют идентичный тип; переменная 
   utype хранит трек их текущего типа */
 
MPI_Datatype   type[2]; 
int            blocklen[2] = {1,1}; 
MPI_Aint       disp[2]; 
MPI_Datatype   mpi_utype[2]; 
MPI_Aint       i,j; 
 
/* вычисляет тип данных MPI для каждого возможного типа union; 
 считаем, что значения в памяти union выровнены по левой границе. */
 
MPI_Address(u, &i); 
MPI_Address(u+1, &j); 
disp[0] = 0; disp[1] = j-i; 
type[1] = MPI_UB; 
 
type[0] = MPI_INT;
MPI_Type_struct(2, blocklen, disp, type, &mpi_utype[0]);
 
type[0] = MPI_FLOAT; 
MPI_Type_struct(2, blocklen, disp, type, &mpi_utype[1]); 
 
for(i=0; i<2; i++) MPI_Type_commit(&mpi_utype[i]); 
 
/* фактический обмен */ 
 
MPI_Send(u, 1000, mpi_utype[utype], dest, tag, comm);



Alex Otwagin 2002-12-10



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

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