diff --git a/MPI-Codes/Collectives/Makefile b/MPI-Codes/Collectives/Makefile new file mode 100755 index 0000000..24f3302 --- /dev/null +++ b/MPI-Codes/Collectives/Makefile @@ -0,0 +1,21 @@ +MPICC = mpicc #The wrapper for the compiler +CC = gcc +CFLAGS += -g #Useful for debug symbols +LDLIBS += -lm + +all: sequentialderiv parallelderiv + +sequentialderiv: sequentialderiv.c + $(CC) $(CFLAGS) $(LDFLAGS) $? $(LDLIBS) -o $@ + +parallelderiv: parallelderiv.c + $(MPICC) $(CFLAGS) $(LDFLAGS) $? $(LDLIBS) -o $@ + +midpointintegral: midpointintegral.c + $(MPICC) $(CFLAGS) $(LDFLAGS) $? $(LDLIBS) -o $@ + +montecarlostyle: montecarlostyle.c + $(MPICC) $(CFLAGS) $(LDFLAGS) $? $(LDLIBS) -o $@ + +clean: + rm -f easysendrecv nonblockingsendrecv sequentialderiv diff --git a/MPI-Codes/Collectives/Solution/Makefile b/MPI-Codes/Collectives/Solution/Makefile new file mode 100755 index 0000000..f5118d3 --- /dev/null +++ b/MPI-Codes/Collectives/Solution/Makefile @@ -0,0 +1,18 @@ +MPICC = mpicc #The wrapper for the compiler +CC = gcc +CFLAGS += -g #Useful for debug symbols +LDLIBS += -lm + +all: parallelderiv midpointintegral montecarlostyle + +parallelderiv: parallelderiv.c + $(MPICC) $(CFLAGS) $(LDFLAGS) $? $(LDLIBS) -o $@ + +midpointintegral: midpointintegral.c + $(MPICC) $(CFLAGS) $(LDFLAGS) $? $(LDLIBS) -o $@ + +montecarlostyle: montecarlostyle.c + $(MPICC) $(CFLAGS) $(LDFLAGS) $? $(LDLIBS) -o $@ + +clean: + rm -f parallelderiv midpointintegral montecarlostyle diff --git a/MPI-Codes/Collectives/Solution/midpointintegral.c b/MPI-Codes/Collectives/Solution/midpointintegral.c new file mode 100755 index 0000000..d0e8e82 --- /dev/null +++ b/MPI-Codes/Collectives/Solution/midpointintegral.c @@ -0,0 +1,43 @@ +#include +#include +#include +#include + +double f( double x); + +int main( int argc, char *argv[]){ +int n, mynode, totalnodes, i; +double PI25DT = 3.141592653589793238462643; +double mypi, pi, h, sum, x; + +MPI_Init(&argc,&argv); +MPI_Comm_size(MPI_COMM_WORLD,&totalnodes); +MPI_Comm_rank(MPI_COMM_WORLD,&mynode); + +if(mynode == 0){ + if(argc != 2){ + n = 20; + }else{ + n = atoi(argv[1]); + } +} +MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); +h = 1.0 / ((double) n*totalnodes); +sum = 0.0; +for (i = 1+mynode*n; i <= n*(mynode+1); i++){ + x = h * ((double)i - 0.5); + sum += f(x); +} +mypi = h*sum; +MPI_Reduce(&mypi, &pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); +if (mynode == 0){ + printf("pi is approximately %.16f, Error is %e\n",pi, fabs(pi - PI25DT)); +} +MPI_Finalize(); +return 0; +} + +double f( double x ) +{ + return (4.0 / (1.0 + x*x)); +} diff --git a/MPI-Codes/Collectives/Solution/montecarlostyle.c b/MPI-Codes/Collectives/Solution/montecarlostyle.c new file mode 100755 index 0000000..64e5622 --- /dev/null +++ b/MPI-Codes/Collectives/Solution/montecarlostyle.c @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include + +int main( int argc, char *argv[]){ + int n, mynode, totalnodes, i; + double PI25DT = 3.141592653589793238462643; + double mypi, pi, h; + double x, y, x1, x2, y1, y2; + int SqPoints, CiPoints, my_SqPoints, my_CiPoints; + unsigned int seed = (unsigned) time(NULL); + + MPI_Init(&argc,&argv); + MPI_Comm_size(MPI_COMM_WORLD,&totalnodes); + MPI_Comm_rank(MPI_COMM_WORLD,&mynode); + + if(mynode == 0){ + if(argc != 2){ + n = 20; + }else{ + n = atoi(argv[1]); + } + } + MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); + + h = 2.0 / (double) totalnodes ; + x1 = -1.0 + mynode * h; + x2 = x1 + h; + y1 = -1.0; + y2 = 1.0; + my_SqPoints = 0; + my_CiPoints = 0; + + for (i = 1; i <= n; i++) + { + srand(seed + mynode); + x = rand_r(&seed); x = x / RAND_MAX; x = x1 + x * (x2 - x1); + y = rand_r(&seed); y = y / RAND_MAX; y = y1 + y * (y2 - y1); + my_SqPoints++; + if ( ( x*x + y*y ) <= 1.0 ) my_CiPoints++; +} +SqPoints = 0; +CiPoints = 0; +MPI_Reduce(&my_SqPoints, &SqPoints, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); +MPI_Reduce(&my_CiPoints, &CiPoints, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); + +if (mynode == 0) +{ + pi = 4.0 * (double)CiPoints / (double)SqPoints; + printf("Pi is approximately %.16f = 4.0 %d/%d, Error is %e (h = %e)\n",pi,CiPoints,SqPoints,fabs(pi - PI25DT),1.0/sqrt( (double) SqPoints) ); +} + +MPI_Finalize(); + +return 0; +} diff --git a/MPI-Codes/Collectives/Solution/parallelderiv.c b/MPI-Codes/Collectives/Solution/parallelderiv.c new file mode 100755 index 0000000..a62bc30 --- /dev/null +++ b/MPI-Codes/Collectives/Solution/parallelderiv.c @@ -0,0 +1,98 @@ +#include +#include +#include +#include "mpi.h" + +void firstderiv1Dp_vec(int n, double dx, double *f,double *fx, int mynode, int totalnodes); + +double fun(double x); +double funprime( double x); + +int main(int argc, char **argv){ + double globala,globalb,a,b,dx,*f,*fx, error; + int n, mynode, totalnodes; + MPI_Status status; + + MPI_Init( &argc, &argv ); + MPI_Comm_rank( MPI_COMM_WORLD, &mynode ); + MPI_Comm_size( MPI_COMM_WORLD, &totalnodes ); + + n = 20; + + globala = 0; + globalb = 1; + + a = globala + ((double) mynode)*(globalb - globala)/( (double) totalnodes); + b = globala + ((double) mynode+1)*(globalb - globala)/( (double) totalnodes); + + f = (double *) malloc(sizeof(double)*(n)); + fx = (double *) malloc(sizeof(double)*(n)); + + dx = (b-a)/((double) n); + for( int i = 0; i < n; i++){ + f[i] = fun(a+((double) i)*dx); + } + firstderiv1Dp_vec( n, dx, f, fx, mynode, totalnodes); + + error = 0.0; + for(int i = 0; i < n; i++){ + error += pow( fx[i]-funprime(a+((b-a)*((double) i))/((double) n)),2.0); + } + error = sqrt(dx*error); + printf("Node %d ||f' - fx||_2 = %e\n",mynode,error); + + + free(f); + free(fx); + MPI_Finalize(); + + return 0; +} + + +void firstderiv1Dp_vec(int n, double dx, double *f,double *fx, int mynode, int totalnodes){ +double scale = 1.0/(2.0*dx); +double mpitemp; +MPI_Status status; + +if(mynode == 0){ + fx[0] = (-3.0*f[0] + 4.0*f[1] - f[2])*scale; +} +if(mynode == (totalnodes-1)){ + fx[n-1] = (3.0*f[n-1] - 4.0*f[n-2] + f[n-3])*scale; +} +for(int i=1;i +#include +#include +#include + +double f( double x); + +int main( int argc, char *argv[]){ +int n, mynode, totalnodes, i; +double PI25DT = 3.141592653589793238462643; +double mypi, pi, h, sum, x; + +MPI_Init(&argc,&argv); +MPI_Comm_size(MPI_COMM_WORLD,&totalnodes); +MPI_Comm_rank(MPI_COMM_WORLD,&mynode); + +if(mynode == 0){ + if(argc != 2){ + n = 20; + }else{ + n = atoi(argv[1]); + } +} +// Broadcast the value to every process + +h = 1.0 / ((double) n*totalnodes); +sum = 0.0; +for (i = 1+mynode*n; i <= n*(mynode+1); i++){ + // compute the local quadrature rule +} +mypi = h * sum; + +// sum all the local sums via reduction + +if (mynode == 0){ + printf("pi is approximately %.16f, Error is %e\n",pi, fabs(pi - PI25DT)); +} +MPI_Finalize(); +return 0; +} + +double f( double x ) +{ + return (4.0 / (1.0 + x*x)); +} diff --git a/MPI-Codes/Collectives/montecarlostyle.c b/MPI-Codes/Collectives/montecarlostyle.c new file mode 100755 index 0000000..7975c20 --- /dev/null +++ b/MPI-Codes/Collectives/montecarlostyle.c @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include + +int main( int argc, char *argv[]){ + int n, mynode, totalnodes, i; + double PI25DT = 3.141592653589793238462643; + double mypi, pi, h; + double x, y, x1, x2, y1, y2; + int SqPoints, CiPoints, my_SqPoints, my_CiPoints; + unsigned int seed = (unsigned) time(NULL); + + MPI_Init(&argc,&argv); + MPI_Comm_size(MPI_COMM_WORLD,&totalnodes); + MPI_Comm_rank(MPI_COMM_WORLD,&mynode); + + if(mynode == 0){ + if(argc != 2){ + n = 20; + }else{ + n = atoi(argv[1]); + } + } + // Broadcast the number of intervals everywhere + + h = 2.0 / (double) totalnodes; + x1 = -1.0 + mynode * h; + x2 = x1 + h; + y1 = -1.0; + y2 = 1.0; + my_SqPoints = 0; + my_CiPoints = 0; + + for (i = 1; i <= n; i++) + { + srand(seed + mynode); + x = rand(&seed); x = x / RAND_MAX; x = x1 + x * (x2 - x1); + y = rand(&seed); y = y / RAND_MAX; y = y1 + y * (y2 - y1); + // do the check on the local Montecarlo Integration : my_SqPoints, my_CiPoints should store + // the number of points into the square, and into the circle (respectively) +} +SqPoints = 0; +CiPoints = 0; + +// Perform reduce operation to put into SqPoints and CiPoints the values + +if (mynode == 0) +{ + pi = 4.0 * (double)CiPoints / (double)SqPoints; + printf("Pi is approximately %.16f = 4.0 %d/%d, Error is %e (h = %e)\n",pi,CiPoints,SqPoints,fabs(pi - PI25DT),1.0/sqrt( (double) SqPoints) ); +} + +MPI_Finalize(); + +return 0; +} diff --git a/MPI-Codes/Collectives/parallelderiv.c b/MPI-Codes/Collectives/parallelderiv.c new file mode 100755 index 0000000..85c76ba --- /dev/null +++ b/MPI-Codes/Collectives/parallelderiv.c @@ -0,0 +1,98 @@ +#include +#include +#include +#include "mpi.h" + +void firstderiv1Dp_vec(int n, double dx, double *f,double *fx, int mynode, int totalnodes); + +double fun(double x); +double funprime( double x); + +int main(int argc, char **argv){ + double globala,globalb,a,b,dx,*f,*fx, error; + int n, mynode, totalnodes; + MPI_Status status; + + MPI_Init( &argc, &argv ); + MPI_Comm_rank( MPI_COMM_WORLD, &mynode ); + MPI_Comm_size( MPI_COMM_WORLD, &totalnodes ); + + n = 20; + + globala = 0; + globalb = 1; + + a = globala + ((double) mynode)*(globalb - globala)/( (double) totalnodes); + b = globala + ((double) mynode+1)*(globalb - globala)/( (double) totalnodes); + + f = (double *) malloc(sizeof(double)*(n)); + fx = (double *) malloc(sizeof(double)*(n)); + + dx = (b-a)/((double) n); + for( int i = 0; i < n; i++){ + f[i] = fun(a+((double) i)*dx); + } + firstderiv1Dp_vec( n, dx, f, fx, mynode, totalnodes); + + error = 0.0; + for(int i = 0; i < n; i++){ + error += pow( fx[i]-funprime(a+((b-a)*((double) i))/((double) n)),2.0); + } + error = sqrt(dx*error); + printf("Node %d ||f' - fx||_2 = %e\n",mynode,error); + + + free(f); + free(fx); + MPI_Finalize(); + + return 0; +} + + +void firstderiv1Dp_vec(int n, double dx, double *f,double *fx, int mynode, int totalnodes){ +double scale = 1.0/(2.0*dx); +double mpitemp; +MPI_Status status; + +if(mynode == 0){ + fx[0] = (-3.0*f[0] + 4.0*f[1] - f[2])*scale; +} +if(mynode == (totalnodes-1)){ + fx[n-1] = (3.0*f[n-1] - 4.0*f[n-2] + f[n-3])*scale; +} +for(int i=1;i +#include +#include + +void firstderiv1D(int n, double a, double b, double *fx); +void firstderiv1D_vec(int n, double dx, double *f, double *fx); +double fun(double x); +double funprime( double x); + +int main(int argc, char **argv){ + double a,b,dx,*f,*fx; + int n; + if(argc != 2){ + n = 20; + }else{ + n = atoi(argv[1]); + } + a = 0.0; + b = 1.0; + f = (double *) malloc(sizeof(double)*n); + fx = (double *) malloc(sizeof(double)*n); + // firstderiv1D(n, a, b, fx); + dx = (b-a)/((double) n); + for( int i = 0; i <= n; i++){ + f[i] = fun(a+((double) i)*dx); + } + firstderiv1D_vec(n, dx, f, fx); + for(int i = 0; i < n; i++){ + printf("fx[%d] = %1.2f f'[%d] = %1.2f |fx - f'| = %1.1e\n", + i,fx[i],i,funprime(a+((b-a)*i)/n),abs(fx[i]- + funprime(a+((b-a)*((double) i))/((double) (n-1))))); + } + + return 1; +} + +void firstderiv1D(int n, double a, double b, double *fx){ + double dx = (b-a)/((double) n-1); + double scale = 1.0/(2.0*dx); + for (int i = 1; i < n-1; i++){ + fx[i] = (fun(a + (i+1)*dx) - fun(a + (i-1)*dx))*scale; + } + fx[0] = (-3.0*fun(a) + 4.0*fun(a + dx) - fun(a + 2.0*dx))*scale; + fx[n-1] = (3.0*fun(a+ (n-1)*dx) - 4.0*fun(a + (n-2)*dx) + fun(a + (n-3)*dx))*scale; + return; +} + +void firstderiv1D_vec(int n, double dx, double *f, double *fx){ + double scale; + scale = 1.0/(2.0*dx); + for (int i = 1; i < n-1; i++){ + fx[i] = (f[i+1] - f[i-1])*scale; + } + fx[0] = (-3.0*f[0] + 4.0*f[1] - f[2])*scale; + fx[n-1] = (3.0*f[n-1] - 4.0*f[n-2] + f[n-3])*scale; + return; +} + +double fun(double x){ + return(x*x + 1); +} + +double funprime( double x){ + return(2*x); +} diff --git a/README.md b/README.md index 979a9c2..c683f44 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,9 @@ Progetto speciale per la didattica dell'Università di Pisa, a.a. 2022/23. - Giovedì 30 Marzo 2023, ore 16.00: Introduzione e uso di GIT - Giovedì 20 Aprile 2023, ore 11.00: Introduzione ad MPI - Venerdì 28 Aprile 2023, ore 11.00: Assemblaggio e prime configurazioni -- Giovedì 4 Maggio 2023, ore 16.00: Configurazione cluster (Slurm&GlusterFS: prime run) +- Giovedì 4 Maggio 2023, ore 16.00: Comunicazioni collettive +- Giovedì 18 Maggio 2023, ore 16.00: Test con il cluster Steffé e uso di Slurm +- Giovedì 25 Maggio 2023, ore 16.00: *Guest lecture*: Prof. S. Filippone Il materiale si trova nella cartella `Slides` del `repository`. diff --git a/Slides/Incontro-4.pdf b/Slides/Incontro-4.pdf new file mode 100644 index 0000000..f769e29 Binary files /dev/null and b/Slides/Incontro-4.pdf differ