1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2004-2010 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "commSchedule.H"
27 #include "SortableList.H"
29 #include "IOstreams.H"
31 #include "OStringStream.H"
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36 defineTypeNameAndDebug(Foam::commSchedule, 0);
39 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
41 Foam::label Foam::commSchedule::outstandingComms
43 const labelList& commToSchedule,
44 DynamicList<label>& procComms
47 label nOutstanding = 0;
51 if (commToSchedule[procComms[i]] == -1)
60 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
62 // Construct from separate addressing
63 Foam::commSchedule::commSchedule
66 const List<labelPair>& comms
69 schedule_(comms.size()),
72 // Determine comms per processor.
73 List<DynamicList<label> > procToComms(nProcs);
77 label proc0 = comms[commI][0];
78 label proc1 = comms[commI][1];
80 if (proc0 < 0 || proc0 >= nProcs || proc1 < 0 || proc1 >= nProcs)
84 "commSchedule::commSchedule"
85 "(const label, const List<labelPair>&)"
86 ) << "Illegal processor " << comms[commI] << abort(FatalError);
89 procToComms[proc0].append(commI);
90 procToComms[proc1].append(commI);
92 // Note: no need to shrink procToComms. Are small.
94 if (debug && Pstream::master())
96 Pout<< "commSchedule::commSchedule : Wanted communication:" << endl;
100 const labelPair& twoProcs = comms[i];
103 << twoProcs[0] << " with " << twoProcs[1] << endl;
108 Pout<< "commSchedule::commSchedule : Schedule:" << endl;
110 // Print header. Use buffered output to prevent parallel output messing
115 for (int i = 0; i < nProcs; i++)
119 Pout<< os.str().c_str() << endl;
124 for (int i = 0; i < nProcs; i++)
128 Pout<< os.str().c_str() << endl;
132 // Schedule all. Note: crap scheduler. Assumes all communication takes
135 label nScheduled = 0;
139 // Per index into comms the time when it was scheduled
140 labelList commToSchedule(comms.size(), -1);
142 while (nScheduled < comms.size())
144 label oldNScheduled = nScheduled;
146 // Find unscheduled comms. This is the comms where the two processors
147 // still have the most unscheduled comms.
149 boolList busy(nProcs, false);
154 label maxNeed = labelMin;
158 label proc0 = comms[commI][0];
159 label proc1 = comms[commI][1];
163 commToSchedule[commI] == -1 // unscheduled
169 outstandingComms(commToSchedule, procToComms[proc0])
170 + outstandingComms(commToSchedule, procToComms[proc1]);
183 // Found no unscheduled procs.
187 // Schedule commI in this iteration
188 commToSchedule[maxCommI] = nScheduled++;
189 busy[comms[maxCommI][0]] = true;
190 busy[comms[maxCommI][1]] = true;
193 if (debug && Pstream::master())
195 label nIterComms = nScheduled-oldNScheduled;
199 labelList procToComm(nProcs, -1);
201 forAll(commToSchedule, commI)
203 label sched = commToSchedule[commI];
205 if (sched >= oldNScheduled && sched < nScheduled)
207 label proc0 = comms[commI][0];
208 procToComm[proc0] = commI;
209 label proc1 = comms[commI][1];
210 procToComm[proc1] = commI;
216 os << setw(3) << iter << " |";
217 forAll(procToComm, procI)
219 if (procToComm[procI] == -1)
225 os << setw(3) << procToComm[procI];
228 Pout<< os.str().c_str() << endl;
235 if (debug && Pstream::master())
241 // Sort commToSchedule and obtain order in comms
242 schedule_ = SortableList<label>(commToSchedule).indices();
244 // Sort schedule_ by processor
246 labelList nProcScheduled(nProcs, 0);
251 label commI = schedule_[i];
252 const labelPair& twoProcs = comms[commI];
254 nProcScheduled[twoProcs[0]]++;
255 nProcScheduled[twoProcs[1]]++;
258 forAll(procSchedule_, procI)
260 procSchedule_[procI].setSize(nProcScheduled[procI]);
266 label commI = schedule_[i];
267 const labelPair& twoProcs = comms[commI];
269 label proc0 = twoProcs[0];
270 procSchedule_[proc0][nProcScheduled[proc0]++] = commI;
272 label proc1 = twoProcs[1];
273 procSchedule_[proc1][nProcScheduled[proc1]++] = commI;
276 if (debug && Pstream::master())
278 Pout<< "commSchedule::commSchedule : Per processor:" << endl;
280 forAll(procSchedule_, procI)
282 const labelList& procComms = procSchedule_[procI];
284 Pout<< "Processor " << procI << " talks to processors:" << endl;
288 const labelPair& twoProcs = comms[procComms[i]];
290 label nbr = (twoProcs[1] == procI ? twoProcs[0] : twoProcs[1]);
292 Pout<< " " << nbr << endl;
300 // ************************************************************************* //