我是学习MPI的新手,我编写了以下简单程序来执行集成 在Ubuntu 10.10上使用Open MPI的梯形规则。这是代码:
#include <iostream>
#include <mpi.h>
#include <cstdlib>
//function to integrate
double f (double x )
{
return 4.0/(1+x*x);
}
//function which integrates the function defined above on the interval local_a and local_b for a given refinement parameters
double Trap(double local_a , double local_b, int local_n , double h)
{
double integral ;
double x;
integral = ( f(local_a) + f(local_b) )/2.0;
x = local_a ;
for (int i = 1; i < local_n - 1; ++i)
{
x += h;
integral += f(x);
}
integral *= h;
return integral;
}
int main(int argc, char *argv[])
{
int my_rank;
int p;
double a = 0.0;
double b = 1.0;
int n = atoi(argv[1]);//number of subdivisions of the interval
double h;
double local_a;
double local_b;
int local_n;
double integral;
double total;
int source;
int dest = 0;
int tag = 0;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD,&p);//get number pf processes
MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);//get rank
double start , finish;
MPI_Barrier(MPI_COMM_WORLD);
start = MPI_Wtime();
////////////////////////////////////////////////////////////////////////////////////////////////////
h = (b-a)/n;
local_n = n/p;
local_a = a + my_rank*local_n*h;
local_b = local_a + local_n*h;
integral = Trap(local_a , local_b , local_n , h);
if (my_rank==0)
{
total = integral;
for (source = 1; source < p; ++source)
{
MPI_Recv(&integral, 1, MPI_DOUBLE , source , tag , MPI_COMM_WORLD, &status );
total+= integral;
}
}
else
{
MPI_Send(&integral, 1, MPI_DOUBLE, dest, tag , MPI_COMM_WORLD);
}
if (my_rank == 0)
{
printf("With n=%d trapezoids our estimate \n", n );
printf("Of the integral from %f to %f = %f \n" , a ,b , total);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
MPI_Barrier(MPI_COMM_WORLD);
finish = MPI_Wtime();
if(my_rank == 0) std::cout << "Time taken is " << finish - start << std::endl ;
MPI_Finalize();
return 0;
}
正在整合的功能是f(x) = 4.0 / 1+x^2
,当它集成在[0,1]
时会pi = 3.14159...
现在,当我使用不同数量的流程运行程序时,我会得到不同的答案。如下所示,差异非常显着。
Desktop: mpirun -np 1 ./a.out 50000
With n=50000 trapezoids our estimate
Of the integral from 0.000000 to 1.000000 = 3.141553
Time taken is 0.000718832
Desktop:
Desktop:
Desktop: mpirun -np 2 ./a.out 50000
With n=50000 trapezoids our estimate
Of the integral from 0.000000 to 1.000000 = 3.141489
Time taken is 0.000422001
Desktop:
Desktop:
Desktop:
Desktop: mpirun -np 3 ./a.out 50000
With n=50000 trapezoids our estimate
Of the integral from 0.000000 to 1.000000 = 3.141345
Time taken is 0.000365019
Desktop:
Desktop:
Desktop:
Desktop: mpirun -np 4 ./a.out 50000
With n=50000 trapezoids our estimate
Of the integral from 0.000000 to 1.000000 = 3.141362
Time taken is 0.0395319
答案 0 :(得分:4)
您的代码中有两个不同的问题:
1。集成边界取决于MPI流程的数量,并且在p
未划分n
时错误。即,最后一个过程的上限是
a + p * int(n/p) * (b-a)/n
与b
不同。我希望这是你代码中最重要的错误(除非我还没有看到另一个错误)
2。浮点运算既不是关联的也不是可交换的。因此,并行算法的结果将从部分和中汇总,因此将取决于部分和的数量。
答案 1 :(得分:2)
进行浮点运算时,运算顺序很重要。在实数算术中(我的意思是实数的算术)a+b+c+d==a+c+d+b
(以及添加的任何其他顺序)。对于浮点运算,这不一定适用。由于MPI不保证每次浮点行为不确定时都以相同的顺序从M个处理器减少到1个处理器,至少就我们大多数人需要关注而言。
将这一点放在一边,不同数量的处理器上的结果之间的差异确实看起来比我预期的要大。看看你的代码我认为你在这一行使用整数运算:
local_n = n/p;
导致总区域的一小部分未分配给任何计算过程。通过我的计算线
local_b = local_a + local_n*h;
没有为最后一个进程将local_b设置为1.0。