| 4.11 搜索(Scan) |
MPI_SCAN(sendbuf, recvbuf, count, datatype, op, comm)
IN sendbuf 发送消息缓冲区的起始地址(可变)
OUT recvbuf 接收消息缓冲区的起始地址(可变)
IN count 输入缓冲区中元素的个数(整型)
IN datatype 输入缓冲区中元素的类型(句柄)
IN op 操作(句柄)
IN comm 通信子(句柄)
int MPI_Scan(void* sendbuf, void* recvbuf, int count,
MPI_Datatype datatype, MPI_Op op, MPI_Comm comm)
MPI_SCAN(SENDBUF, RECVBUF, COUNT, DATATYPE, OP, COMM, IERROR)
<type> SENDBUF(*), RECVBUF(*)
INTEGER COUNT, DATATYPE, OP, COMM, IERROR
MPI_SCAN常用于对分布于组中的数据作前置归约操作.此操作将序列号为0,... ,i(包括i)的进程发送缓冲区的值的归约结果存入序列号为i 的进程的接收消息缓冲区中,这种操作支持的类型、语义以及对发送及接收缓冲区的限制和MPI_REDUCE相同.
例4.22: 本例用一个用户自定义的操作进行段扫描,一个段扫描将一组值和一组逻辑量作为输入,其中逻辑值将输入分割成不同的段.例如对于以下数据:

操作符产生的结果是:

这里

注意这是一个非交换操作.它的C代码如下:
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);
/* 生成段扫描的用户op */
MPI_Op_create(segScan, False, &myOp);
......
MPI_Scan(a, answer, 1, sspair, myOp, root, comm);
| Copyright: NPACT |