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