MIDAPACK - MIcrowave Data Analysis PACKage  1.1b
Parallel software tools for high performance CMB DA analysis
 All Data Structures Files Functions Variables Typedefs Groups Pages
truebutterfly.c
Go to the documentation of this file.
1 
9 #ifdef W_MPI
10 #include <mpi.h>
11 #include <stdlib.h>
12 #include <string.h>
13 
14 
37 int truebutterfly_init(int *indices, int count, int **R, int *nR, int **S, int *nS, int **com_indices, int *com_count, int steps, MPI_Comm comm){
38 
39  int i, k, p2k, p2k1;
40  int rank, size, rk, sk;
41  int tag;
42  MPI_Request s_request, r_request;
43  int nbuf, *buf;
44  int **I, *nI;
45  int **J, *nJ;
46 
47  MPI_Comm_size(comm, &size);
48  MPI_Comm_rank(comm, &rank);
49 
50  I = (int **) malloc(steps * sizeof(int*));
51  nI = (int *) malloc(steps * sizeof(int));
52  tag=0;
53  p2k=size/2;
54  p2k1=2*p2k;
55 
56  for(k=0; k<steps; k++){ //butterfly first pass : bottom up (fill tabs nI and I)
57 
58  if( rank%p2k1 < p2k) sk=rk=rank+p2k; else sk=rk=rank-p2k;
59 
60  if(k==0){ //S^0 := A
61  nS[k] = count;
62  S[k] = (int *) malloc(nS[k] * sizeof(int));
63  memcpy( S[k], indices, nS[k]*sizeof(int));
64  }
65  else{ //S^k := S^{k-1} \cup R^{k-1}
66  nS[k] = card_or(S[k-1], nS[k-1], I[steps-k], nI[steps-k]);
67  S[k] = (int *) malloc(nS[k] * sizeof(int));
68  set_or(S[k-1], nS[k-1], I[steps-k], nI[steps-k], S[k]);
69  }
70 
71  MPI_Irecv(&nI[steps-k-1], 1, MPI_INT, rk, tag, comm, &r_request); //receive number of indices
72  MPI_Isend(&nS[k], 1, MPI_INT, sk, tag, comm, &s_request); //send number of indices
73  MPI_Wait(&r_request, MPI_STATUS_IGNORE);
74  MPI_Wait(&s_request, MPI_STATUS_IGNORE);
75 
76  I[steps-k-1]= (int *) malloc(nI[steps-k-1] * sizeof(int));
77 
78  tag++;
79  MPI_Irecv(I[steps-k-1], nI[steps-k-1], MPI_INT, rk, tag, comm, &r_request); //receive indices
80  MPI_Isend(S[k], nS[k], MPI_INT, sk, tag, comm, &s_request); //send indices
81  MPI_Wait(&r_request, MPI_STATUS_IGNORE);
82  MPI_Wait(&s_request, MPI_STATUS_IGNORE);
83 
84  p2k/=2;
85  p2k1/=2;
86  tag++;
87  }
88 
89  J = (int **) malloc(steps * sizeof(int*));
90  nJ = (int *) malloc(steps * sizeof(int));
91 
92  tag=0;
93  p2k=1;
94  p2k1=p2k*2;
95  for(k=0; k<steps; k++){ //buuterfly second pass : top down (fill tabs nJ and J)
96  free(S[k]);
97 
98  if( rank%p2k1 < p2k) sk=rk=rank+p2k; else sk=rk=rank-p2k;
99 
100  if(k==0){
101  nJ[k] = count;
102  J[k] = (int *) malloc(nJ[k] * sizeof(int));
103  memcpy( J[k], indices, nJ[k]*sizeof(int));
104  }
105  else{
106  nJ[k] = card_or(J[k-1], nJ[k-1], R[k-1], nR[k-1]);
107  J[k] = (int *) malloc(nJ[k] * sizeof(int));
108  set_or(J[k-1], nJ[k-1], R[k-1], nR[k-1], J[k]); //J^k=R^k-1 \cup J^k-1
109  free(R[k-1]);
110  }
111  if(k!=steps-1){
112  MPI_Irecv(&nR[k], 1, MPI_INT, rk, tag, comm, &r_request);
113  MPI_Isend(&nJ[k], 1, MPI_INT, sk, tag, comm, &s_request);
114  MPI_Wait(&r_request, MPI_STATUS_IGNORE);
115  MPI_Wait(&s_request, MPI_STATUS_IGNORE);
116 
117  R[k]= (int *) malloc( nR[k] * sizeof(int));
118  tag++;
119 
120  MPI_Irecv(R[k], nR[k], MPI_INT, rk, tag, comm, &r_request);
121  MPI_Isend(J[k], nJ[k], MPI_INT, sk, tag, comm, &s_request);
122  MPI_Wait(&r_request, MPI_STATUS_IGNORE);
123  MPI_Wait(&s_request, MPI_STATUS_IGNORE);
124  }
125  p2k*=2;
126  p2k1*=2;
127  tag++;
128  }
129 
130 
131  tag=0;
132  p2k=1;
133  p2k1=p2k*2;
134  for(k=0; k<steps; k++){ //butterfly last pass : know that Sending tab is S = I \cap J, so send S and we'll get R
135 
136  if( rank%p2k1 < p2k) sk=rk=rank+p2k; else sk=rk=rank-p2k;
137 
138  nS[k] = card_and(I[k], nI[k], J[k], nJ[k]);
139  S[k] = (int *) malloc(nJ[k] *sizeof(int));
140  set_and( I[k], nI[k], J[k], nJ[k], S[k]); //S^k=I^k \cap J^k
141 
142  free(I[k]);
143  free(J[k]);
144 
145  MPI_Irecv(&nR[k],1, MPI_INT, rk, tag, comm, &r_request); //receive size
146  MPI_Isend(&nS[k], 1, MPI_INT, sk, tag, comm, &s_request); //send size
147  MPI_Wait(&r_request, MPI_STATUS_IGNORE);
148  MPI_Wait(&s_request, MPI_STATUS_IGNORE);
149 
150  R[k]= (int *) malloc( nR[k] * sizeof(int));
151  tag++;
152 
153  MPI_Irecv(R[k], nR[k], MPI_INT, rk, tag, comm, &r_request); //receive indices
154  MPI_Isend(S[k], nS[k], MPI_INT, sk, tag, comm, &s_request); //send indices
155  MPI_Wait(&r_request, MPI_STATUS_IGNORE);
156  MPI_Wait(&s_request, MPI_STATUS_IGNORE);
157 
158  p2k*=2;
159  p2k1*=2;
160  tag++;
161  }
162 
163  //Now we work locally
164  int **USR, *nUSR, **U, *nU;
165 
166  USR = (int **) malloc(steps*sizeof(int *));
167  nUSR = (int *) malloc(steps*sizeof(int));
168  U = (int **) malloc(steps*sizeof(int *));
169  nU = (int *) malloc(steps*sizeof(int));
170 
171  for(k=0; k<steps; k++){
172  nUSR[k] = card_or(S[k], nS[k], R[k], nR[k]);
173  USR[k] = (int *) malloc(nUSR[k]*sizeof(int));
174  set_or(S[k], nS[k], R[k], nR[k], USR[k]);
175  }
176  for(k=0; k<steps; k++){
177  if(k==0){
178  nU[k]=nUSR[k];
179  U[k] = (int *) malloc(nU[k] * sizeof(int));
180  memcpy( U[k], USR[k], nU[k]*sizeof(int));
181  }
182  else{
183  nU[k] = card_or(U[k-1], nU[k-1], USR[k], nUSR[k]);
184  U[k] = (int *) malloc(nU[k]*sizeof(int *));
185  set_or(U[k-1], nU[k-1], USR[k], nUSR[k], U[k]);
186  }
187  }
188  *com_count=nU[steps-1];
189  *com_indices = (int *) malloc(*com_count * sizeof(int));
190  memcpy(*com_indices, U[steps-1], *com_count * sizeof(int));
191  //====================================================================
192 
193  for(k=0; k<steps; k++){
194  subset2map(*com_indices, *com_count, S[k], nS[k]);
195  subset2map(*com_indices, *com_count, R[k], nR[k]);
196  }
197  free(USR);
198  free(U);
199 
200  return 0;
201 }
202 
203 
216 int truebutterfly_reduce(int **R, int *nR, int nRmax, int **S, int *nS, int nSmax, double *val, int steps, MPI_Comm comm){
217 // double st, t;
218 // t=0.0;
219  int k, p2k, p2k1, tag;
220  int rank, size, rk, sk;
221  MPI_Status status;
222  MPI_Request s_request, r_request;
223  double *sbuf, *rbuf;
224 
225  MPI_Comm_size(comm, &size);
226  MPI_Comm_rank(comm, &rank);
227 
228  sbuf = (double *) malloc(nSmax * sizeof(double));
229  rbuf = (double *) malloc(nRmax * sizeof(double));
230  tag=0;
231  p2k=1;
232  p2k1=p2k*2;
233 
234  for(k=0; k<steps; k++){
235 
236  if( rank%p2k1 < p2k){
237 
238  sk=rk=rank+p2k;
239 
240  // st=MPI_Wtime();
241 
242  // MPI_Sendrecv(sbuf, nS[k], MPI_DOUBLE, sk, tag, rbuf, nR[k], MPI_DOUBLE, rk, tag, comm, &status);
243 
244  m2s(val, sbuf, S[k], nS[k]); //fill the sending buffer
245  MPI_Isend(sbuf, nS[k], MPI_DOUBLE, sk, tag, comm, &s_request);
246  MPI_Irecv(rbuf, nR[k], MPI_DOUBLE, rk, tag, comm, &r_request);
247 
248  MPI_Wait(&s_request, MPI_STATUS_IGNORE);
249  MPI_Wait(&r_request, MPI_STATUS_IGNORE);
250  s2m_sum(val, rbuf, R[k], nR[k]); //sum receive buffer into values
251 
252 
253  // t=t+MPI_Wtime()-st;
254 
255  } else {
256 
257  sk=rk=rank-p2k;
258 
259  // st=MPI_Wtime();
260 
261  MPI_Irecv(rbuf, nR[k], MPI_DOUBLE, rk, tag, comm, &r_request);
262  m2s(val, sbuf, S[k], nS[k]); //fill the sending buffer
263  MPI_Isend(sbuf, nS[k], MPI_DOUBLE, sk, tag, comm, &s_request);
264 
265  MPI_Wait(&r_request, MPI_STATUS_IGNORE);
266  s2m_sum(val, rbuf, R[k], nR[k]); //sum receive buffer into values
267 
268  MPI_Wait(&s_request, MPI_STATUS_IGNORE);
269 
270  // MPI_Sendrecv(sbuf, nS[k], MPI_DOUBLE, sk, tag, rbuf, nR[k], MPI_DOUBLE, rk, tag, comm, &status);
271 
272  // t=t+MPI_Wtime()-st;
273 
274  }
275 
276  p2k*=2;
277  p2k1*=2;
278  tag++;
279 
280  }
281  free(sbuf);
282  free(rbuf);
283  return 0;
284 }
285 
286 #endif
287 
288