Scippy

UG

Ubiquity Generator framework

parascip.cpp
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and software framework */
4 /* UG --- Ubquity Generator Framework */
5 /* */
6 /* Copyright Written by Yuji Shinano <shinano@zib.de>, */
7 /* Copyright (C) 2021 by Zuse Institute Berlin, */
8 /* licensed under LGPL version 3 or later. */
9 /* Commercial licenses are available through <licenses@zib.de> */
10 /* */
11 /* This code is free software; you can redistribute it and/or */
12 /* modify it under the terms of the GNU Lesser General Public License */
13 /* as published by the Free Software Foundation; either version 3 */
14 /* of the License, or (at your option) any later version. */
15 /* */
16 /* This program is distributed in the hope that it will be useful, */
17 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
18 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
19 /* GNU Lesser General Public License for more details. */
20 /* */
21 /* You should have received a copy of the GNU Lesser General Public License */
22 /* along with this program. If not, see <http://www.gnu.org/licenses/>. */
23 /* */
24 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
25 
26 /**@file parascip.cpp
27  * @brief ParaSCIP MAIN.
28  * @author Yuji Shinano
29  *
30  *
31  *
32  */
33 
34 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
35 
36 
37 #include <cfloat>
38 #include "ug/paraInstance.h"
39 #include "ug/paraLoadCoordinator.h"
40 #include "ug/paraParamSet.h"
42 #include "ug/paraInitiator.h"
43 #include "ug_bb/bbParaNodeMpi.h"
44 #include "ug/paraSysTimer.h"
45 #include "scip/scip.h"
46 #include "scipParaCommMpi.h"
47 #include "scipParaInstance.h"
49 #include "scipParaSolver.h"
50 #include "scipParaInitiator.h"
52 
53 using namespace UG;
54 using namespace ParaSCIP;
55 
56 extern void
57 setUserPlugins(ParaInitiator *initiator);
58 extern void
59 setUserPlugins(ParaInstance *instance);
60 extern void
61 setUserPlugins(ParaSolver *solver);
62 
63 void
65  char **argv
66  )
67 {
68  std::cout << std::endl;
69  std::cout << "syntax: " << argv[0] << " #MPI_processes(#solvers + 1) parascip_param_file problem_file_name "
70  << "[-l <logfile>] [-q] [-sl <settings>] [-s <settings>] [-sr <root_settings>] [-w <prefix_warm>] [-sth <number>] [-fsol <solution_file>] [-isol <initial solution file]" << std::endl;
71  std::cout << " -l <logfile> : copy output into log file" << std::endl;
72  std::cout << " -q : suppress screen messages" << std::endl;
73  std::cout << " -sl <settings> : load parameter settings (.set) file for LC presolving" << std::endl;
74  std::cout << " -s <settings> : load parameter settings (.set) file for solvers" << std::endl;
75  std::cout << " -sr <root_settings> : load parameter settings (.set) file for root" << std::endl;
76  std::cout << " -w <prefix_warm> : warm start file prefix ( prefix_warm_nodes.gz and prefix_warm_solution.txt are read )" << std::endl;
77  std::cout << " -fsol <solution file> : specify output solution file" << std::endl;
78  std::cout << " -isol <intial solution file> : specify initial solution file" << std::endl;
79  std::cout << "File names need to be specified by full path form." << std::endl;
80 }
81 
82 void
86  )
87 {
88  if( !paraParamSet->getBoolParamValue(Quiet) )
89  {
90  std::ofstream ofsParamsOutputFile;
91  std::ostringstream s;
92  if( paraInitiator->getPrefixWarm() )
93  {
94  s << paraInitiator->getPrefixWarm();
95  }
96  else
97  {
99  << paraInitiator->getParaInstance()->getProbName();
100  }
101  s << ".prm";
102  ofsParamsOutputFile.open(s.str().c_str());
103  if( !ofsParamsOutputFile ){
104  std::cout << "Cannot open ParaParams output file: file name = " << s.str() << std::endl;
105  exit(1);
106  }
107  paraParamSet->write(&ofsParamsOutputFile);
108  ofsParamsOutputFile.close();
109  }
110 }
111 
112 void
116  )
117 {
118  if( !paraParamSet->getBoolParamValue(Quiet) )
119  {
120  std::ofstream ofsSolverParamsOutputFile;
121  std::ostringstream s;
122  if( paraInitiator->getPrefixWarm() )
123  {
124  s << paraInitiator->getPrefixWarm();
125  }
126  else
127  {
129  << paraInitiator->getParaInstance()->getProbName();
130  }
131  s << "_solver.prm";
132  ofsSolverParamsOutputFile.open(s.str().c_str());
133  if( !ofsSolverParamsOutputFile ){
134  std::cout << "Cannot open Solver parameters output file: file name = " << s.str() << std::endl;
135  exit(1);
136  }
137  paraInitiator->writeSolverParameters(&ofsSolverParamsOutputFile);
138  ofsSolverParamsOutputFile.close();
139  }
140 }
141 
142 /**************************************************************************************
143  * *
144  * Command line see outputCommandLineMessages() *
145  * *
146  **************************************************************************************/
147 int
149  int argc,
150  char **argv
151  )
152 {
153  // mtrace();
154  static const int solverOrigin = 1;
155 
156  bool racingSolversExist = false;
157  ParaDeterministicTimer *detTimer = 0;
158 
159  ParaSysTimer sysTimer;
160  sysTimer.start();
161 
162 #ifdef UG_WITH_UGS
163  char *configFileName = 0;
164  for( int i = 1; i < argc; ++i )
165  {
166  if ( strcmp(argv[i], "-ugsc") == 0 )
167  {
168  i++;
169  if( i < argc )
170  {
171  configFileName = argv[i];
172  break;
173  }
174  else
175  {
176  std::cerr << "missing file name after parameter '-ugsc" << std::endl;
177  exit(1);
178  }
179  }
180  }
181 
182  ScipParaCommMpi *comm = 0;
183  UGS::UgsParaCommMpi *commUgs = 0; // commUgs != 0 means ParaScip runs under UGS
184  if( configFileName )
185  {
186  commUgs = new UGS::UgsParaCommMpi();
187  commUgs->init(argc,argv);
188  comm = new ScipParaCommMpi(commUgs->getSolverMPIComm());
189  comm->setUgsComm(commUgs);
190  }
191  else
192  {
193  comm = new ScipParaCommMpi();
194  }
195 #else
196  // ParaComm *comm = new PARA_COMM_TYPE();
197  ScipParaCommMpi *comm = new ScipParaCommMpi();
198 #endif
199 
200  comm->init(argc,argv);
201 
202  ParaTimer *paraTimer = new ParaTimerMpi();
203  paraTimer->init(comm);
204 
206 
207 #ifndef SCIP_THREADSAFE_MESSAGEHDLRS
208  SCIP_CALL_ABORT( SCIPcreateMesshdlrPThreads(1) );
209  SCIPmessageSetDefaultHandler();
210 #endif
211 
212  if( comm->getRank() == 0 )
213  {
214  if( argc < 3 )
215  {
217  return 1;
218  }
219  paraParamSet->read(comm, argv[1]);
220 
221  paraParamSet->bcast(comm, 0);
222  comm->lcInit(paraParamSet);
223  ParaInitiator *paraInitiator = new ScipParaInitiator(comm, paraTimer);
224  setUserPlugins(paraInitiator);
225  if( paraInitiator->init(paraParamSet, argc, argv) )
226  {
227  if( dynamic_cast<ScipParaInitiator *>(paraInitiator)->isSolvedAtInit() )
228  {
229  paraInitiator->outputFinalSolverStatistics(0, paraTimer->getElapsedTime());
230  delete paraInitiator;
231  delete paraParamSet;
232  delete paraTimer;
233  if( detTimer ) delete detTimer;
234 // sysTimer.stop();
235 // std::cout << "[ Rank: " << comm->getRank() << " ], UTime = " << sysTimer.getUTime()
236 // << ", STime = " << sysTimer.getSTime() << ", RTime = " << sysTimer.getRTime() << std::endl;
237  comm->abort();
238  delete comm;
239 #ifdef UG_WITH_UGS
240  if( commUgs ) delete commUgs;
241 #endif
242  return 0;
243  }
244  }
245  std::cout << "** Initiatior was initilized after " << paraTimer->getElapsedTime() << " sec." << std::endl;
246  ParaInstance *paraInstance = paraInitiator->getParaInstance();
247  if( paraParamSet->getIntParamValue(OutputParaParams) > 0 )
248  {
249  outputParaParamSet(paraParamSet, paraInitiator);
250  outputSolverParams(paraParamSet, paraInitiator);
251  }
252  paraInstance->bcast(comm, 0, paraParamSet->getIntParamValue(InstanceTransferMethod) );
253  paraInitiator->sendSolverInitializationMessage(); // This messages should be received in constructor of the target Solver
254  std::cout << "** Instance data were sent to all solvers after " << paraTimer->getElapsedTime() << " sec." << std::endl;
256  if( paraParamSet->getBoolParamValue(Deterministic) )
257  {
258  detTimer = new ScipParaDeterministicTimer();
259  }
260  if( dynamic_cast<ScipParaInitiator *>(paraInitiator)->isSolvedAtInit() )
261  {
262 #ifdef UG_WITH_UGS
263  paraLc = new ScipParaLoadCoordinator(commUgs, comm, paraParamSet, paraInitiator, &racingSolversExist, paraTimer, detTimer);
264 #else
265  paraLc = new ScipParaLoadCoordinator(comm, paraParamSet, paraInitiator, &racingSolversExist, paraTimer, detTimer);
266 #endif
267  delete paraLc;
268  delete paraInitiator;
269  delete paraParamSet;
270  delete paraTimer;
271  if( detTimer ) delete detTimer;
272 
273 // sysTimer.stop();
274 // std::cout << "[ Rank: " << comm->getRank() << " ], UTime = " << sysTimer.getUTime()
275 // << ", STime = " << sysTimer.getSTime() << ", RTime = " << sysTimer.getRTime() << std::endl;
276 
277  comm->abort();
278  delete comm;
279 #ifdef UG_WITH_UGS
280  if( commUgs ) delete commUgs;
281 #endif
282  return 0;
283  }
284  else
285  {
286 #ifdef UG_WITH_UGS
287  paraLc = new ScipParaLoadCoordinator(commUgs, comm, paraParamSet, paraInitiator, &racingSolversExist, paraTimer, detTimer);
288 #else
289  paraLc = new ScipParaLoadCoordinator(comm, paraParamSet, paraInitiator, &racingSolversExist, paraTimer, detTimer);
290 #endif
291  }
292  if( paraInitiator->isWarmStarted() )
293  {
294 #ifdef UG_WITH_ZLIB
295  paraLc->warmStart();
296 #endif
297  }
298  else
299  {
300  if( paraParamSet->getIntParamValue(RampUpPhaseProcess) == 0 ||
301  paraParamSet->getIntParamValue(RampUpPhaseProcess) == 3 )
302  {
303  ParaTask *rootNode = new BbParaNodeMpi(
304  TaskId(), TaskId(), 0, -DBL_MAX, -DBL_MAX, -DBL_MAX,
305  dynamic_cast<ScipParaInitiator *>(paraInitiator)->makeRootNodeDiffSubproblem());
306  paraLc->run(rootNode);
307  }
308  else if( paraParamSet->getIntParamValue(RampUpPhaseProcess) >= 1 &&
309  paraParamSet->getIntParamValue(RampUpPhaseProcess) <= 2 ) // racing ramp-up
310  {
311  ParaRacingRampUpParamSet **racingRampUpParams = new ParaRacingRampUpParamSetPtr[comm->getSize()];
312  paraInitiator->generateRacingRampUpParameterSets( (comm->getSize()-1), racingRampUpParams );
313  for( int i = 1; i < comm->getSize(); i++ )
314  {
315  int noKeep = 0;
317  comm->send( &noKeep, 1, ParaINT, i, UG::TagKeepRacing)
318  );
320  racingRampUpParams[i-solverOrigin]->send(comm, i)
321  );
322  }
323  ParaTask *rootNode = new BbParaNodeMpi(
324  TaskId(), TaskId(), 0, -DBL_MAX, -DBL_MAX, -DBL_MAX,
325  dynamic_cast<ScipParaInitiator *>(paraInitiator)->makeRootNodeDiffSubproblem());
326  paraLc->run(rootNode, (comm->getSize()-1), racingRampUpParams );
327  for( int i = 1; i < comm->getSize(); i++ )
328  {
329  if( racingRampUpParams[i-solverOrigin] ) delete racingRampUpParams[i-solverOrigin];
330  }
331  delete [] racingRampUpParams;
332  }
333  else
334  {
335  THROW_LOGICAL_ERROR2("Invalid RampUpPhaseProcess: ", paraParamSet->getIntParamValue(RampUpPhaseProcess) )
336  }
337  }
338  delete paraLc;
339  if( paraInitiator ) delete paraInitiator;
340  }
341  else
342  {
343  if( argc < 3 )
344  {
345  return 1;
346  }
347  paraParamSet->bcast(comm, 0);
348  comm->solverInit(paraParamSet);
349  int nNonLinearConsHdlrs = 0;
351  comm->bcast( &nNonLinearConsHdlrs, 1, ParaINT, 0 )
352  );
353  ParaInstance *paraInstance = comm->createParaInstance();
354  setUserPlugins(paraInstance);
355  if( nNonLinearConsHdlrs > 0 )
356  {
357  paraParamSet->setIntParamValue(InstanceTransferMethod,2);
358  }
359  if( paraParamSet->getIntParamValue(InstanceTransferMethod) == 2 )
360  {
361  ScipParaInstanceMpi *scipParaInstanceMpi = dynamic_cast<ScipParaInstanceMpi *>(paraInstance);
362  scipParaInstanceMpi->setFileName(argv[2]);
363  }
364  paraInstance->bcast(comm, 0, paraParamSet->getIntParamValue(InstanceTransferMethod) );
365  if( paraParamSet->getBoolParamValue(Deterministic) )
366  {
367  detTimer = new ScipParaDeterministicTimer();
368  }
369  ParaSolver *paraSolver = new ScipParaSolver(argc, argv, comm, paraParamSet, paraInstance, detTimer);
370  // setUserPlugins(paraSolver); too late!! user plugin is necessary when instance data are read
371  dynamic_cast<ScipParaSolver *>(paraSolver)->setProblemFileName(argv[2]);
372  // if( paraParamSet->getIntParamValue(RampUpPhaseProcess) == 0 || paraSolver->isWarmStarted() )
373  if( paraParamSet->getIntParamValue(RampUpPhaseProcess) == 0 ||
374  paraParamSet->getIntParamValue(RampUpPhaseProcess) == 3 )
375  {
376  paraSolver->run();
377  }
378  else if( paraParamSet->getIntParamValue(RampUpPhaseProcess) >= 1 &&
379  paraParamSet->getIntParamValue(RampUpPhaseProcess) <= 2 ) // racing ramp-up
380  {
381  int source;
382  int tag;
383  (void)comm->probe(&source, &tag);
384  if( tag == TagKeepRacing )
385  {
386  int keep = 0;
388  comm->receive( &keep, 1, ParaINT, 0, UG::TagKeepRacing)
389  );
390  if( keep == 0 )
391  {
392  dynamic_cast<BbParaSolver *>(paraSolver)->setKeepRacing(false);
393  }
394  else
395  {
396  dynamic_cast<BbParaSolver *>(paraSolver)->setKeepRacing(true);
397  }
398  (void)comm->probe(&source, &tag);
399  ParaRacingRampUpParamSet *racingRampUpParamSet = new ScipParaRacingRampUpParamSetMpi();
401  racingRampUpParamSet->receive(comm, 0)
402  );
403  paraSolver->run( racingRampUpParamSet );
404  // delete racingRampUpParamSet; // racingRampUpParamSet is set in Solver object and deleted in the object
405  }
406  else
407  {
408  if( tag == TagTerminateRequest )
409  {
411  comm->receive( NULL, 0, ParaBYTE, source, TagTerminateRequest )
412  );
413  // when solver is deleted, solver's destructor sends termination status
414  }
415  else
416  {
417  THROW_LOGICAL_ERROR2("Invalid Tag is recicv3ed in ParaSCIP solver main: ", tag )
418  }
419  }
420  }
421  else
422  {
423  THROW_LOGICAL_ERROR2("Invalid RampUpPhaseProcess: ", paraParamSet->getIntParamValue(RampUpPhaseProcess) )
424  }
425  delete paraSolver;
426  //if( paraInstance ) delete paraInstance; /** deleted in paraSolver destructor */
427  }
428 
429  delete paraParamSet;
430 
431 // sysTimer.stop();
432 // std::cout << "[ Rank: " << comm->getRank() << " ], UTime = " << sysTimer.getUTime()
433 // << ", STime = " << sysTimer.getSTime() << ", RTime = " << sysTimer.getRTime() << std::endl;
434 
435 
436 #ifndef SCIP_THREADSAFE_MESSAGEHDLRS
437  SCIPfreeMesshdlrPThreads();
438 #endif
439 
440  delete paraTimer;
441  if( detTimer ) delete detTimer;
442 
443  if( racingSolversExist ) comm->abort();
444 
445  delete comm;
446 
447 #ifdef UG_WITH_UGS
448  if( commUgs ) delete commUgs;
449 #endif
450 
451  return 0;
452 
453 } /* END main */
virtual void generateRacingRampUpParameterSets(int nParamSets, ParaRacingRampUpParamSet **racingRampUpParamSets)=0
generate racing ramp-up parameter sets TODO: this function may be in inherited class ...
void outputSolverParams(ParaParamSet *paraParamSet, ParaInitiator *paraInitiator)
Definition: parascip.cpp:113
void lcInit(ParaParamSet *paraParamSet)
initializer for LoadCoordinator
Definition: paraCommMpi.cpp:69
UG::ParaInstance * createParaInstance()
ParaDeterministicTimer extension for SCIP.
void outputCommandLineMessages(char **argv)
Definition: parascip.cpp:64
ParaInstance extenstion for SCIP solver.
bool isWarmStarted()
check if the execution is warm started (restarted) or not
static const int LogSolvingStatusFilePath
Definition: paraParamSet.h:127
static ScipParaCommTh * comm
Definition: fscip.cpp:73
static ScipParaParamSet * paraParamSet
Definition: fscip.cpp:74
virtual double getElapsedTime()=0
get elapsed time
static const int TagTerminateRequest
Definition: paraTagDef.h:56
static ScipParaInitiator * paraInitiator
Definition: fscip.cpp:76
void init(int argc, char **argv)
SCIP ParaComm extension for MPI communication.
int getRank()
get rank of caller&#39;s thread
Definition: paraCommMpi.h:213
virtual int bcast(ParaComm *comm, int rank, int method)=0
broadcast function to all solvers
static const int OutputParaParams
Definition: paraParamSet.h:87
static ScipParaLoadCoordinator * paraLc
Definition: fscip.cpp:77
void outputParaParamSet(ParaParamSet *paraParamSet, ParaInitiator *paraInitiator)
Definition: parascip.cpp:83
virtual int bcast(ParaComm *comm, int root)=0
broadcast ParaParams
class BbParaSolver
Definition: bbParaSolver.h:63
void setUserPlugins(ParaInitiator *initiator)
void setFileName(const char *inFileName)
Class for initiator.
Definition: paraInitiator.h:62
TaskId class.
Definition: paraTask.h:222
class for deterministic timer
virtual void writeSolverParameters(std::ostream *os)=0
write solver runtime parameters
virtual const char * getProbName()=0
get problem name
#define PARA_COMM_CALL(paracommcall)
Definition: paraComm.h:47
static const int Deterministic
Definition: paraParamSet.h:76
virtual int init(ParaParamSet *params, int argc, char **argv)=0
initialize initiator
virtual void run()=0
run this Solver
int getSize()
get size of this communicator, which indicates how many threads in a UG process
Definition: paraCommMpi.h:223
ParaSolver extension for SCIP: Parallelized solver implementation for SCIP.
class ParaTimerMpi (Timer used in MPI communication)
Definition: paraTimerMpi.h:50
virtual void outputFinalSolverStatistics(std::ostream *os, double time)=0
output final solver statistics
class BbParaNodeMpi
Definition: bbParaNodeMpi.h:52
virtual int send(void *bufer, int count, const int datatypeId, int dest, const int tag)
send function for standard ParaData types
Parameter set for UG framework.
virtual void sendSolverInitializationMessage()=0
send solver initialization message
const char * getPrefixWarm()
get prefix of warm start (restart) files
System timer.
Base class for racing ramp-up parameter set.
bool probe(int *source, int *tag)
probe function which waits a new message
virtual void run()=0
run function to start main process
Base class for instance data.
class ParaParamSet
Definition: paraParamSet.h:850
int main(int argc, char **argv)
Definition: parascip.cpp:148
class for instance data
Definition: paraInstance.h:50
Load Coordinator.
#define THROW_LOGICAL_ERROR2(msg1, msg2)
Definition: paraDef.h:69
virtual void init(ParaComm *paraComm)=0
if you want to set original initial time, you can do it init()
static const int InstanceTransferMethod
Class for LoadCoordinator.
const char * getStringParamValue(int param)
for char parameters
static const int ParaBYTE
Definition: paraComm.h:79
virtual void read(ParaComm *comm, const char *filename)
read ParaParams from file
Class ParaSysTimer.
Definition: paraSysTimer.h:107
Base class of initiator that maintains original problem and incumbent solution.
UG::ParaParamSet * createParaParamSet()
static const int Quiet
Definition: paraParamSet.h:71
void start(void)
start timer
static const int RampUpPhaseProcess
int receive(void *bufer, int count, const int datatypeId, int source, const int tag)
receive function for standard ParaData types
int bcast(void *buffer, int count, const int datatypeId, int root)
broadcast function for standard ParaData types
virtual int receive(ParaComm *comm, int source)=0
receive ParaRacingRampUpParamSet
virtual ParaInstance * getParaInstance()=0
get instance object
static const int TagKeepRacing
Definition: bbParaTagDef.h:69
void abort()
abort. How it works sometimes depends on communicator used
static const int ParaINT
Definition: paraComm.h:66
void write(std::ostream *os)
write ParaParams to output stream
int getIntParamValue(int param)
for int parameters
ParaInitiator extension for SCIP solver.
class ParaTimer
Definition: paraTimer.h:48
class ParaRacingRampUpParamSet (parameter set for racing ramp-up)
class ParaSolver
Definition: paraSolver.h:70
void setIntParamValue(int param, int value)
set int parameter value
void solverInit(ParaParamSet *paraParamSet)
initializer for Solvers
Definition: paraCommMpi.cpp:96
class ParaTask
Definition: paraTask.h:541
bool getBoolParamValue(int param)
for bool parameters