Commit 3604dfae01896fa69a8327b313cf2f5da11bc4c1

Authored by kmazouzi
1 parent 2b4ce206b0
Exists in master

MPI version

Showing 4 changed files with 451 additions and 63 deletions Side-by-side Diff

lab3/Makefile View file @ 3604dfa
... ... @@ -2,20 +2,24 @@
2 2 CFLAGS = -O3 -fopenmp
3 3 OMP_FLAG = -fopenmp
4 4 RM = rm -rf
  5 +MPI = mpicc
  6 +MPI_FLAG = -O1 -g
  7 +EXE = omp_heat2D ser_heat2D mpi_heat2D
5 8  
6   -
7   -EXE = omp_heat2D ser_heat2D
8   -
9 9 all : $(EXE)
10 10  
11 11 #.PHONY: all clean purge
12 12  
13 13  
14   -pi_ser: ser_heat2D.o
  14 +ser_heat2D: ser_heat2D.o
15 15 $(GCC) $(CFLAGS) -o $@ $^
16 16  
17   -pi_task: omp_heat2D.o
  17 +omp_heat2D: omp_heat2D.o
18 18 $(GCC) $(CFLAGS) -o $@ $^
  19 +
  20 +mpi_heat2D:
  21 + $(MPI) $(MPI_FLAG) mpi_heat2D.c -o $@
  22 +
19 23  
20 24  
21 25 %.o :%.c
lab3/mpi_heat2D.c View file @ 3604dfa
  1 +/****************************************************************************
  2 + * DESCRIPTION:
  3 + * Serial HEAT2D Example - C Version
  4 + * This example is based on a simplified
  5 + * two-dimensional heat equation domain decomposition. The initial
  6 + * temperature is computed to be high in the middle of the domain and
  7 + * zero at the boundaries. The boundaries are held at zero throughout
  8 + * the simulation. During the time-stepping, an array containing two
  9 + * domains is used; these domains alternate between old data and new data.
  10 + *
  11 + * The physical region, and the boundary conditions, are suggested
  12 + by this diagram;
  13 +
  14 + u = 0
  15 + +------------------+
  16 + | |
  17 + u = 100 | | u = 100
  18 + | |
  19 + | |
  20 + | |
  21 + | |
  22 + +------------------+
  23 + u = 100
  24 +
  25 +Interrior point :
  26 + u[Central] = (1/4) * ( u[North] + u[South] + u[East] + u[West] )
  27 +
  28 +
  29 +PARALLEL MPI VERSION :
  30 +
  31 + +-------------------+
  32 + | | P0 m=(n-2)/P +2
  33 + +-------------------+
  34 + | | P1
  35 + +-------------------+
  36 + n | | ..
  37 + +-------------------+
  38 + | | Pq
  39 + +-------------------+
  40 +
  41 + <-------- n -------->
  42 + <-------n-2 ------>
  43 +
  44 +
  45 + ****************************************************************************/
  46 +#include <stdio.h>
  47 +#include <stdlib.h>
  48 +#include <math.h>
  49 +#include <mpi/mpi.h>
  50 +#define NN 50
  51 +#define MM 50
  52 +
  53 +#define RING 100
  54 +#define ITER_PRINT 100
  55 +#define PRINT_DATA 1
  56 +#define MAX_ITER 1000
  57 +#define _EPSILON 0.01
  58 +
  59 +
  60 +float update(int rank,int size, int nx,int ny, float *u, float *unew);
  61 +void inidat(int rank, int size, int nx, int ny, float *u, float *unew);
  62 +void prtdat(int rank, int size, int nx, int ny, float *u,const char *fnam);
  63 +
  64 +
  65 +
  66 +
  67 +int main(int argc, char *argv[])
  68 +{
  69 + int N=NN,M=MM;
  70 +
  71 + int rank,size;
  72 +
  73 + float EPSILON=_EPSILON;
  74 +
  75 +
  76 + /* INITIALIZE MPI */
  77 + MPI_Init(&argc, &argv);
  78 +
  79 + /* GET THE PROCESSOR ID AND NUMBER OF PROCESSORS */
  80 + MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  81 + MPI_Comm_size(MPI_COMM_WORLD, &size);
  82 +
  83 + //Only Rank 0 read application parameters
  84 + if(rank==0) {
  85 +
  86 + if(argc !=3)
  87 + {
  88 + fprintf(stderr,"usage %s N EPSILON\n ", argv[0]);
  89 + fprintf(stderr,"\t\twhere N is GRID size, EPSILON is Tolerance\n");
  90 + fprintf(stderr,"\t\texample N = 100, EPSILON = 0.1\n");
  91 + return -1;
  92 + }
  93 +
  94 + N = M = atoi(argv[1]);
  95 + EPSILON = atof(argv[2]);
  96 +
  97 + if(N % size!=0)
  98 + {
  99 + fprintf(stderr,"Grid Size MUST be divisible by the number of processors !");
  100 + return -1;
  101 + }
  102 +
  103 + }
  104 +
  105 + //Wait for rank 0 , all process start here
  106 + MPI_Barrier(MPI_COMM_WORLD);
  107 +
  108 + //Exchange N
  109 + MPI_Bcast(&N , 1, MPI_FLOAT, 0 , MPI_COMM_WORLD);
  110 + //Exchange EPSILON
  111 + MPI_Bcast(&EPSILON , 1, MPI_FLOAT, 0 , MPI_COMM_WORLD);
  112 +
  113 + //local size
  114 + M = (N-2)/size + 2;
  115 +
  116 + float *u = (float *)malloc(N * M * sizeof(float));
  117 + float *unew = (float *)malloc(N * M * sizeof(float));
  118 +
  119 + if(u==0 || unew ==0)
  120 + {
  121 + perror("Can't allocated data\n");
  122 + return -1;
  123 + }
  124 +
  125 + if(rank==0) {
  126 +
  127 + printf ( "\n" );
  128 + printf ( "HEATED_PLATE\n" );
  129 + printf ( " Parallel MPI version using %d processors \n",size );
  130 + printf ( " A program to solve for the steady state temperature distribution\n" );
  131 + printf ( " over a rectangular plate.\n" );
  132 + printf ( "\n" );
  133 + printf ( " Spatial grid of %d by %d points.\n", N, N );
  134 + printf ( " Each processor will use grid of %d +2 by %d points.\n", M-2, N );
  135 + printf ( " The iteration will end until tolerance <= %f\n\n",EPSILON);
  136 +
  137 + }
  138 +
  139 + /* Initialize grid and create input file
  140 + * each process initialize its part
  141 + * */
  142 +
  143 + inidat(rank,size,M,N,u,unew);
  144 +
  145 + prtdat(rank,size,M,N,u, "initial.dat");
  146 +
  147 +
  148 + /*
  149 + * iterate until the new solution unew differs from the old solution u
  150 + * by no more than EPSILON.
  151 + * */
  152 +
  153 + float diff=1.0;
  154 + int iter=0;
  155 +
  156 + while(diff> EPSILON) {
  157 +
  158 + diff= update(rank,size,M,N, u, unew);
  159 +
  160 + if(rank==0)
  161 + if(iter%ITER_PRINT==0)
  162 + printf("Processor #%d, iteration %d, epsilon = %f\n ", rank,iter,diff);
  163 + iter++;
  164 + }
  165 +
  166 + prtdat(rank,size,M,N, u, "final.dat");
  167 + free(u);
  168 + free(unew);
  169 + MPI_Finalize();
  170 +}
  171 +
  172 +
  173 +
  174 +/****************************************************************************
  175 + * subroutine update
  176 + ****************************************************************************/
  177 +float update(int rank, int size, int nx,int ny, float *u, float *unew){
  178 + int ix, iy;
  179 + float diff=0.0;
  180 + float globaldiff;
  181 + MPI_Status status;
  182 +
  183 +
  184 + /*
  185 + * EXCHANGE GHOST CELL
  186 + */
  187 + if (rank > 0 && rank< size-1)
  188 + {
  189 + MPI_Sendrecv(&u[ny*(nx-2)], ny, MPI_FLOAT, rank+1, 0,
  190 + &u[ny*0], ny, MPI_FLOAT, rank-1, 0, MPI_COMM_WORLD, &status);
  191 + MPI_Sendrecv(&u[ny*1], ny, MPI_FLOAT, rank-1, 1,
  192 + &u[ny*(nx-1)], ny, MPI_FLOAT, rank+1, 1, MPI_COMM_WORLD, &status);
  193 + }
  194 +
  195 + else if (rank == 0 && rank< size-1)
  196 + MPI_Sendrecv(&u[ny*(nx-2)], ny, MPI_FLOAT, rank+1, 0,
  197 + &u[ny*(nx-1)], ny, MPI_FLOAT, rank+1, 1, MPI_COMM_WORLD, &status);
  198 + else if ( rank> 0 && rank == size-1)
  199 + MPI_Sendrecv(&u[ny*1], ny, MPI_FLOAT, rank-1, 1,
  200 + &u[ny*0], ny, MPI_FLOAT, rank-1, 0, MPI_COMM_WORLD, &status);
  201 +
  202 +
  203 +
  204 + /**
  205 + * PERFORM LOCAL COMPUTATION
  206 + * */
  207 +
  208 + for (ix = 1; ix < nx-1; ix++) {
  209 + for (iy = 1; iy < ny-1; iy++) {
  210 + unew[ix*ny+iy] = (u[(ix+1)*ny+iy] + u[(ix-1)*ny+iy] + u[ix*ny+iy+1] + u[ix*ny+iy-1] )/4.0
  211 + ;
  212 + if (diff < fabs (unew[ix*ny+iy] - u[ix*ny+iy] ))
  213 + {
  214 + diff = fabs ( unew[ix*ny+iy] - u[ix*ny+iy] );
  215 + }
  216 + }
  217 +
  218 + }
  219 +
  220 +
  221 + /**
  222 + * COMPUTE GLOBAL CONVERGENCE
  223 + *
  224 + * */
  225 +
  226 + MPI_Allreduce(&diff, &globaldiff , 1, MPI_FLOAT, MPI_MAX, MPI_COMM_WORLD);
  227 +
  228 +
  229 + /**
  230 + * COPY OLD DATA
  231 + * */
  232 +
  233 +
  234 + for (ix = 1; ix < nx-1; ix++) {
  235 + for (iy = 1; iy < ny-1; iy++) {
  236 + u[ix*ny+iy] = unew[ix*ny+iy];
  237 + }
  238 + }
  239 +
  240 +
  241 + return globaldiff;
  242 +}
  243 +
  244 +/*****************************************************************************
  245 + * Initialize Data
  246 + *****************************************************************************/
  247 +
  248 +void inidat(int rank, int size,int nx, int ny, float *u, float *unew)
  249 +{
  250 + int ix, iy;
  251 +
  252 + /*
  253 + *Set boundary data and interrior values
  254 + * */
  255 +
  256 +
  257 + // interior points
  258 + for (ix = 1; ix < nx-1; ix++)
  259 + for (iy = 1; iy < ny-1; iy++) {
  260 + u[ix*ny+iy]=0.0;
  261 + }
  262 +
  263 + //boundary left
  264 + for (ix = 1; ix < nx-1; ix++){
  265 + u[ix*ny]=100.0;
  266 +
  267 + }
  268 +
  269 + //boundary right
  270 + for (ix = 1; ix < nx-1; ix++){
  271 + u[ix*ny+ (ny-1)]=100.0;
  272 +
  273 + }
  274 +
  275 + //boundary down
  276 + for (iy = 0; iy < ny; iy++){
  277 +
  278 + if(rank==size-1) {
  279 + u[(nx-1)*(ny)+iy]=100.0;
  280 + }else
  281 + {
  282 + u[(nx-1)*(ny)+iy]=0.0;
  283 + }
  284 + }
  285 +
  286 + //boundary top
  287 + for (iy = 0; iy < ny; iy++){
  288 + u[iy]=0.0;
  289 +
  290 + }
  291 +
  292 +}
  293 +
  294 +
  295 +/***************************************************************************
  296 + * Print Data to files
  297 + **************************************************************************/
  298 +
  299 +void print2file(int rank, int nx, int ny, float *u,const char *fname)
  300 +{
  301 + int ix, iy;
  302 + FILE *fp;
  303 +
  304 + char str[255];
  305 +
  306 + sprintf(str, "%d_%s", rank,fname);
  307 +
  308 + fp = fopen(str, "w");
  309 +
  310 + for (ix = 0 ; ix < nx; ix++) {
  311 + for (iy =0; iy < ny; iy++) {
  312 +
  313 + fprintf(fp, "%6.2f ", u[ix*ny+iy]);
  314 + }
  315 + fputc ( '\n', fp);
  316 + }
  317 +
  318 + fclose(fp);
  319 +
  320 +}
  321 +
  322 +
  323 +
  324 +void prtdat(int rank, int size,int nx, int ny, float *u,const char *fname)
  325 +{
  326 +
  327 +
  328 + if(ITER_PRINT==0)return;
  329 +
  330 +
  331 + /**
  332 + * USE TOKEN RING to write to unique file
  333 + * 0 will rite first and then 1, 2, ... size-1
  334 + *
  335 + * * */
  336 +
  337 +
  338 + print2file(rank,nx,ny,u,fname);
  339 +
  340 +}
lab3/omp_heat2D.c View file @ 3604dfa
... ... @@ -37,7 +37,7 @@
37 37 #define _EPSILON 0.001
38 38  
39 39  
40   -void update(int nx,int ny, float *u, float *unew, float * diff);
  40 +float update(int nx,int ny, float *u, float *unew);
41 41 void inidat(int nx, int ny, float *u, float *unew);
42 42 void prtdat(int nx, int ny, float *u,const char *fnam);
43 43  
... ... @@ -97,7 +97,7 @@
97 97  
98 98 while(diff> EPSILON) {
99 99  
100   - update(N, M, u, unew,&diff);
  100 + diff = update(N, M, u, unew);
101 101  
102 102 if(iter%ITER_PRINT==0)
103 103 printf("Iteration %d, diff = %f\n ", iter,diff);
104 104  
... ... @@ -116,10 +116,10 @@
116 116 /****************************************************************************
117 117 * subroutine update
118 118 ****************************************************************************/
119   -void update(int nx,int ny, float *u, float *unew, float * diff)
  119 +float update(int nx,int ny, float *u, float *unew)
120 120 {
121 121 int ix, iy;
122   - *diff=0.0;
  122 + float diff=0.0;
123 123  
124 124 #pragma omp parallel for shared(nx,ny,u,unew) private (ix,iy)
125 125 for (ix = 1; ix < nx-1; ix++) {
... ... @@ -136,6 +136,10 @@
136 136  
137 137 float mydiff;
138 138  
  139 +/**
  140 + * IMPLEMENT OMP REDUCE MAX
  141 + */
  142 +
139 143 #pragma omp parallel shared(nx,ny,u,unew, diff) private (ix,iy,mydiff)
140 144 {
141 145 mydiff=0.0;
142 146  
143 147  
144 148  
... ... @@ -150,15 +154,17 @@
150 154 }
151 155  
152 156  
153   -# pragma omp critical
  157 +#pragma omp critical
154 158 {
155   - if (*diff < mydiff )
  159 + if (diff < mydiff )
156 160 {
157   - *diff = mydiff;
  161 + diff = mydiff;
158 162 }
159 163 }
160 164  
161   -
  165 +/*
  166 + * COPY OLD DATA
  167 + */
162 168 #pragma omp for
163 169 for (ix = 1; ix < nx-1; ix++) {
164 170 for (iy = 1; iy < ny-1; iy++) {
165 171  
... ... @@ -166,11 +172,14 @@
166 172 }
167 173 }
168 174 }
  175 +
  176 + return diff;
169 177 }
170 178  
171 179 /*****************************************************************************
172 180 * Initialize Data
173 181 *****************************************************************************/
  182 +
174 183 void inidat(int nx, int ny, float *u, float *unew)
175 184 {
176 185 int ix, iy;
177 186  
178 187  
179 188  
180 189  
181 190  
... ... @@ -178,32 +187,51 @@
178 187 /*
179 188 *Set boundary data and interrior values
180 189 * */
181   - for (ix = 0; ix < nx; ix++)
182   - for (iy = 0; iy < ny; iy++) {
183 190  
184   - if(ix==0)
185   - {
186   - u[ix*ny+iy]=0.0;
187   - }
188   - else
189   - if(iy==0 && ix!=0)
190   - {
191   - u[ix*ny+iy]=100.0;
192   - }else
  191 +#pragma omp parallel private (ix,iy)
  192 + {
  193 + // interior points
  194 + #pragma omp for
  195 + for (ix = 1; ix < nx-1; ix++)
  196 + for (iy = 1; iy < ny-1; iy++) {
  197 + u[ix*ny+iy]=5.0;
  198 + }
193 199  
194   - if(ix==nx-1)
195   - {
196   - u[ix*ny+iy]=100.0;
197   - }else
  200 + //boundary left
  201 + #pragma omp for
  202 + for (ix = 1; ix < nx-1; ix++){
  203 + u[ix*ny]=100.0;
198 204  
199   - if(iy==ny-1 && ix!=0)
200   - {
201   - u[ix*ny+iy]=100.0;
202   - }else
  205 + }
203 206  
204   - u[ix*ny+iy]=0.0;
205   - }
  207 + //boundary right
  208 + #pragma omp for
  209 + for (ix = 1; ix < nx-1; ix++){
  210 + u[ix*ny+ (ny-1)]=100.0;
  211 +
  212 + }
  213 +
  214 + //boundary down
  215 + #pragma omp for
  216 + for (iy = 0; iy < ny; iy++){
  217 + u[(nx-1)*(ny)+iy]=100.0;
  218 +
  219 + }
  220 +
  221 + //boundary top
  222 + #pragma omp for
  223 + for (iy = 0; iy < ny; iy++){
  224 + u[iy]=0.0;
  225 +
  226 + }
  227 +
  228 + }
  229 +
206 230 }
  231 +
  232 +
  233 +
  234 +
207 235  
208 236 /**************************************************************************
209 237 * Print Data to files
lab3/ser_heat2D.c View file @ 3604dfa
... ... @@ -36,7 +36,7 @@
36 36 #define _EPSILON 0.01
37 37  
38 38  
39   -void update(int nx,int ny, float *u, float *unew, float * diff);
  39 +float update(int nx,int ny, float *u, float *unew);
40 40 void inidat(int nx, int ny, float *u, float *unew);
41 41 void prtdat(int nx, int ny, float *u,const char *fnam);
42 42  
... ... @@ -98,7 +98,7 @@
98 98  
99 99 while(diff> EPSILON) {
100 100  
101   - update(N, M, u, unew,&diff);
  101 + diff= update(N, M, u, unew);
102 102  
103 103 if(iter%ITER_PRINT==0)
104 104  
105 105  
106 106  
107 107  
108 108  
109 109  
... ... @@ -118,30 +118,33 @@
118 118 /****************************************************************************
119 119 * subroutine update
120 120 ****************************************************************************/
121   -void update(int nx,int ny, float *u, float *unew, float * diff)
  121 +float update(int nx,int ny, float *u, float *unew)
122 122 {
123 123 int ix, iy;
124   - *diff=0.0;
  124 + float diff=0.0;
125 125  
126 126 for (ix = 1; ix < nx-1; ix++) {
127 127 for (iy = 1; iy < ny-1; iy++) {
128 128 unew[ix*ny+iy] = (u[(ix+1)*ny+iy] + u[(ix-1)*ny+iy] + u[ix*ny+iy+1] + u[ix*ny+iy-1] )/4.0
129 129 ;
130   - if (*diff < fabs (unew[ix*ny+iy] - u[ix*ny+iy] ))
  130 + if (diff < fabs (unew[ix*ny+iy] - u[ix*ny+iy] ))
131 131 {
132   - *diff = fabs ( unew[ix*ny+iy] - u[ix*ny+iy] );
  132 + diff = fabs ( unew[ix*ny+iy] - u[ix*ny+iy] );
133 133 }
134 134 }
135 135  
136 136 }
137 137  
138   -
  138 + /**
  139 + * COPY OLD DATA
  140 + */
139 141 for (ix = 1; ix < nx-1; ix++) {
140 142 for (iy = 1; iy < ny-1; iy++) {
141 143 u[ix*ny+iy] = unew[ix*ny+iy];
142 144 }
143 145 }
144 146  
  147 + return diff;
145 148 }
146 149  
147 150 /*****************************************************************************
148 151  
149 152  
150 153  
151 154  
... ... @@ -154,32 +157,42 @@
154 157 /*
155 158 *Set boundary data and interrior values
156 159 * */
157   - for (ix = 0; ix < nx; ix++)
158   - for (iy = 0; iy < ny; iy++) {
159 160  
160   - if(ix==0)
161   - {
162   - u[ix*ny+iy]=0.0;
163   - }
164   - else
165   - if(iy==0 && ix!=0)
166   - {
167   - u[ix*ny+iy]=100.0;
168   - }else
169   -
170   - if(ix==nx-1)
171   - {
172   - u[ix*ny+iy]=100.0;
173   - }else
174 161  
175   - if(iy==ny-1 && ix!=0)
176   - {
177   - u[ix*ny+iy]=100.0;
178   - }else
179   -
180   - u[ix*ny+iy]=0.0;
  162 + // interior points
  163 + for (ix = 1; ix < nx-1; ix++)
  164 + for (iy = 1; iy < ny-1; iy++) {
  165 + u[ix*ny+iy]=5.0;
181 166 }
  167 +
  168 + //boundary left
  169 + for (ix = 1; ix < nx-1; ix++){
  170 + u[ix*ny]=100.0;
  171 +
  172 + }
  173 +
  174 + //boundary right
  175 + for (ix = 1; ix < nx-1; ix++){
  176 + u[ix*ny+ (ny-1)]=100.0;
  177 +
  178 + }
  179 +
  180 + //boundary down
  181 + for (iy = 0; iy < ny; iy++){
  182 + u[(nx-1)*(ny)+iy]=100.0;
  183 +
  184 + }
  185 +
  186 + //boundary top
  187 + for (iy = 0; iy < ny; iy++){
  188 + u[iy]=0.0;
  189 +
  190 + }
  191 +
  192 +
182 193 }
  194 +
  195 +
183 196  
184 197 /**************************************************************************
185 198 * Print Data to files