我可以将 MPI 与共享内存一起使用吗
Posted
技术标签:
【中文标题】我可以将 MPI 与共享内存一起使用吗【英文标题】:Can I use MPI with shared memory 【发布时间】:2017-02-16 04:16:47 【问题描述】:我编写了一个用于高度并行执行的模拟软件,使用 MPI 进行节点间并行化,线程进行节点内并行化,以通过尽可能使用共享内存来减少内存占用。 (最大的数据结构大多是只读的,所以我可以轻松管理线程安全。)
虽然我的程序运行良好(最终),但我正在重新考虑这种方法是否真的是最好的,主要是因为管理两种类型的并行化确实需要一些杂乱无章的异步代码。
我发现paper (pdf draft) 向 MPI 引入了共享内存扩展,允许在单个节点上的 MPI 并行化中使用共享数据结构。
我对 MPI 不是很有经验,所以我的问题是:最近的标准 Open MPI 实现是否可以做到这一点,我在哪里可以找到关于如何做到这一点的介绍/教程?
请注意,我不是在谈论如何使用共享内存完成消息传递,我知道 MPI 可以做到这一点。我想从多个 MPI 处理器(读取)访问内存中的同一个对象。
【问题讨论】:
【参考方案1】:这是可以做到的——这是一个测试代码,它在每个共享内存节点上设置一个小表。只有一个进程(节点等级 0)实际分配和初始化表,但节点上的所有进程都可以读取它(对格式化道歉 - 似乎是空格/制表符问题)
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
int main(void)
int i, flag;
int nodesize, noderank;
int size, rank, irank;
int tablesize, localtablesize;
int *table, *localtable;
int *model;
MPI_Comm allcomm, nodecomm;
char verstring[MPI_MAX_LIBRARY_VERSION_STRING];
char nodename[MPI_MAX_PROCESSOR_NAME];
MPI_Aint winsize;
int windisp;
int *winptr;
int version, subversion, verstringlen, nodestringlen;
allcomm = MPI_COMM_WORLD;
MPI_Win wintable;
tablesize = 5;
MPI_Init(NULL, NULL);
MPI_Comm_size(allcomm, &size);
MPI_Comm_rank(allcomm, &rank);
MPI_Get_processor_name(nodename, &nodestringlen);
MPI_Get_version(&version, &subversion);
MPI_Get_library_version(verstring, &verstringlen);
if (rank == 0)
printf("Version %d, subversion %d\n", version, subversion);
printf("Library <%s>\n", verstring);
// Create node-local communicator
MPI_Comm_split_type(allcomm, MPI_COMM_TYPE_SHARED, rank,
MPI_INFO_NULL, &nodecomm);
MPI_Comm_size(nodecomm, &nodesize);
MPI_Comm_rank(nodecomm, &noderank);
// Only rank 0 on a node actually allocates memory
localtablesize = 0;
if (noderank == 0) localtablesize = tablesize;
// debug info
printf("Rank %d of %d, rank %d of %d in node <%s>, localtablesize %d\n",
rank, size, noderank, nodesize, nodename, localtablesize);
MPI_Win_allocate_shared(localtablesize*sizeof(int), sizeof(int),
MPI_INFO_NULL, nodecomm, &localtable, &wintable);
MPI_Win_get_attr(wintable, MPI_WIN_MODEL, &model, &flag);
if (1 != flag)
printf("Attribute MPI_WIN_MODEL not defined\n");
else
if (MPI_WIN_UNIFIED == *model)
if (rank == 0) printf("Memory model is MPI_WIN_UNIFIED\n");
else
if (rank == 0) printf("Memory model is *not* MPI_WIN_UNIFIED\n");
MPI_Finalize();
return 1;
// need to get local pointer valid for table on rank 0
table = localtable;
if (noderank != 0)
MPI_Win_shared_query(wintable, 0, &winsize, &windisp, &table);
// All table pointers should now point to copy on noderank 0
// Initialise table on rank 0 with appropriate synchronisation
MPI_Win_fence(0, wintable);
if (noderank == 0)
for (i=0; i < tablesize; i++)
table[i] = rank*tablesize + i;
MPI_Win_fence(0, wintable);
// Check we did it right
for (i=0; i < tablesize; i++)
printf("rank %d, noderank %d, table[%d] = %d\n",
rank, noderank, i, table[i]);
MPI_Finalize();
以下是跨两个节点的 6 个进程的一些示例输出:
Version 3, subversion 1
Library <SGI MPT 2.14 04/05/16 03:53:22>
Rank 3 of 6, rank 0 of 3 in node <r1i0n1>, localtablesize 5
Rank 4 of 6, rank 1 of 3 in node <r1i0n1>, localtablesize 0
Rank 5 of 6, rank 2 of 3 in node <r1i0n1>, localtablesize 0
Rank 0 of 6, rank 0 of 3 in node <r1i0n0>, localtablesize 5
Rank 1 of 6, rank 1 of 3 in node <r1i0n0>, localtablesize 0
Rank 2 of 6, rank 2 of 3 in node <r1i0n0>, localtablesize 0
Memory model is MPI_WIN_UNIFIED
rank 3, noderank 0, table[0] = 15
rank 3, noderank 0, table[1] = 16
rank 3, noderank 0, table[2] = 17
rank 3, noderank 0, table[3] = 18
rank 3, noderank 0, table[4] = 19
rank 4, noderank 1, table[0] = 15
rank 4, noderank 1, table[1] = 16
rank 4, noderank 1, table[2] = 17
rank 4, noderank 1, table[3] = 18
rank 4, noderank 1, table[4] = 19
rank 5, noderank 2, table[0] = 15
rank 5, noderank 2, table[1] = 16
rank 5, noderank 2, table[2] = 17
rank 5, noderank 2, table[3] = 18
rank 5, noderank 2, table[4] = 19
rank 0, noderank 0, table[0] = 0
rank 0, noderank 0, table[1] = 1
rank 0, noderank 0, table[2] = 2
rank 0, noderank 0, table[3] = 3
rank 0, noderank 0, table[4] = 4
rank 1, noderank 1, table[0] = 0
rank 1, noderank 1, table[1] = 1
rank 1, noderank 1, table[2] = 2
rank 1, noderank 1, table[3] = 3
rank 1, noderank 1, table[4] = 4
rank 2, noderank 2, table[0] = 0
rank 2, noderank 2, table[1] = 1
rank 2, noderank 2, table[2] = 2
rank 2, noderank 2, table[3] = 3
rank 2, noderank 2, table[4] = 4
【讨论】:
以上是关于我可以将 MPI 与共享内存一起使用吗的主要内容,如果未能解决你的问题,请参考以下文章