我有一个项目,我需要使用MPI_Isend和MPI_Irecv计算任何错误的MPI_Bcast实现,并将其与MPI_Bcast进行比较。因为这些程序的时间是0.000000秒,我需要使用一个大型数组(正如我所做的那样)。我的代码中还没有的是for循环和MPI_Irecv / Isend函数应该在循环中以使程序花费大量的时间来完成。
这是我的代码,我将在下面讨论我遇到的问题:
#include <stdio.h>
#include <string.h>
#include <mpi.h>
int main(int argc, char **argv) {
int a = 1000000000;
int i, N;
int Start_time, End_time, Elapse_Time;
int proc_rank, partner, world_size;
MPI_Status stat;
float mydata[a];
MPI_Request request;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD, &proc_rank);
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
Start_time = MPI_Wtime();
for (i = 0; i < a; i++) {
mydata[i] = 0.2567*i;
}
MPI_Irecv(mydata, a, MPI_BYTE, 0, 1, MPI_COMM_WORLD, &request);
MPI_Isend(mydata, a, MPI_BYTE, 0, 1, MPI_COMM_WORLD, &request);
End_time = MPI_Wtime();
Elapse_Time = End_time - Start_time;
printf("Time on process %d is %f Seconds.\n", proc_rank, Elapse_Time);
MPI_Finalize;
return 0;
}
当我使用命令mpirun -np 4 ./a.out
运行时,我只得到一个处理器的时间,但我不确定为什么。我想我只是不了解这些功能是如何工作的,或者我应该如何使用它们。
感谢您的帮助!
答案 0 :(得分:3)
您的代码中存在一些不同的问题,所有这些问题都可能导致崩溃或行为异常:
mydata
是一个非常糟糕的主意。对于这么大的数组,你肯定应该在堆上进行分配,并显式调用malloc()
。即便如此,你在这里玩的是一些严重的记忆,所以要小心不要耗尽机器上可用的东西。此外,一些MPI库难以处理大小超过2GB的消息,这是您的情况。所以再次注意这一点。mydata
作为发送和接收目的。但是,一旦您发布了非阻止通信,在通信完成之前无法重复使用相应的消息。因此,在您的情况下,您需要两个阵列,一个用于发送,一个用于接收。MPI_BYTE
,与您传输的数据的实际类型(即float
不一致。您应该使用MPI_FLOAT
代替。MPI_Irecv()
或MPI_Isend()
函数,即可致电MPI_Wait()
和MPI_Test()
。这是错误的,因为这意味着通信可能永远不会发生。MPI_Wtime()
返回double
,而不是int
。这不是本身的错误,但可能会导致意外结果。此外,调用printf()
时请求的格式对应于浮点数据,而不是整数,因此您必须使其一致。()
的{{1}}。所以这是一个可行的工作代码版本:
MPI_Finalize()
注意:为了让代码在所有情况下工作,我在这里实现了一个通信环,进程0发送到进程1并从进程大小-1接收...但是,在你的重新上下文中实现广播,您可以忽略这一点(即#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <mpi.h>
int main(int argc, char **argv) {
int a = 1000000000;
int i, from, to;
double Start_time, End_time, Elapse_Time;
int proc_rank, world_size;
float *mysenddata, *myrecvdata;
MPI_Request requests[2];
MPI_Init( &argc, &argv );
MPI_Comm_rank( MPI_COMM_WORLD, &proc_rank );
MPI_Comm_size( MPI_COMM_WORLD, &world_size );
Start_time = MPI_Wtime();
mysenddata = (float*) malloc( a * sizeof( float ) );
myrecvdata = (float*) malloc( a * sizeof( float ) );
assert( mysenddata != NULL ); /*very crude sanity check */
assert( myrecvdata != NULL ); /*very crude sanity check */
for ( i = 0; i < a; i++ ) {
mysenddata[i] = 0.2567 * i;
}
from = ( proc_rank + world_size - 1 ) % world_size;
to = ( proc_rank + 1 ) % world_size;
MPI_Irecv( myrecvdata, a, MPI_FLOAT, from, 1, MPI_COMM_WORLD, &requests[0] );
MPI_Isend( mysenddata, a, MPI_FLOAT, to, 1, MPI_COMM_WORLD, &requests[1] );
MPI_Waitall( 2, requests, MPI_STATUSES_IGNORE );
End_time = MPI_Wtime();
Elapse_Time = End_time - Start_time;
printf( "Time on process %d is %f Seconds.\n", proc_rank, Elapse_Time );
free( mysenddata );
free( myrecvdata );
MPI_Finalize();
return 0;
}
和from
参数)。
答案 1 :(得分:0)
我看到的唯一解释是你的另一个进程在打印之前崩溃了。尝试将代码的某些部分放在注释中并重新执行代码。
尝试这种方式,看看你是否看到差异
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD, &proc_rank);
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
/*Start_time = MPI_Wtime();
for (i = 0; i < a; i++) {
mydata[i] = 0.2567*i;
}
MPI_Irecv(mydata, a, MPI_BYTE, 0, 1, MPI_COMM_WORLD, &request);
MPI_Isend(mydata, a, MPI_BYTE, 0, 1, MPI_COMM_WORLD, &request);
End_time = MPI_Wtime();
Elapse_Time = End_time - Start_time;*/
printf("I'm process %d.\n", proc_rank);
MPI_Finalize;