MPI_Fetch_and_op的一致性

问题描述 投票:0回答:1

我试图通过一个小例子来理解MPI函数`MPI_Fetch_and_op()并遇到我想理解的奇怪行为。

在示例中,等级为0的过程一直等待,直到过程1..4在执行之前各自将结果值增加1。

[在函数0中使用断言的默认值MPI_Win_lock_all(),有时我(10之1)会遇到无限循环,即将MASTER中result[0]的值更新为3。终端输出类似于以下代码片段:

result: 3
result: 3
result: 3
...

根据文档,功能MPI_Fetch_and_op是原子的。

此操作相对于其他“累加”是原子的操作。

第一个问题:为什么不将result[0]的值更新为4?


如果我将assert的值更改为MPI_MODE_NOCHECK,则似乎可行

第二个问题:为什么使用MPI_MODE_NOCHECK

根据文档,我认为这意味着互斥必须以不同的方式组织。有人可以解释MPI_Win_lock_all()文档中的段落吗?

MPI_MODE_NOCHECK

在调用方持有窗口锁的同时,没有其他进程持有或将尝试获取冲突的锁。这在以下情况下很有用互斥是通过其他方式实现的,但是连贯性锁定和解锁调用可能附带的操作仍然必填。

提前感谢!

示例程序:

#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>

#define MASTER 0

int main(int argc, char *argv[])
{
  MPI_Init(&argc, &argv);
  MPI_Comm comm = MPI_COMM_WORLD;
  int r, p;
  MPI_Comm_rank(comm, &r);
  MPI_Comm_size(comm, &p);
  printf("Hello from %d\n", r);
  int result[1] = {0};
  //int assert = MPI_MODE_NOCHECK;
  int assert = 0;
  int one = 1;
  MPI_Win win_res;
  MPI_Win_allocate(1 * sizeof(MPI_INT), sizeof(MPI_INT), MPI_INFO_NULL, comm, &result[0], &win_res);
  MPI_Win_lock_all(assert, win_res);
  if (r == MASTER) {
    result[0] = 0;
    do{
      MPI_Fetch_and_op(&result, &result , MPI_INT, r, 0, MPI_NO_OP, win_res);  
      printf("result: %d\n", result[0]);
    } while(result[0] != 4);
    printf("Master is done!\n");
  } else {
    MPI_Fetch_and_op(&one, &result, MPI_INT, 0, 0, MPI_SUM, win_res);
  }
  MPI_Win_unlock_all(win_res);
  MPI_Win_free(&win_res);
  MPI_Finalize();
  return 0;
}

与以下Makefile一起编译:

MPICC = mpicc
CFLAGS = -g -std=c99 -Wall -Wpedantic -Wextra

all: fetch_and

fetch_and: main.c
    $(MPICC) $(CFLAGS) -o $@ main.c

clean:
    rm fetch_and

run: all
    mpirun -np 5 ./fetch_and
c mpi mutual-exclusion mpi-rma
1个回答
0
投票

您的代码对我有用,没有变化。请注意:

  • 您在测试result[0] != 4中硬编码了进程数
  • 您已将主值硬编码为MPI_Fetch_and_op(&one, &result, MPI_INT, 0
  • 传递与更新和结果相同的地址对我来说似乎很危险:MPI_Fetch_and_op(&result, &result
  • 而且我的编译器抱怨第一个参数,因为它实际上是一个int**(实际上是int (*)[1]
  • 我不确定为什么您在第二个参数上没有收到相同的投诉,
  • ...。但是无论如何我都不满意第二个参数,因为获取操作会将您指定为窗口缓冲区的内容写入内存。我想这里缺乏连贯性可以节省您的时间。
  • 您用result[0] = 0;初始化了窗口,但我认为这与窗口不一致,所以再次,您可能很幸运。

好,所以这是很多情况,比理想的编程还少。不过,在我的设置中它仍然有效。但是您可能需要稍微清理一下代码。-我认为MPI_Win_allocate(1 * sizeof(MPI_INT), sizeof(MPI_INT), MPI_INFO_NULL, comm, &result[0]也会造成某种内存损坏,因为result是此处的输出,但它是静态分配的数组。

© www.soinside.com 2019 - 2024. All rights reserved.