00001 // -*- C++ -*- 00002 /*************************************************************************** 00003 * 00004 * The IPPL Framework 00005 * 00006 * This program was prepared by PSI. 00007 * All rights in the program are reserved by PSI. 00008 * Neither PSI nor the author(s) 00009 * makes any warranty, express or implied, or assumes any liability or 00010 * responsibility for the use of this software 00011 * 00012 * Visit http://www.acl.lanl.gov/POOMS for more details 00013 * 00014 ***************************************************************************/ 00015 00016 // -*- C++ -*- 00017 /*************************************************************************** 00018 * 00019 * The IPPL Framework 00020 * 00021 * 00022 * Visit http://people.web.psi.ch/adelmann/ for more details 00023 * 00024 ***************************************************************************/ 00025 00026 // include files 00027 #include "FieldLayout/ConejoBalancer.h" 00028 #include "FieldLayout/MultiBalancer.h" 00029 #include "Utility/IpplInfo.h" 00030 00032 // 00033 // PUBLIC FUNCTIONS 00034 // 00036 00037 // 00038 // The constructor for ConejoBalancer. 00039 // Record the number of processors in the system. 00040 // 00041 00042 ConejoBalancer::ConejoBalancer() 00043 : 00044 // Initialize the pointer to the balancer to zero 00045 // because we can't construct it yet. 00046 m_balancer(0), 00047 // Initialize the number of vnodes to -1 because we don't know that yet. 00048 m_localVnodes(-1), 00049 m_totalVnodes(-1), 00050 // Record the number of processors. 00051 m_procs( IpplInfo::getNodes() ), 00052 // Record which processor is mine. 00053 m_myProc( IpplInfo::myNode() ) 00054 { 00055 // Record the number of vnodes on each processor. 00056 // Start the value out with -1 so we know if it has been set or not. 00057 m_vnodeCounts.resize(m_procs); 00058 for (int i=0; i<m_procs; ++i) 00059 m_vnodeCounts[i] = -1; 00060 } 00061 00063 00064 // 00065 // The destructor for ConejoBalancer. 00066 // Just delete the balancer. 00067 // 00068 00069 ConejoBalancer::~ConejoBalancer() 00070 { 00071 delete m_balancer; 00072 } 00073 00075 // 00076 // PRIVATE FUNCTIONS 00077 // 00079 00080 // 00081 // ConejoBalancer::sendWeights 00082 // 00083 // INPUTS: 00084 // vnodeWeights: A vector<double> of weights for vnodes on this proc. 00085 // tag: an integer tag for the message. 00086 // 00087 // OUTPUTS: 00088 // Message is sent. 00089 // 00090 00091 void 00092 ConejoBalancer::sendWeights(vector<double>& vnodeWeights, int tag) 00093 { 00094 // Build a message to be sent. 00095 Message *msg = new Message(); 00096 00097 // Add data to the message. 00098 // First the number of elements, then the elements themselves. 00099 msg->put(vnodeWeights.size()); 00100 putMessage(*msg, vnodeWeights.begin(), vnodeWeights.end()); 00101 00102 // Send the message. 00103 Ippl::Comm->send(msg, 0, tag); 00104 } 00105 00107 00108 // 00109 // ConejoBalancer::receiveWeights 00110 // 00111 // INPUTS: 00112 // vnodeWeights: A vector<double>. Initially has the data from this 00113 // processor. Used as a place to put incoming data. 00114 // tag: an integer tag for the messages. 00115 // 00116 // OUTPUTS: 00117 // Updated state of the ConejoBalancer with the data from 00118 // the other processors. 00119 // 00120 00121 void 00122 ConejoBalancer::receiveWeights(vector<double>& vnodeWeights, int tag) 00123 { 00124 // Tell the MultiBalancer that it is about to get a new material. 00125 m_balancer->newMaterial(); 00126 00127 // Receive messages from all the other processors. 00128 for ( int proc=0; proc < m_procs ; ++proc ) 00129 { 00130 // Receive a message from the next proc. 00131 Message *msg = Ippl::Comm->receive_block(proc,tag); 00132 00133 // Get the number of vnodes. 00134 long int count; 00135 msg->get(count); 00136 00137 // Record the number of vnodes on that proc. 00138 recordVnodeCount(count,proc); 00139 00140 // Allocate space for the incoming data. 00141 vnodeWeights.resize( count ); 00142 00143 // Unpack it. 00144 getMessage_iter(*msg, vnodeWeights.begin() ); 00145 00146 // Record it by extracting a double* from the vnodeWeights iterator. 00147 double *p = &*(vnodeWeights.begin()); 00148 m_balancer->appendWeights(p,p+vnodeWeights.size()); 00149 00150 // Delete the message. 00151 delete msg; 00152 } 00153 } 00154 00156 00157 // 00158 // Tell the ConejoBalancer the number of vnodes it is dealing with. 00159 // 00160 // INPUT: 00161 // localVnodes: The number of vnodes on this processor. 00162 // totalVnodes: The total number of vnodes on all the processors. 00163 // 00164 // OUTPUT: 00165 // Updated state of the ConejoBalancer. 00166 // The number of vnodes is recorded. 00167 // The MultiBalancer is initialized. 00168 // 00169 00170 void 00171 ConejoBalancer::setupVnodes(int localVnodes, int remoteVnodes) 00172 { 00173 // The first time through we need to record the sizes, 00174 // and build the balancer 00175 if ( m_balancer == 0 ) 00176 { 00177 // Record the sizes. 00178 m_localVnodes = localVnodes; 00179 m_totalVnodes = localVnodes + remoteVnodes; 00180 00181 // If we are processor zero, build the balancer object. 00182 if ( m_myProc == 0 ) 00183 m_balancer = new MultiBalancer(m_procs,m_totalVnodes); 00184 } 00185 // If it isn't the first time, make sure this BareField 00186 // is consistent with the previous. 00187 else 00188 { 00189 PAssert(m_localVnodes == localVnodes); 00190 PAssert(m_totalVnodes == localVnodes + remoteVnodes); 00191 PAssert( (m_balancer!=0) == (m_myProc==0 ) ); 00192 } 00193 } 00194 00196 00197 // 00198 // Tell the ConejoBalancer the number of vnodes on a given processor. 00199 // 00200 // INPUT: 00201 // count: an integer for the number of vnodes 00202 // proc: an integer of the processor 00203 // 00204 // OUTPUT: 00205 // Updated state of the ConejoBalancer. 00206 // The first time it is called it records the count. 00207 // After that, it checks to make sure the counts agree. 00208 // 00209 00210 void 00211 ConejoBalancer::recordVnodeCount(int count, int proc) 00212 { 00213 // Make sure this processor number makes sense. 00214 PAssert( proc >= 0 ); 00215 00216 // Check to see if this is the first time it is being called. 00217 if ( m_vnodeCounts[proc] < 0 ) 00218 { 00219 // First time, record the count. 00220 m_vnodeCounts[proc] = count; 00221 } 00222 // Not the first time. 00223 else 00224 { 00225 // Make sure this count agrees with record. 00226 PAssert( m_vnodeCounts[proc] == count ); 00227 } 00228 } 00229 00231 00232 // 00233 // ConejoBalancer::broadcastVnodesToSend 00234 // 00235 // Scan through the data in the MultiBalancer and figure out 00236 // which processors will be sending vnodes to where. 00237 // Broadcast that information to the processors that will 00238 // be sending. 00239 // 00240 // INPUT: 00241 // tag: an integer message tag. 00242 // 00243 // OUTPUT: 00244 // Messages sent. 00245 // 00246 00247 void 00248 ConejoBalancer::broadcastVnodesToSend(int tag) 00249 { 00250 // Get a pointer to the destination processors for each vnode. 00251 MultiBalancer::iterator vp = m_balancer->begin(); 00252 00253 // Loop over the source processors, sending data to each. 00254 for ( int sourceProc = 0; sourceProc < m_procs; ++sourceProc ) 00255 { 00256 // Cache the number of vnodes on this processor. 00257 long int c = m_vnodeCounts[sourceProc]; 00258 00259 // Build the message. 00260 Message *msg = new Message; 00261 msg->put(c); 00262 putMessage(*msg, vp, vp + c); 00263 00264 // Send the message. 00265 Ippl::Comm->send(msg,sourceProc,tag); 00266 00267 // Increment the pointer to the destination processors. 00268 vp += c; 00269 } 00270 } 00271 00273 00274 // 00275 // ConejoBalancer::receiveVnodesToSend 00276 // 00277 // Every processor receives from processor zero the destinations 00278 // for its vnodes. 00279 // 00280 // INPUT: 00281 // tag: an integer message tag. 00282 // 00283 // OUTPUT: 00284 // vnodeDestinations: A vector<int>& to hold the destinations for 00285 // all the vnodes on this proc. 00286 // 00287 00288 void 00289 ConejoBalancer::receiveVnodesToSend(vector<int>& vnodeDestinations, int tag) 00290 { 00291 // Receive the message from proc 0. 00292 int proc_zero = 0; 00293 Message *msg = Ippl::Comm->receive_block(proc_zero,tag); 00294 00295 // Get the number of vnodes coming in. 00296 long int s; 00297 msg->get(s); 00298 00299 // Extract the vnode destinations. 00300 vnodeDestinations.resize(s); 00301 getMessage_iter(*msg, vnodeDestinations.begin() ); 00302 00303 // Delete the message. 00304 delete msg; 00305 } 00306 00307 /*************************************************************************** 00308 * $RCSfile: ConejoBalancer_inst.cpp,v $ $Author: adelmann $ 00309 * $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:27 $ 00310 * IPPL_VERSION_ID: $Id: ConejoBalancer_inst.cpp,v 1.1.1.1 2003/01/23 07:40:27 adelmann Exp $ 00311 ***************************************************************************/