我正在尝试并行化向量的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(分段故障)。”
我认为分散存在问题,但我不知道是什么。
感谢您的帮助
答案 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()
!