The OpenNET Project / Index page

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

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

Функция acumulate

Часто бывает полезным в операции put совместить данные, перемещаемые в процесс-адресат, с данными которые ему принадлежат, вместо того, чтобы выполнять замещение этих данных в процессе-инициаторе. Это позволяет, к примеру, произвести накопление суммы, заставляя все участвующие процессы добавлять свой вклад в переменную для суммирования, расположенную в памяти одного процесса.

MPI_ACCUMULATE(origin_addr, origin_count, origin_datatype,
               target_rank, target_disp, target_count,
               target_datatype, op, win)

IN origin_addr начальный адрес буфера (выбор)  
IN origin_count число записей в буфере инициатора (неотрицательное целое)  
IN origin_datatype тип данных каждой записи в буфере (дескриптор)  
IN target_rank ранг адресата (неотрицательное целое)  
IN target_disp смещение от начала окна до буфера адресата (неотрицательное целое)  
IN target_count число записей в буфере адресата (неотрицательное целое)  
IN target_datatype тип данных каждой записи в буфере адресата (дескриптор)  
IN op уменьшающая операция (дескриптор)  
IN win оконный объект (дескриптор)  

int MPI_Accumulate(void *origin_addr, int origin_count,
                   MPI_Datatype origin_datatype, int target_rank,
                   MPI_Aint target_disp, int target_count,
                   MPI_Datatype target_datatype,
                   MPI_Op op, MPI_Win win)

MPI_ACCUMULATE(ORIGIN_ADDR, ORIGIN_COUNT, ORIGIN_DATATYPE,
               TARGET_RANK, TARGET_DISP, TARGET_COUNT,
               TARGET_DATATYPE, OP, WIN, IERROR)
   <type> ORIGIN_ADDR(*)
   INTEGER(KIND=MPI_ADDRESS_KIND) TARGET_DISP
   INTEGER ORIGIN_COUNT, ORIGIN_DATATYPE,TARGET_RANK,
   TARGET_COUNT, TARGET_DATATYPE, OP, WIN, IERROR

void MPI::Win::Accumulate(const void* origin_addr, int origin_count,
                          const MPI::Datatype& origin_datatype,
                          int target_rank, MPI::Aint target_disp,
                          int target_count,
                          const MPI::Datatype& target_datatype,
                          const MPI::Op& op) const

Данная функция накапливает содержимое буфера инициатора (который определяется параметрами origin_addr, origin_datatype и origin_count) в буфере, определенном аргументами
target_count и target_datatype, по смещению target_disp в окне, определенном при помощи target_rank и win, используя операцию op. Функция похожа на MPI_PUT за исключением того, что данные объединяются в области адресата вместо их перезаписи.

Может использоваться любая из операций, определенных для MPI_REDUCE. Функции, определенные пользователем, использоваться не могут. Например, если op это MPI_SUM, каждый элемент буфера инициатора прибавляется к соответствующему элементу в буфере адресата, замещая предыдущее значение в буфере адресата.

Все аргументы должны иметь либо предопределенный тип данных, либо быть производным типом данных, все базовые компоненты которого являются такими же предопределенными типами данных. Аргументы как инициатора, так и адресата должны быть производными от таких же предопределенных типов. Операция op применяется к элементам этого предопределенного типа. Параметр target_datatype не может определять перекрывающиеся записи, и буфер адресата должен помещаться в окне адресата.

Определяется новая предопределенная операция MPI_REPLACE. Она соответствует ассоциативной функции $f(a,b)=b$; это значит, что данное значение в памяти адресата замещается значением, взятым из памяти инициатора.

Совет разработчикам: В простейшем случае MPI_PUT - это особый случай MPI_ACCUMULATE с операцией MPI_REPLACE. Отметим, тем не менее, что MPI_PUT и MPI_ACCUMULATE имеют разные ограничения на конкурентные обновления. []

Пример 4.3 Мы хотим вычислить $B(j)=\sum_{i:map(i)=j}A(i)$. Массивы A, B и map распределены одинаковым образом. Напишем простую версию.

SUBROUTINE SUM(A, B, map, m, comm, p)
USE MPI
INTEGER m, map(m), comm, p, sizeofreal, win, ierr
REAL A(m), B(m)

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_ACCUMULATE(A(i), 1, MPI_REAL, j, k, 1, MPI_REAL,   &
                      MPI_SUM, win, ierr)
END DO
CALL MPI_WIN_FENCE(0, win, ierr)

CALL MPI_WIN_FREE(win, ierr)
RETURN
END

Этот код идентичен коду в примере 6.2 за исключением того, что вызов get был заменен на вызов accumulate. (Заметим, что если mapLocal возвращает то, что получает, тогда код вычисляет B=A(map^-1), что есть обратное присваивание по отношению к вычисленному в предыдущем примере.) Схожим образом в примере 6.1 мы можем заменить вызов get вызовом accumulate, таким образом, выполняя вычисления только с одним взаимодействием между любыми двумя процессами.



Alex Otwagin 2002-12-10



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

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