我试图ISend()
两个数组:arr1,arr2
和整数n
这是arr1,arr2
大小。我从这个post了解到,发送一个包含全部三个结构的结构不是一个选项,因为n
只在运行时才知道。显然,我需要首先接收n
,否则接收过程不知道要接收多少个元素。什么是最有效的方法来实现这一点,而不使用blokcing Send()
?ÇMPI多个动态数组传递
回答
发送阵列的大小是冗余的(且低效的)作为MPI提供了一种探测进入的消息而没有接收它们,这在为了正确地分配存储器仅提供足够的信息。探测执行MPI_PROBE
,看起来很像MPI_RECV
,除了它没有缓冲区相关的参数。探测操作返回一个状态对象,然后可以查询可以从消息内容中提取的给定MPI数据类型的元素数量,其中MPI_GET_COUNT
,因此显式发送元素数量变得多余。
下面是一个简单的例子有两个等级:
if (rank == 0)
{
MPI_Request req;
// Send a message to rank 1
MPI_Isend(arr1, n, MPI_DOUBLE, 1, 0, MPI_COMM_WORLD, &req);
// Do not forget to complete the request!
MPI_Wait(&req, MPI_STATUS_IGNORE);
}
else if (rank == 1)
{
MPI_Status status;
// Wait for a message from rank 0 with tag 0
MPI_Probe(0, 0, MPI_COMM_WORLD, &status);
// Find out the number of elements in the message -> size goes to "n"
MPI_Get_count(&status, MPI_DOUBLE, &n);
// Allocate memory
arr1 = malloc(n*sizeof(double));
// Receive the message. ignore the status
MPI_Recv(arr1, n, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
}
MPI_PROBE
还接受通配符排名MPI_ANY_SOURCE
和通配符标签MPI_ANY_TAG
。然后可以查阅状态结构中的相应条目,以便找出实际的发送者等级和实际的消息标签。
探测消息大小的工作原理是每个消息都带有一个标头,称为包络线。信封由发送者的等级,接收者的等级,消息标签和通信者组成。它还包含有关总邮件大小的信息。信封作为两个通信过程之间的初始握手的一部分发送。
首先,您需要为rank 0的arr1和arr2分配内存(full memory = n = elements),即您的前端处理器。
根据编号将数组分成若干部分。的处理器。确定每个处理器的元件数量。
发送该元件从等级0
第二发送是用于阵列即ARR1算到其它处理器和ARR2
在其它处理器根据从元件主收到的计分配ARR1和ARR2处理器即rank = 0.在接收到元素数后,接收分配的内存中的两个数组。
这是一个示例C++实现,但C将遵循相同的逻辑。也只是交换发送Isend。
#include <mpi.h>
#include <iostream>
using namespace std;
int main(int argc, char*argv[])
{
MPI::Init (argc, argv);
int rank = MPI::COMM_WORLD.Get_rank();
int no_of_processors = MPI::COMM_WORLD.Get_size();
MPI::Status status;
double *arr1;
if (rank == 0)
{
// Setting some Random n
int n = 10;
arr1 = new double[n];
for(int i = 0; i < n; i++)
{
arr1[i] = i;
}
int part = n/no_of_processors;
int offset = n % no_of_processors;
// cout << part << "\t" << offset << endl;
for(int i = 1; i < no_of_processors; i++)
{
int start = i*part;
int end = start + part - 1;
if (i == (no_of_processors-1))
{
end += offset;
}
// cout << i << " Start: " << start << " END: " << end;
// Element_Count
int e_count = end - start + 1;
// cout << " e_count: " << e_count << endl;
// Sending
MPI::COMM_WORLD.Send(
&e_count,
1,
MPI::INT,
i,
0
);
// Sending Arr1
MPI::COMM_WORLD.Send(
(arr1+start),
e_count,
MPI::DOUBLE,
i,
1
);
}
}
else
{
// Element Count
int e_count;
// Receiving elements count
MPI::COMM_WORLD.Recv (
&e_count,
1,
MPI::INT,
0,
0,
status
);
arr1 = new double [e_count];
// Receiving FIrst Array
MPI::COMM_WORLD.Recv (
arr1,
e_count,
MPI::DOUBLE,
0,
1,
status
);
for(int i = 0; i < e_count; i++)
{
cout << arr1[i] << endl;
}
}
// if(rank == 0)
delete [] arr1;
MPI::Finalize();
return 0;
}
谢谢!但你怎么能确定接收没有发生之前发生? – Shmoopy
当您执行Send/Recv时,程序将启动处理器的句柄。 recv句柄等待相应的发送。该程序根据定义的参数(如data_type,no)匹配发送和接收。传递的元素,最重要的是你有一个用户定义的“标签”,它可以帮助映射这些语句。 Irecv/Isend和Recv/Send的唯一区别在于后面的代码会阻止代码的执行直到找到它的匹配部分,而Irecv/Isend放置一个句柄并继续移动到代码的其余部分。 – DOOM
@DOOM,您关于匹配过程的陈述不正确。 MPI只匹配与接收方指定的包络过滤器一起发送的消息信封,并且只包括发件人的等级,标签和通信器。匹配消息时,不会使用数据类型和缓冲区大小。 –
@Histro我想说的是,Irecv/Isend是MPI lib自己操纵的一些函数。你问的问题完全取决于你关于Send/Recv之后你做什么的代码的其余部分。有两种情况:
硕士和工 您发送的问题的一部分(比如数组)的工人(所有其他队伍除了0 =主)。工作人员(在数组上)做了一些工作,然后将结果返回给主人。然后主人将结果加起来,并将新工作传达给工人。现在,在这里您希望主人等待所有工作人员返回他们的结果(修改后的数组)。所以你不能使用Isend和Irecv,而是在我的代码和相应的recv中使用多重发送。如果你的代码在这个方向上,你想使用B_cast和MPI_Reduce。
懒法师 主分工,但不小心从他的工人的结果。假设你想为相同的数据编程一个不同类型的模式。就像给定某个城市的人口特征一样,你想要计算的模式包括18岁以上有多少人,有多少人有工作,有多少人在某些公司工作。现在这些结果与彼此没有任何关系。在这种情况下,您不必担心工作人员是否收到数据。主人可以继续执行其余的代码。这是使用Isend/Irecv安全的地方。
- 1. C++传递一个动态数组到
- 2. 上传和传递动态数组(C++)
- 3. 传递多个动态数组到PHP一些隐藏
- 4. 传递动态数组入参数
- 5. 动态数组传递给函数
- 6. 传递动态数组后,我创建这个动态数组在C
- 7. 动态传递php数组到javascript
- 8. 传递动态数组的功能
- 9. 传递动态数组:空值
- 10. 传递数据反应组件动态
- 11. Vue.js动态组件 - 传递数据
- 12. 传递结构的动态数组C++
- 13. 将动态多维数组的元素传递给一个函数
- 14. 传递一个动态创建的数组作为参数
- 15. 传递一个二维动态数组在C++函数
- 16. 如何动态地将多个参数传递给函数?
- 17. ViewChildren传递多个组件
- 18. 传递多个数组; ajax到webmethod
- 19. 传递一个多维数组在C++
- 20. 传递多个数组来查看
- 21. 将多维数组从一个活动传递到另一个
- 22. 传递动态参数
- 23. 动态传递AJAX参数
- 24. 动态传递参数
- 25. 传递多维数组C++
- 26. Lua传递多维数组
- 27. 传递数组以便在C/C++中动态声明数组
- 28. 如何传递一个动态数组参考c + +
- 29. Pro * C将一个动态数组传递给PL/SQL过程
- 30. 将动态数据传递给Internet Explorer - 创建多个登录
MPI_PROBE块操作吗?我会想象它。 – Shmoopy
@Shmoopy,'MPI_PROBE'是一个阻塞操作。 'MPI_IPROBE'不会阻塞并返回一个布尔标志,指示匹配的消息是否立即可用。 –