gpt4 book ai didi

c - 打开 MPI Waitall() 段错误

转载 作者:太空宇宙 更新时间:2023-11-04 08:00:11 25 4
gpt4 key购买 nike

我是 MPI 的新手,我正在尝试开发一个非阻塞程序(使用 Isend 和 Irecv)。功能非常基础(具有教育意义):

  • 有一个进程(级别 0)是主进程并从从属进程(级别 1-P)接收消息。主人只接收结果。
  • slaves 生成一组 N 0 到 R 之间的随机数,然后他们用这些数字做一些操作(同样,这只是为了教育目的,操作没有任何意义)
  • 整个过程(操作+发送数据)完成M次(这只是为了比较不同的实现;阻塞和非阻塞)

当我调用 MPI_waitall() 函数时,我在主进程中遇到了段错误

#include <stdio.h>
#include <stdlib.h>
#include "mpi.h"
#include <math.h>
#include <time.h>
#define M 1000 //Number of times
#define N 2000 //Quantity of random numbers
#define R 1000 //Max value of random numbers

double SumaDeRaices (double*);

int main(int argc, char* argv[]) {
int yo; /* rank of process */
int p; /* number of processes */
int dest; /* rank of receiver */

/* Start up MPI */
MPI_Init(&argc, &argv);

/* Find out process rank */
MPI_Comm_rank(MPI_COMM_WORLD, &yo);

/* Find out number of processes */
MPI_Comm_size(MPI_COMM_WORLD, &p);

MPI_Request reqs[p-1];
MPI_Status stats[p-1];

if (yo == 0) {
int i,j;
double result;
clock_t inicio,fin;

inicio = clock();

for(i = 0; i<M; i++){ //M times
for(j = 1; j<p; j++){ //for every slave
MPI_Irecv(&result, sizeof(double), MPI_DOUBLE, j, i, MPI_COMM_WORLD, &reqs[j-1]);
}
MPI_Waitall(p-1,reqs,stats); //wait all slaves (SEG_FAULT)
}
fin = clock()-inicio;

printf("Tiempo total de ejecucion %f segundos \n", ((double)fin)/CLOCKS_PER_SEC);
}
else {
double* numAleatorios = (double*) malloc( sizeof(double) * ((double) N) ); //array with numbers
int i,j;
double resultado;
dest=0;

for(i=0; i<M; i++){ //again, M times
for(j=0; j<N; j++){
numAleatorios[j] = rand() % R ;
}
resultado = SumaDeRaices(numAleatorios);
MPI_Isend(&resultado,sizeof(double), MPI_DOUBLE, dest, i, MPI_COMM_WORLD,&reqs[p-1]); //send result to master
}
}

/* Shut down MPI */
MPI_Finalize();

exit(0);
} /* main */



double SumaDeRaices (double* valores){
int i;
double sumaTotal = 0.0;

//Raices cuadradas de los valores y suma de estos
for(i=0; i<N; i++){
sumaTotal = sqrt(valores[i]) + sumaTotal;
}

return sumaTotal;
}

最佳答案

您的代码存在多个问题。首先也是最重要的是,在您的 Isend 中,您多次传递 &resultado,而无需等到先前的非阻塞操作完成。在确保操作完成之前,您不得重复使用传递给 Isend 的缓冲区。

相反,我建议您使用普通发送,因为与同步发送 (SSend) 相比,普通阻塞发送会在您可以重用缓冲区后立即返回。

其次,不需要使用消息标签。我建议您只将标签设置为 0。就性能而言,它会更快。

第三,结果不应该是一个简单的变量,而是一个大小至少为(p-1)

的数组

第四,如果大小不是已知的小数,我不建议你在堆栈上分配数组,如 MPI_Request 和 MPI_Status。在这种情况下,数组的大小为 (p-1),因此您最好对该数据结构使用 malloc。

第五,如果你不检查状态,使用MPI_STATUSES_IGNORE

此外,您应该指定项目数 (1) 而不是 sizeof(double)

当然,最好的版本就是使用 MPI_Gather。

此外,通常没有理由不在根节点上运行计算。

这里是稍微重写的例子:

#include <stdio.h>
#include <stdlib.h>
#include "mpi.h"
#include <math.h>
#include <time.h>
#define M 1000 //Number of times
#define N 2000 //Quantity of random numbers
#define R 1000 //Max value of random numbers

double SumaDeRaices (double* valores)
{

int i;
double sumaTotal = 0.0;

//Raices cuadradas de los valores y suma de estos
for(i=0; i<N; i++) {
sumaTotal = sqrt(valores[i]) + sumaTotal;
}

return sumaTotal;
}


int main(int argc, char* argv[]) {
int yo; /* rank of process */
int p; /* number of processes */

/* Start up MPI */
MPI_Init(&argc, &argv);

/* Find out process rank */
MPI_Comm_rank(MPI_COMM_WORLD, &yo);

/* Find out number of processes */
MPI_Comm_size(MPI_COMM_WORLD, &p);

double *result;
clock_t inicio, fin;
double *numAleatorios;
if (yo == 0) {
inicio = clock();
}

numAleatorios = (double*) malloc( sizeof(double) * ((double) N) ); //array with numbers
result = (double *) malloc(sizeof(double) * p);

for(int i = 0; i<M; i++){ //M times
for(int j=0; j<N; j++) {
numAleatorios[j] = rand() % R ;
}
double local_result = SumaDeRaices(numAleatorios);
MPI_Gather(&local_result, 1, MPI_DOUBLE, result, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); //send result to master
}

if (yo == 0) {
fin = clock()-inicio;

printf("Tiempo total de ejecucion %f segundos \n", ((double)fin)/CLOCKS_PER_SEC);
}

free(numAleatorios);

/* Shut down MPI */
MPI_Finalize();
} /* main */

关于c - 打开 MPI Waitall() 段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47265060/

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