FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

commSchedule.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 \*---------------------------------------------------------------------------*/
00025 
00026 #include "commSchedule.H"
00027 #include <OpenFOAM/SortableList.H>
00028 #include <OpenFOAM/boolList.H>
00029 #include <OpenFOAM/IOstreams.H>
00030 #include <OpenFOAM/IOmanip.H>
00031 #include <OpenFOAM/OStringStream.H>
00032 #include <OpenFOAM/Pstream.H>
00033 
00034 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00035 
00036 defineTypeNameAndDebug(Foam::commSchedule, 0);
00037 
00038 
00039 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00040 
00041 Foam::label Foam::commSchedule::outstandingComms
00042 (
00043     const labelList& commToSchedule,
00044     DynamicList<label>& procComms
00045 ) const
00046 {
00047     label nOutstanding = 0;
00048 
00049     forAll(procComms, i)
00050     {
00051         if (commToSchedule[procComms[i]] == -1)
00052         {
00053             nOutstanding++;
00054         }
00055     }
00056     return nOutstanding;
00057 }
00058 
00059 
00060 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00061 
00062 // Construct from separate addressing
00063 Foam::commSchedule::commSchedule
00064 (
00065     const label nProcs,
00066     const List<labelPair>& comms
00067 )
00068 :
00069     schedule_(comms.size()),
00070     procSchedule_(nProcs)
00071 {
00072     // Determine comms per processor.
00073     List<DynamicList<label> > procToComms(nProcs);
00074 
00075     forAll(comms, commI)
00076     {
00077         label proc0 = comms[commI][0];
00078         label proc1 = comms[commI][1];
00079 
00080         if (proc0 < 0 || proc0 >= nProcs || proc1 < 0 || proc1 >= nProcs)
00081         {
00082             FatalErrorIn
00083             (
00084                 "commSchedule::commSchedule"
00085                 "(const label, const List<labelPair>&)"
00086             )   << "Illegal processor " << comms[commI] << abort(FatalError);
00087         }
00088 
00089         procToComms[proc0].append(commI);
00090         procToComms[proc1].append(commI);
00091     }
00092     // Note: no need to shrink procToComms. Are small.
00093 
00094     if (debug && Pstream::master())
00095     {
00096         Pout<< "commSchedule::commSchedule : Wanted communication:" << endl;
00097 
00098         forAll(comms, i)
00099         {
00100             const labelPair& twoProcs = comms[i];
00101 
00102             Pout<< i << ": "
00103                 << twoProcs[0] << " with " << twoProcs[1] << endl;
00104         }
00105         Pout<< endl;
00106 
00107 
00108         Pout<< "commSchedule::commSchedule : Schedule:" << endl;
00109 
00110         // Print header. Use buffered output to prevent parallel output messing
00111         // up.
00112         {
00113             OStringStream os;
00114             os  << "iter|";
00115             for (int i = 0; i < nProcs; i++)
00116             {
00117                 os  << setw(3) << i;
00118             }
00119             Pout<< os.str().c_str() << endl;
00120         }
00121         {
00122             OStringStream os;
00123             os  << "----+";
00124             for (int i = 0; i < nProcs; i++)
00125             {
00126                 os  << "---";
00127             }
00128             Pout<< os.str().c_str() << endl;
00129         }
00130     }
00131 
00132     // Schedule all. Note: crap scheduler. Assumes all communication takes
00133     // equally long.
00134 
00135     label nScheduled = 0;
00136 
00137     label iter = 0;
00138 
00139     // Per index into comms the time when it was scheduled
00140     labelList commToSchedule(comms.size(), -1);
00141 
00142     while (nScheduled < comms.size())
00143     {
00144         label oldNScheduled = nScheduled;
00145 
00146         // Find unscheduled comms. This is the comms where the two processors
00147         // still have the most unscheduled comms.
00148 
00149         boolList busy(nProcs, false);
00150 
00151         while (true)
00152         {
00153             label maxCommI = -1;
00154             label maxNeed = labelMin;
00155 
00156             forAll(comms, commI)
00157             {
00158                 label proc0 = comms[commI][0];
00159                 label proc1 = comms[commI][1];
00160 
00161                 if
00162                 (
00163                     commToSchedule[commI] == -1             // unscheduled
00164                 && !busy[proc0]
00165                 && !busy[proc1]
00166                 )
00167                 {
00168                     label need =
00169                         outstandingComms(commToSchedule, procToComms[proc0])
00170                       + outstandingComms(commToSchedule, procToComms[proc1]);
00171 
00172                     if (need > maxNeed)
00173                     {
00174                         maxNeed = need;
00175                         maxCommI = commI;
00176                     }
00177                 }
00178             }
00179 
00180 
00181             if (maxCommI == -1)
00182             {
00183                 // Found no unscheduled procs.
00184                 break;
00185             }
00186 
00187             // Schedule commI in this iteration
00188             commToSchedule[maxCommI] = nScheduled++;
00189             busy[comms[maxCommI][0]] = true;
00190             busy[comms[maxCommI][1]] = true;
00191         }
00192 
00193         if (debug && Pstream::master())
00194         {
00195             label nIterComms = nScheduled-oldNScheduled;
00196 
00197             if (nIterComms > 0)
00198             {
00199                 labelList procToComm(nProcs, -1);
00200 
00201                 forAll(commToSchedule, commI)
00202                 {
00203                     label sched = commToSchedule[commI];
00204 
00205                     if (sched >= oldNScheduled && sched < nScheduled)
00206                     {
00207                         label proc0 = comms[commI][0];
00208                         procToComm[proc0] = commI;
00209                         label proc1 = comms[commI][1];
00210                         procToComm[proc1] = commI;
00211                     }
00212                 }
00213 
00214                 // Print it
00215                 OStringStream os;
00216                 os  << setw(3) << iter << " |";
00217                 forAll(procToComm, procI)
00218                 {
00219                     if (procToComm[procI] == -1)
00220                     {
00221                         os  << "   ";
00222                     }
00223                     else
00224                     {
00225                         os  << setw(3) << procToComm[procI];
00226                     }
00227                 }
00228                 Pout<< os.str().c_str() << endl;
00229             }
00230         }
00231 
00232         iter++;
00233     }
00234 
00235     if (debug && Pstream::master())
00236     {
00237         Pout<< endl;
00238     }
00239 
00240 
00241     // Sort commToSchedule and obtain order in comms
00242     schedule_ = SortableList<label>(commToSchedule).indices();
00243 
00244     // Sort schedule_ by processor
00245 
00246     labelList nProcScheduled(nProcs, 0);
00247 
00248     // Count
00249     forAll(schedule_, i)
00250     {
00251         label commI = schedule_[i];
00252         const labelPair& twoProcs = comms[commI];
00253 
00254         nProcScheduled[twoProcs[0]]++;
00255         nProcScheduled[twoProcs[1]]++;
00256     }
00257     // Allocate
00258     forAll(procSchedule_, procI)
00259     {
00260         procSchedule_[procI].setSize(nProcScheduled[procI]);
00261     }
00262     nProcScheduled = 0;
00263     // Fill
00264     forAll(schedule_, i)
00265     {
00266         label commI = schedule_[i];
00267         const labelPair& twoProcs = comms[commI];
00268 
00269         label proc0 = twoProcs[0];
00270         procSchedule_[proc0][nProcScheduled[proc0]++] = commI;
00271 
00272         label proc1 = twoProcs[1];
00273         procSchedule_[proc1][nProcScheduled[proc1]++] = commI;
00274     }
00275 
00276     if (debug && Pstream::master())
00277     {
00278         Pout<< "commSchedule::commSchedule : Per processor:" << endl;
00279 
00280         forAll(procSchedule_, procI)
00281         {
00282             const labelList& procComms = procSchedule_[procI];
00283 
00284             Pout<< "Processor " << procI << " talks to processors:" << endl;
00285 
00286             forAll(procComms, i)
00287             {
00288                 const labelPair& twoProcs = comms[procComms[i]];
00289 
00290                 label nbr = (twoProcs[1] == procI ? twoProcs[0] : twoProcs[1]);
00291 
00292                 Pout<< "    " << nbr << endl;
00293             }
00294         }
00295         Pout<< endl;
00296     }
00297 }
00298 
00299 
00300 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines