next up previous contents
Next: Корректность Up: Функция Scan Previous: Функция Scan   Contents

Примеры использования MPI_SCAN

Пример 4.22 Этот пример построен на пользовательской операции, чтобы выполнить сегментированный просмотр. При сегментированном просмотре на вход принимается множество значений и множество логических величин, логические значения устанавливают различные сегменты для просмотра. Например:


values v$_{1}$ v$_{2}$ v$_{3}$ v$_{4}$ v$_{5}$ v$_{6}$ v$_{7}$ v$_{8}$
logicals 0 0 1 1 1 0 0 1
result v$_{1}$ v$_{1}$+v$_{2}$ v$_{3}$ v$_{3}$+v$_{4}$ v$_{3}$+v$_{4}$+v$_{5}$ v$_{6}$ v$_{6}$+v$_{7}$ v$_{8}$

Оператор, производящий этот эффект


\begin{displaymath}
\left({{\begin{array}{*{20}c}
u \hfill \\
i \hfill \\
\e...
...y}{*{20}c}
w \hfill \\
j \hfill \\
\end{array} }} \right),
\end{displaymath}

где


\begin{displaymath}
w = \left\{ {{\begin{array}{*{20}c}
{u + v} \hfill \\
v \...
...{\mbox{ if i } \ne \mbox{ j}} \hfill \\
\end{array} } \quad .
\end{displaymath}

Отметим, что это некоммутативный оператор. Код на языке Си, реализующий вычисления, представлен ниже.

typedef struct { double val; int log; } SegScanPair; /* функция, определенная пользователем */ void segScan(SegScanPair *in, SegScanPair *inout, int *len, MPI_Datatype *dptr) { int i; SegScanPair c; for (i=0; i< *len; ++i) { if (in->log == inout->log) c.val = in->val + inout->val; else c.val = inout->val; c.log = inout->log; *inout = c; in++; inout++; } }

Заметим, что параметр inout в определяемой пользователем функции соответствует правому операнду оператора. При использовании этого оператора необходимо быть внимательным, чтобы описать, что он некоммутативный, как в следующем листинге.

int i,base; SeqScanPair a, answer; MPI_Op myOp; MPI_Datatype type[2] = {MPI_DOUBLE, MPI_INT}; MPI_Aint disp[2]; int blocklen[2] = { 1, 1}; MPI_Datatype sspair; /* объяснение для MPI, как определяется тип SegScanPair */ MPI_Address(a, disp); MPI_Address(a.log, disp+1); base = disp[0]; for (i=0; i<2; ++i) disp[i] -= base; MPI_Type_struct(2, blocklen, disp, type, &sspair); MPI_Type_commit(&sspair); /* создается пользовательская операция segmented-scan */ MPI_Op_create(segScan, False, &myOp); ... MPI_Scan(a, answer, 1, sspair, myOp, root, comm);



Alex Otwagin 2002-12-10