next up previous contents
Next: Функция acumulate Up: Коммуникационные вызовы Previous: Get   Contents

Примеры

Пример 6.1 Мы показываем, как реализовать общее присваивание A=B(map), где у A, B и map распределены одинаковым образом, и map является перестановочным вектором.

Для простоты, мы рассмотрим блочное распределение с блоками одинакового размера.

SUBROUTINE MAPVALS(A, B, map, m, comm, p) USE MPI INTEGER m, map(m), comm, p REAL A(m), B(m) INTEGER otype(p), oindex(m), & ! Используется для построения типов данных инициатора ttype(p), tindex(m), & ! Используется для построения типов данных адресата count(p), total(p), & sizeofreal, win, ierr ! Эта часть делает работу, которая зависит от расположения B. ! Может многократно использоваться, пока расположение не изменяется CALL MPI_TYPE_EXTENT(MPI_REAL, sizeofreal, ierr) CALL MPI_WIN_CREATE(B, m*sizeofreal, sizeofreal, MPI_INFO_NULL, & comm, win, ierr) ! Эта часть делает работу, которая зависит от значения MAP и ! расположения массивов. ! Может многократно использоваться, пока те не изменяются ! Вычисляет число записей, которые будут получены от каждого процесса DO i=1,p count(i) = 0 END DO DO i=1,m j = map(i)/m+1 count(j) = count(j)+1 END DO total(1) = 0 DO i=2,p total(i) = total(i-1) + count(i-1) END DO DO i=1,p count(i) = 0 END DO ! Вычисляет origin и target индексы записей. ! Запись i в данном процессе получена из позиции ! k в процессе (j-1), где map(i) = (j-1)*m + (k-1), ! j = 1..p и k = 1..m DO i=1,m j = map(i)/m+1 k = MOD(map(i),m)+1 count(j) = count(j)+1 oindex(total(j) + count(j)) = i tindex(total(j) + count(j)) = k END DO ! Создает типы данных инициатора и адресата для каждой операции GET DO i=1,p CALL MPI_TYPE_INDEXED_BLOCK(count(i), 1, oindex(total(i)+1), & MPI_REAL, otype(i), ierr) CALL MPI_TYPE_COMMIT(otype(i), ierr) CALL MPI_TYPE_INDEXED_BLOCK(count(i), 1, tindex(total(i)+1), & MPI_REAL, ttype(i), ierr) CALL MPI_TYPE_COMMIT(ttype(i), ierr) END DO ! Эта часть непосредственно выполняет присваивание CALL MPI_WIN_FENCE(0, win, ierr) DO i=1,p CALL MPI_GET(A, 1, otype(i), i-1, 0, 1, ttype(i), win, ierr) END DO CALL MPI_WIN_FENCE(0, win, ierr) CALL MPI_WIN_FREE(win, ierr) DO i=1,p CALL MPI_TYPE_FREE(otype(i), ierr) CALL MPI_TYPE_FREE(ttype(i), ierr) END DO RETURN END

Пример 4.2 Можно написать более простую версию, которая не требует, чтобы для буфера адресата создавался тип данных с использованием отдельного вызова get для каждого элемента. Этот код гораздо проще, но обычно менее эффективен для больших массивов.

SUBROUTINE MAPVALS(A, B, map, m, comm, p) USE MPI INTEGER m, map(m), comm, p REAL A(m), B(m) INTEGER sizeofreal, win, ierr CALL MPI_TYPE_EXTENT(MPI_REAL, sizeofreal, ierr) CALL MPI_WIN_CREATE(B, m*sizeofreal, sizeofreal, & MPI_INFO_NULL, comm, win, ierr) CALL MPI_WIN_FENCE(0, win, ierr) DO i=1,m j = map(i)/p k = MOD(map(i),p) CALL MPI_GET(A(i), 1, MPI_REAL, j, k, 1, MPI_REAL, & win, ierr) END DO CALL MPI_WIN_FENCE(0, win, ierr) CALL MPI_WIN_FREE(win, ierr) RETURN END



Alex Otwagin 2002-12-10