gpt4 book ai didi

c - 使用 MPI_Isend 和 MPI_Irecv 而不是 MPI_Bcast 为所有处理器定时广播消息

转载 作者:行者123 更新时间:2023-12-04 10:38:14 24 4
gpt4 key购买 nike

我有一个项目,我需要使用 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 运行它时,我只得到一个处理器的时间,但我不太确定为什么。我想我只是不明白这些功能是如何工作的,或者我应该如何使用它们。

谢谢你的帮助!

最佳答案

您的代码中存在一些不同的问题,所有这些问题都可能导致它崩溃或行为异常:

  • 正如@Olaf 已经提到的,在堆栈上分配数组mydata 是一个非常糟糕的主意。对于这么大的数组,您绝对应该通过显式调用 malloc() 在堆上进行分配。即便如此,您还是在这里使用了一些严重的内存块,因此请注意不要耗尽计算机上的可用内存。此外,某些 MPI 库难以处理大小大于 2GB 的消息,您的情况就是如此。因此,请再次注意这一点。
  • 您将 mydata 用于发送和接收目的。但是,一旦您发布了非阻塞通信,您在通信完成之前不能重复使用相应的消息。因此,在您的情况下,您需要两个数组,一个用于发送,一个用于接收。
  • 您传递给 MPI 调用的数据类型,即 MPI_BYTE,与您传输的实际数据类型,即 float 不一致。您应该改用 MPI_FLOAT
  • 您调用了 MPI_Irecv()MPI_Isend() 而没有调用任何有效的 MPI_Wait()MPI_Test() 功能。这是错误的,因为这意味着通信可能永远不会发生。
  • MPI_Wtime() 返回一个 double,而不是一个 int。这不是错误本身,但它可能会导致意外结果。此外,您在调用 printf() 时请求的格式对应于 float 据,而不是整数,因此您必须使其连贯。
  • (轻微错别字)您错过了 MPI_Finalize()()
  • (次要 - 我猜)您只与进程 #0 通信...

所以这是一些可能的工作代码版本:

#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;
}

注意:为了让代码在所有情况下都能正常工作,我在这里实现了一个通信环,进程 0 发送到进程 1 并从进程 size-1 接收......但是,在你重新的上下文中广播的实现,您可以忽略它(即 fromto 参数)。

关于c - 使用 MPI_Isend 和 MPI_Irecv 而不是 MPI_Bcast 为所有处理器定时广播消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33028121/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com