如何分散然后使用MPI和c ++减少

时间:2017-11-28 17:26:01

标签: c++ mpi

我正在尝试并行化向量的norm2(可变大小)的计算。我的方法是首先分散处理器中的向量,计算每个子向量的平方和总和,然后减少重新分配并应用平方根。

这是我的代码:

#include <mpi.h>
#include <vector>
#include <iostream>
#include <cmath>

double SquareSum(std::vector<double> & v) {

double res;

for (std::vector<double>::iterator it = v.begin(); it != v.end(); it++){
    if (*it){
        res += (*it)*(*it);
    }
    else{
        it++;
    }
}

return res;
}




int main(int argc, char *argv[]){

std::vector<double> numbers;
double val;
while (std::cin >> val) numbers.push_back(val);



MPI_Init(&argc,&argv);

int rank, size;

MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);

unsigned numbers_count = numbers.size();

MPI_Bcast(&numbers_count, 1, MPI_UNSIGNED, 0, MPI_COMM_WORLD);

unsigned local_share = numbers_count / size; // local_share is the floor function of numbers.size() / number of process


if (numbers_count % size > 0){
    ++local_share;  // if size is not a multiple of numbers.size() add 1 to local_share in order to make it "fit"
}

if (rank == 0){ 
numbers.resize(local_share*size); //resize numbers by adding null empty spot if necessary
}

//std::cout << "I'm" << rank << std::endl;
std::vector<double> local(local_share);

MPI_Scatter(&numbers, local_share, MPI_DOUBLE, &local, local_share, MPI_DOUBLE, 0, MPI_COMM_WORLD);

double par_sum = SquareSum(local);

double sum = 0;


MPI_Reduce(&par_sum, &sum, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);

if (rank == 0){

    std::cout << "norm : " << std::sqrt(sum);
}
MPI_Finalize();
return 0;
}

当我尝试执行程序时出现此错误:

“mpiexec注意到节点笔记本电脑上的PID 9823进程等级2退出信号11(分段故障)。”

我认为分散存在问题,但我不知道是什么。

感谢您的帮助

1 个答案:

答案 0 :(得分:0)

除了@Hristo Iliev的评论:

numbers的大小可能不是大小的倍数。然后,local_share变为numbers_count % size+1。它用作每个流程按MPI_Scatter()检索的部分的大小。因此,散射矢量的大小必须为(numbers_count % size+1)*size。由于提供的向量numbers可能太小,程序会尝试加入超出边界的元素,从而触发未定义的行为,例如分段错误。

两种解决方案:

  • 推回零直到numbers.size()%size==0。它修改了向量,这对于将来的使用是不实用的,而且相当丑陋。
  • 使用MPI_Scatterv()