砍猪佩琪 2023-11-21 17:16 采纳率: 33.3%
浏览 84
已结题

mpi共享内存同步问题

我开辟了一片共享内存,然后有多个进程对这篇内存进行写操作,为了保证每个进程的数据保持一致,我使用了一对儿MPI_WIN_FENCE()函数来保证其一致性,但是测试发现,MPI_WIN_FENCE()并不能保证数据一致性,在这片共享内存中有些数据会随机变化,然后我又使用了MPI_WIN_LOCK_ALL与MPI_WIN_UNLOCK_ALL函数,结果仍然会出现随机数。有人知道是什么原因嘛?
伪代码如下:

CALL MPI_Win_allocate_shared(windowsize, disp_unit, MPI_INFO_NULL, MPI_COMM_WORLD, baseptr, win_Zmn, ierr)
  if (ActiveRank /= 0) then
     CALL MPI_Win_shared_query( win_Zmn,  0, windowsize, disp_unit, baseptr,  ierr )
  end if
CALL C_F_POINTER(baseptr,NF_group_pair_1d ,[array_size] )
!以上是开辟共享内存的操作,窗口名为win_Zmn

CALL MPI_WIN_FENCE(0, win_Zmn, ierr)
!此处就是对这篇共享内存进行累加的操作,将各个进程中tmp数组中的值累加到shm_array中
  shm_array(1:5000) = shm_array(1:5000) + tmp(1:5000)
CALL MPI_WIN_FENCE(0, win_Zmn, ierr)

!重复执行以上操作后会发现,shm_array数组中会有一小部分的值随机变化
  • 写回答

13条回答 默认 最新

  • 专家-赤兔[在线] 优质创作者: 编程框架技术领域 2023-11-21 17:16
    关注
    获得0.75元问题酬金

    引自强大而免费的微信小程序:皆我百晓生

    首先,MPI(Message Passing Interface)是一个并行计算的标准库,它通过在不同进程之间传递消息来实现并行计算。MPI中提供了共享内存操作的机制,可以在多个进程间共享同一块内存,但是需要进行同步操作来保证数据的一致性。

    你提到使用了MPI_WIN_FENCE()和MPI_WIN_LOCK_ALL与MPI_WIN_UNLOCK_ALL函数来进行同步操作,但是发现数据仍然会出现随机数。下面我们来分析可能的原因。

    问题原因分析:

    1. 内存操作顺序问题: MPI中共享内存操作需要保证读-修改-写的顺序正确,即首先读取内存中的数据,进行修改,然后再写回内存。如果顺序有误,可能会导致数据一致性问题。
    2. 同步操作不完整: MPI_WIN_FENCE()和MPI_WIN_LOCK_ALL与MPI_WIN_UNLOCK_ALL函数只是提供了一种同步的机制,但并不能保证数据一致性。还需要保证每个进程在对共享内存进行读写操作前都已经完成了上一次的修改。
    3. 数据竞争问题: 如果多个进程同时对共享内存进行写操作,可能会出现数据竞争的情况,导致数据的不确定性。需要使用锁机制来解决数据竞争问题。

    解决方案:

    针对上述问题,推荐你采取以下解决方案:

    1. 正确的内存操作顺序: 确保在进行修改之前先读取共享内存中的数据,然后修改后再写回内存。可以使用tmp数组作为临时变量,将共享内存中的数据拷贝到tmp数组中进行修改后再写回。

      伪代码示例:

      IF (ActiveRank /= 0) THEN
          CALL MPI_Get(tmp, 5000, MPI_INTEGER, 0, 0, 5000, MPI_INTEGER, win_Zmn, ierr)
      END IF
      
      CALL MPI_Win_fence(0, win_Zmn, ierr)
      
      ! 进行累加操作
      tmp(1:5000) = tmp(1:5000) + increment_values
      
      CALL MPI_Win_fence(0, win_Zmn, ierr)
      
      IF (ActiveRank /= 0) THEN
          CALL MPI_Put(tmp, 5000, MPI_INTEGER, 0, 0, 5000, MPI_INTEGER, win_Zmn, ierr)
      END IF
      
    2. 完整的同步操作: 使用MPI_WIN_FENCE()函数对共享内存进行同步操作,并使用MPI_Barrier()函数保证所有进程已经完成上一次共享内存的修改。

      伪代码示例:

      CALL MPI_Win_fence(0, win_Zmn, ierr)
      CALL MPI_Barrier(MPI_COMM_WORLD, ierr)
      
      ! 进行共享内存的操作
      
      CALL MPI_Barrier(MPI_COMM_WORLD, ierr)
      CALL MPI_Win_fence(0, win_Zmn, ierr)
      
    3. 数据竞争的解决: 使用MPI_WIN_LOCK和MPI_WIN_UNLOCK进行共享内存的读写锁定操作,保证同一时间只有一个进程可以对共享内存进行读写操作。

      伪代码示例:

      CALL MPI_Win_lock(MPI_LOCK_SHARED, 0, MPI_MODE_NOCHECK, win_Zmn, ierr)
      
      ! 进行共享内存的操作
      
      CALL MPI_Win_unlock(0, win_Zmn, ierr)
      

    以上是针对共享内存同步问题的解决方案的详细说明。希望对你有帮助!

    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 11月29日
  • 创建了问题 11月21日