Performance 与MPI-2的单边通信

Performance 与MPI-2的单边通信,performance,parallel-processing,mpi,mpi-rma,Performance,Parallel Processing,Mpi,Mpi Rma,考虑以下OpenMP代码片段,它使用中间共享变量在两个线程之间传输私有数据 #pragma omp parallel shared(x) private(a,b) { ... a = somefunction(b); if (omp_get_thread_num() == 0) { x = a; } } #pragma omp parallel shared(x) private(a,b) { if (omp_get_thread_num() == 1)

考虑以下OpenMP代码片段,它使用中间共享变量在两个线程之间传输私有数据

#pragma omp parallel shared(x) private(a,b)
{
    ...
   a = somefunction(b);
   if (omp_get_thread_num() == 0) {
      x = a;
   }
}
#pragma omp parallel shared(x) private(a,b)
{
  if (omp_get_thread_num() == 1) {
    a = x;
  }
  b = anotherfunction(a);
  ...
}
我(在伪代码中)需要使用单边消息传递库将私有数据从一个进程传输到另一个进程。
有什么想法吗?

这是可能的,但其中涉及到更多的“脚手架”——毕竟,您正在潜在的完全不同的计算机之间进行数据通信

这类事情的协调是在可从其他处理器访问的数据窗口之间进行的,并通过锁定/解锁操作来协调对该数据的访问。锁并不是真正意义上的互斥锁,但它们更像是协调对窗口的数据访问的同步点

我现在没有时间详细解释这一点,但下面是一个使用MPI2在没有共享内存的系统中进行共享内存标记的示例:

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

int main(int argc, char** argv)
{
    int rank, size, *a, geta;
    int x;
    int ierr;
    MPI_Win win;
    const int RCVR=0;
    const int SENDER=1;

    ierr = MPI_Init(&argc, &argv);
    ierr |= MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    ierr |= MPI_Comm_size(MPI_COMM_WORLD, &size);

    if (ierr) {
        fprintf(stderr,"Error initializing MPI library; failing.\n");
        exit(-1);
    }

    if (rank == RCVR) {
        MPI_Alloc_mem(sizeof(int), MPI_INFO_NULL, &a);
        *a = 0;
    } else {
        a = NULL;
    }

    MPI_Win_create(a, 1, sizeof(int), MPI_INFO_NULL, MPI_COMM_WORLD, &win);

    if (rank == SENDER) {
        /* Lock recievers window */
        MPI_Win_lock(MPI_LOCK_EXCLUSIVE, RCVR, 0, win);

        x = 5;

        /* put 1 int (from &x) to 1 int rank RCVR, at address 0 in window "win"*/
        MPI_Put(&x, 1, MPI_INT, RCVR, 0, 1, MPI_INT, win);

        /* Unlock */
        MPI_Win_unlock(0, win);
        printf("%d: My job here is done.\n", rank);
    }

    if (rank == RCVR) {
        for (;;) {
            MPI_Win_lock(MPI_LOCK_EXCLUSIVE, RCVR, 0, win);
            MPI_Get(&geta, 1, MPI_INT, RCVR, 0, 1, MPI_INT, win);
            MPI_Win_unlock(0, win);

            if (geta == 0) {
                printf("%d: a still zero; sleeping.\n",rank);
                sleep(2);
            } else
                break;
        }
        printf("%d: a now %d!\n",rank,geta);
        printf("a = %d\n", *a);
    MPI_Win_free(&win);
    if (rank == RCVR) MPI_Free_mem(a);
    MPI_Finalize();

    return 0;
}
#包括
#包括
#包括
#包括“mpi.h”
int main(int argc,字符**argv)
{
整数秩,大小,*a,geta;
int x;
内特里尔;
MPI_Win Win;
常数int RCVR=0;
const int SENDER=1;
ierr=MPI_Init(&argc,&argv);
ierr |=MPI通信等级(MPI通信世界和等级);
ierr |=MPI_通信大小(MPI_通信世界和大小);
如果(ierr){
fprintf(stderr,“初始化MPI库时出错;失败。\n”);
出口(-1);
}
如果(秩==RCVR){
MPI_Alloc_mem(sizeof(int)、MPI_INFO_NULL和a);
*a=0;
}否则{
a=零;
}
MPI_Win_create(a,1,sizeof(int),MPI_INFO_NULL,MPI_COMM_WORLD,&Win);
if(秩==发送方){
/*锁定接收器窗口*/
MPI_Win_lock(MPI_lock_独占,RCVR,0,Win);
x=5;
/*在窗口“win”中的地址0处,将1整数(从&x)放入1整数秩RCVR*/
MPI_Put(&x,1,MPI_INT,RCVR,0,1,MPI_INT,win);
/*解锁*/
MPI_赢_解锁(0,赢);
printf(“%d:我在这里的工作已完成。\n”,秩);
}
如果(秩==RCVR){
对于(;;){
MPI_Win_lock(MPI_lock_独占,RCVR,0,Win);
MPI_-Get(&geta,1,MPI_-INT,RCVR,0,1,MPI_-INT,win);
MPI_赢_解锁(0,赢);
如果(geta==0){
printf(“%d:仍然为零;正在休眠。\n”,秩);
睡眠(2);
}否则
打破
}
printf(“%d:a现在是%d!\n”,排名,geta);
printf(“a=%d\n”,*a);
MPI_Win_免费(&Win);
如果(秩==RCVR)MPI\u Free\u mem(a);
MPI_Finalize();
返回0;
}

这是可能的,但其中涉及到更多的“脚手架”——毕竟,您是在可能完全不同的计算机之间进行数据通信

这类事情的协调是在可从其他处理器访问的数据窗口之间进行的,并通过锁定/解锁操作来协调对该数据的访问。锁并不是真正意义上的锁,而是更像是协调对窗口的数据访问的同步点

我现在没有时间详细解释这一点,但下面是一个使用MPI2在没有共享内存的系统中进行共享内存标记的示例:

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

int main(int argc, char** argv)
{
    int rank, size, *a, geta;
    int x;
    int ierr;
    MPI_Win win;
    const int RCVR=0;
    const int SENDER=1;

    ierr = MPI_Init(&argc, &argv);
    ierr |= MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    ierr |= MPI_Comm_size(MPI_COMM_WORLD, &size);

    if (ierr) {
        fprintf(stderr,"Error initializing MPI library; failing.\n");
        exit(-1);
    }

    if (rank == RCVR) {
        MPI_Alloc_mem(sizeof(int), MPI_INFO_NULL, &a);
        *a = 0;
    } else {
        a = NULL;
    }

    MPI_Win_create(a, 1, sizeof(int), MPI_INFO_NULL, MPI_COMM_WORLD, &win);

    if (rank == SENDER) {
        /* Lock recievers window */
        MPI_Win_lock(MPI_LOCK_EXCLUSIVE, RCVR, 0, win);

        x = 5;

        /* put 1 int (from &x) to 1 int rank RCVR, at address 0 in window "win"*/
        MPI_Put(&x, 1, MPI_INT, RCVR, 0, 1, MPI_INT, win);

        /* Unlock */
        MPI_Win_unlock(0, win);
        printf("%d: My job here is done.\n", rank);
    }

    if (rank == RCVR) {
        for (;;) {
            MPI_Win_lock(MPI_LOCK_EXCLUSIVE, RCVR, 0, win);
            MPI_Get(&geta, 1, MPI_INT, RCVR, 0, 1, MPI_INT, win);
            MPI_Win_unlock(0, win);

            if (geta == 0) {
                printf("%d: a still zero; sleeping.\n",rank);
                sleep(2);
            } else
                break;
        }
        printf("%d: a now %d!\n",rank,geta);
        printf("a = %d\n", *a);
    MPI_Win_free(&win);
    if (rank == RCVR) MPI_Free_mem(a);
    MPI_Finalize();

    return 0;
}
#包括
#包括
#包括
#包括“mpi.h”
int main(int argc,字符**argv)
{
整数秩,大小,*a,geta;
int x;
内特里尔;
MPI_Win Win;
常数int RCVR=0;
const int SENDER=1;
ierr=MPI_Init(&argc,&argv);
ierr |=MPI通信等级(MPI通信世界和等级);
ierr |=MPI_通信大小(MPI_通信世界和大小);
如果(ierr){
fprintf(stderr,“初始化MPI库时出错;失败。\n”);
出口(-1);
}
如果(秩==RCVR){
MPI_Alloc_mem(sizeof(int)、MPI_INFO_NULL和a);
*a=0;
}否则{
a=零;
}
MPI_Win_create(a,1,sizeof(int),MPI_INFO_NULL,MPI_COMM_WORLD,&Win);
if(秩==发送方){
/*锁定接收器窗口*/
MPI_Win_lock(MPI_lock_独占,RCVR,0,Win);
x=5;
/*在窗口“win”中的地址0处,将1整数(从&x)放入1整数秩RCVR*/
MPI_Put(&x,1,MPI_INT,RCVR,0,1,MPI_INT,win);
/*解锁*/
MPI_赢_解锁(0,赢);
printf(“%d:我在这里的工作已完成。\n”,秩);
}
如果(秩==RCVR){
对于(;;){
MPI_Win_lock(MPI_lock_独占,RCVR,0,Win);
MPI_-Get(&geta,1,MPI_-INT,RCVR,0,1,MPI_-INT,win);
MPI_赢_解锁(0,赢);
如果(geta==0){
printf(“%d:仍然为零;正在休眠。\n”,秩);
睡眠(2);
}否则
打破
}
printf(“%d:a现在是%d!\n”,排名,geta);
printf(“a=%d\n”,*a);
MPI_Win_免费(&Win);
如果(秩==RCVR)MPI\u Free\u mem(a);
MPI_Finalize();
返回0;
}

您的代码示例不正确,它是两个连续的并行区域。要共享日期,请使用内存(带锁/互斥锁),不是MPI,它们无论如何都不是连续的,但这一想法是通过单边通信实现相同的功能,而不是使用锁。您的代码之所以正确,是因为与并行区域末尾的连接相关联的隐式内存障碍。如果您融合并行区域,则您的代码需要一个围栏/刷新来进行良好定义。并且nce join还意味着一个障碍,这段代码无论如何都没有意义。您将免费获得变量共享和同步。有关OpenMP中正确的消息传递示例,请参阅并行研究内核synch_p2p OpenMP实现。您的代码示例不正确,它是两个连续的并行区域。若要共享日期,请使用内存(带锁/互斥锁)不是MPI,它们无论如何都是不连续的,但这个想法是通过单边通信实现相同的功能,而不是通过锁。您的代码之所以正确,是因为隐式内存限制