Algorithm Implementation of MPI Trapezoidal Integral Method (C Language)


foreword

Requirements: Realize the scattered MPI trapezoidal integration algorithm in the textbook as a complete MPI program, and compile, debug, debug, run, and optimize in a distributed environment. Then summarize the learning experience and write an experiment report.
Tip: When the MPI program is started, the executable file of the program will start and run on each node, so all the variables in the program are local private variables; when communicating between processes, there must be a one-to-one correspondence between sending and receiving. Whether it is received or not sent will cause the program to freeze.


1. Experiment code

code show as below:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <mpi.h> 
double Trap(double left_endpt, double right_endpt, double trap_count, double base_len);
double f(double x);
void Get_data(int my_rank,int comm_sz,double* a,double* b,int* n);
int main(void)
{
    
    
    int my_rank = 0, comm_sz = 0, n, local_n = 0;
    double a , b , h , local_a = 0, local_b = 0;
    double local_int = 0, total_int = 0;
    int source;
    MPI_Init(NULL,NULL);
    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
    MPI_Comm_size(MPI_COMM_WORLD, &comm_sz);
	  Get_data(my_rank,comm_sz,&a,&b,&n);

    h = (b - a) / n;           
local_n = n / comm_sz; 
    local_a = a + my_rank*local_n*h;
    local_b = local_a + local_n*h;
    local_int = Trap(local_a, local_b, local_n, h);

    if (my_rank != 0)
    {
    
    
        MPI_Send(&local_int, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
    }
    else
    {
    
    
        total_int = local_int;
        for (source = 1; source < comm_sz; source++)
        {
    
    
            MPI_Recv(&local_int, 1, MPI_DOUBLE, source, 0,
                MPI_COMM_WORLD, MPI_STATUS_IGNORE);
            total_int += local_int;
        }
    }

    if (my_rank == 0)
    {
    
    
        printf("With n = %d trapezoids, our estimate\n", n);
        printf("of the integral from %f to %f = %.15e\n", a, b, total_int);
        
    }
    MPI_Finalize();
    return 0;
}

double Trap(double left_endpt, double right_endpt, double trap_count, double base_len)
{
    
    
    double estimate = 0, x = 0;
    int i;

    estimate = (f(left_endpt) + f(right_endpt)) / 2.0;
    for (i = 1; i <= trap_count - 1; i++)
    {
    
    
        x = left_endpt + i*base_len;
        estimate += f(x);
    }
    estimate = estimate*base_len;
    return estimate;
}

double f(double x)
{
    
    
    return x;
}
void Get_data(int my_rank,int comm_sz,double* a,double* b,int* n)
{
    
    
if (my_rank == 0) {
    
    
		printf("Enter a, b, and n \n");
		scanf("%lf %lf %d", a, b, n);
		for (int i = 1; i < comm_sz; i++) {
    
    
			MPI_Send(a, 1, MPI_DOUBLE, i, 0, MPI_COMM_WORLD);
			MPI_Send(b, 1, MPI_DOUBLE, i, 0, MPI_COMM_WORLD);
			MPI_Send(n, 1, MPI_INT, i, 0, MPI_COMM_WORLD);
		}
	}
	else {
    
    
		MPI_Recv(a, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, MPI_STATUSES_IGNORE);
		MPI_Recv(b, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, MPI_STATUSES_IGNORE);
		MPI_Recv(n, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUSES_IGNORE);
	}

}

2. Experimental operation effect

insert image description here

3. Problems and thoughts

Question 1: The input function frequently reports errors.
Solution: It is wrong to pass the parameters after inspection, change the type of the passed parameters, and also change the definition of the functions of MPI_Send and MPI_Rev.
Question 2: There is an error in the return value of the function for calculating the trapezoidal integral.
Solution: Set the function type to double, and accept the returned value as double
to realize one-to-one correspondence.
Question 3: There is still room for further optimization.
Solution: Next, the broadcast method will be used to transmit the input data to each core.
Question 4: The experimental results are not accurate when the value of n is relatively small.
Solution: It is related to the algorithm idea. Changing the value of n will make it closer to the correct value, but when the value of n is larger, the result will not be accurate enough, which is related to the calculation accuracy of floating point numbers.
(This is unavoidably related to the calculation accuracy of floating-point numbers. I thought about it for a long time at the time, but I didn’t expect it to be a problem that I thought about myself. I have to be more careful, but I haven’t touched distributed for a long time now. I miss o(╥﹏╥)o)


Summarize

In this experiment, I experienced the idea of ​​evenly distributing tasks in a parallel program, each core is executed separately and then output by a designated core. Each core independently undertakes a part of the task, and then summarizes the calculation results. At the same time, each core calculates It is necessary to consider the size of the task to be allocated (the trapezoidal integral method can be directly and evenly distributed because the calculation amount is similar), parallel programs are more difficult to implement than ordinary serial ideas, but because they greatly improve the performance of the machine, they are extremely Great learning significance, especially the realization process of the trapezoidal integral method all reflects this idea.
insert image description here
Come and have a bite when you are tired from studying O(∩_∩)O haha~

Guess you like

Origin blog.csdn.net/weixin_51759592/article/details/125987421