MPI 发送消息或将其作为参数提供
MPI sending messages or giving them as parameter
我有一个带有一个管理器和多个工作人员的 MPI 实现。main
函数位于名为 run_mpi.cpp
的文件中。它进行 MPI 的初始化并调用 manager.cpp
和 worker.cpp
。我想在worker.cpp
中有一些变量。我有两种方法可以做到这一点:
-
当
main
函数在run_mpi.cpp
中调用它时,我可以将变量作为参数提供给worker.cpp
。 -
我可以在
manager.cpp
中发送带有MPI_Send
或MPI_Isend
的变量。
我可以在什么条件下使用它们?它们有什么好处?
两者视为完全独立的程序。 MPI 在程序的实例(秩(之间提供通信层,但它们之间没有共享数据。 假设您的主节点读取一个包含数字列表的文件,将每个数字发送给工作人员,然后工作人员对该数字执行某些操作。 你可能会有这样的东西:
float localx;
float *x;
int rank;
int size;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,rank);
MPI_Comm_size(MPI_COMM_WORLD,size);
x=new float[size];
if (rank==0)
{
/* Typically, rank 0 is considered the master rank in a master/worker setup
Open, read, and close file.
Assume the data is read into array x, which is single precision floating point.
For ease of illustration, I'm sending to one rank at a time, but this
is better accomplished using MPI_Scatter. */
localx=x[0];
for (int i=1; i<size; i++)
{
MPI_Send(&x[i], 1, MPI_FLOAT, i, i, MPI_COMM_WORLD);
}
master(localx); // The master subroutine does whatever it needs to do
} else
{
// If the rank isn't 0, then the rank is a worker
MPI_Recv(&localx, 1, MPI_FLOAT, 0, rank, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
worker(localx);
}
delete[] x;
前三个 MPI 调用将初始化 MPI 通信环境 (MPI_Init(,获取当前实例的排名号 (MPI_Comm_rank( 和通信器的大小 (MPI_Comm_size(。 MPI_COMM_WORLD的大小是你用mpirun发起的等级。 接下来,分配 x 为每个工作线程保存一个值。
通常,如果您使用的是主/辅助角色模型,则等级 0 将被视为主等级。 因此,如果排名编号为 0,我们将继续读取文件。 作为旁注,除非您使用的是 MPI I/O 或其他并行 I/O,否则只有一个等级访问文件会更安全。 主节点将读取该文件,对于我的示例,该文件的每个工作线程等级应该有一个值。 正如我在评论中所说,使用 MPI_Scatter 是一种更好的方法,但如果您是 MPI 的新手,我们现在将坚持使用基础知识。 首先,我将 localx 设置为 x[0]。 然后,我为每个等级调用MPI_Send一次,向每个等级发送一个 x 元素。 一旦数据被发送出去,主级就可以调用master(localx(并在那里做任何需要做的事情。
如果等级编号不为 0,则等级为工作人员。 工作人员不会读取该文件。 相反,他们将调用MPI_Recv以获取从主服务器发送的数据。 工人队伍将简单地坐在这里等待,直到数据到达。 完成此操作后,工人将调用worker(localx(并在那里执行任何操作。
我见过人们在学习 MPI 时遇到的一大障碍是每个等级的记忆是分开的。 与线程不同,绝对没有共享内存(您的应用程序可以看到,MPI 实现可能会为自己设置一些东西(。 通过分配点,没有一个等级为局部 x 或 x 设置任何值。 主人读完之后,只有主人知道 x 包含什么。 发送数据后,每个工人等级将有一个来自 x 的单个值存储在 localx 中的主节点。
我提到使用MPI_Scatter更好。 这是如何完成的。 条件块之前和之后的所有内容都将保持不变。 条件块将变为:
if (rank==0)
{
// Read the file, fill x
}
MPI_Scatter(&x[0], size, MPI_FLOAT, &localx, 1, MPI_FLOAT, 0, MPI_COMM_WORLD);
if (rank==0)
{
master(localx);
} else
{
worker(localx);
}
不同之处在于,现在,我们不是为每个工人等级发送和接收一次,而是一次将数组分散到每个等级中的变量。 根据您正在执行的操作,可能无法使用MPI_Scatter。 此示例非常简单,您可以。
- 如何反转整数参数包
- 如何通过参数抛出错误消息
- 结构数组的构造函数错误,错误消息:没有构造函数实例与参数列表匹配
- 为什么调用单例类 Qt 消息处理程序成员函数会出现错误:缺少参数列表
- 接受 lambda 作为参数的类方法 - 错误消息
- 如何使用带2个参数的void函数多次打印消息
- C++11 static_assert:参数化错误消息
- 将常量参数作为参数传递时出现神秘的错误消息
- 请帮助消息框不接受参数
- 此错误消息是否正确:非类型模板参数不是常量表达式
- chrome本机消息传递:本机主机可执行文件能否以参数开头
- 在异常构造函数中参数化错误消息是一种好的做法吗
- Poco Logger更改消息参数
- 如何在gcc错误消息中隐藏默认模板参数
- QList 默认参数错误消息(QList 的默认参数<QVariant>具有 int 类型)
- 当我按值传递参数时,c++构建消息显示一个引用参数
- MPI 发送消息或将其作为参数提供
- 获取WM_KEYDOWN消息中lParam参数的第30位
- 发送wm_ncmousmove和WM_SETCURSOR消息.如何填写参数
- 如何从 WndProc 的参数中检索消息发送对象?