Scippy

SCIP

Solving Constraint Integer Programs

syncstore.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2017 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file syncstore.c
17  * @ingroup PARALLEL
18  * @brief the function definitions of the synchronization store
19  * @author Robert Lion Gottwald
20  * @author Stephen J. Maher
21  */
22 
23 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
24 
25 #include <assert.h>
26 
27 #include "scip/def.h"
28 #include "scip/pub_message.h"
29 #include "scip/concsolver.h"
30 #include "scip/struct_concsolver.h"
31 #include "scip/prob.h"
32 #include "scip/scip.h"
33 #include "blockmemshell/memory.h"
34 #include "tpi/tpi.h"
35 #include "scip/struct_syncstore.h"
36 #include "scip/concurrent.h"
37 #include "scip/syncstore.h"
38 #include "scip/boundstore.h"
39 
40 
41 /** computes the size of the array of synchronization datas, such that
42  * it cannot ever happen that a synchronization data is reused while still
43  * not read by any thread */
44 static
46  SCIP* scip /**< SCIP main datastructure */
47  )
48 {
49  int maxnsyncdelay;
50  SCIP_CALL_ABORT( SCIPgetIntParam(scip, "concurrent/sync/maxnsyncdelay", &maxnsyncdelay) );
51 
52  return 2 * (maxnsyncdelay + 1);
53 }
54 
55 /** creates and captures a new synchronization store */
57  SCIP_SYNCSTORE** syncstore /**< pointer to return the created synchronization store */
58  )
59 {
60  assert(syncstore != NULL);
61 
62  SCIPdebugMessage("SCIPsyncstoreCreate()\n");
63 
64  SCIP_ALLOC( BMSallocMemory(syncstore) );
65 
66  (*syncstore)->mode = SCIP_PARA_DETERMINISTIC; /* initialising the mode */
67  (*syncstore)->initialized = FALSE;
68  (*syncstore)->syncdata = NULL;
69  (*syncstore)->stopped = FALSE;
70  (*syncstore)->nuses = 1;
71  SCIP_CALL( SCIPtpiInitLock(&(*syncstore)->lock) );
72 
73  return SCIP_OKAY;
74 }
75 
76 /** releases a synchronization store */
78  SCIP_SYNCSTORE** syncstore /**< pointer to the synchronization store */
79  )
80 {
81  int references;
82 
83  assert(syncstore != NULL);
84  assert(*syncstore != NULL);
85 
86  SCIP_CALL( SCIPtpiAcquireLock(&(*syncstore)->lock) );
87  (*syncstore)->nuses -= 1;
88  references = (*syncstore)->nuses;
89  SCIP_CALL( SCIPtpiReleaseLock(&(*syncstore)->lock) );
90 
91  if( references == 0 )
92  {
93  if( (*syncstore)->initialized )
94  {
95  SCIP_CALL( SCIPsyncstoreExit(*syncstore) );
96  }
97 
98  assert(!(*syncstore)->initialized);
99  SCIPtpiDestroyLock(&(*syncstore)->lock);
100  BMSfreeMemory(syncstore);
101  }
102  else
103  {
104  *syncstore = NULL;
105  }
106 
107  return SCIP_OKAY;
108 }
109 
110 /** captures a synchronization store */
112  SCIP_SYNCSTORE* syncstore /**< the synchronization store */
113  )
114 {
115  SCIP_CALL( SCIPtpiAcquireLock(&syncstore->lock) );
116 
117  ++(syncstore->nuses);
118 
119  SCIP_CALL( SCIPtpiReleaseLock(&syncstore->lock) );
120 
121  return SCIP_OKAY;
122 }
123 
124 /** initialize the syncstore for the given SCIP instance */
126  SCIP* scip /**< SCIP main datastructure */
127  )
128 {
129  SCIP_SYNCSTORE* syncstore;
130  int i;
131  int j;
132  int paramode;
133 
134  assert(scip != NULL);
135  syncstore = SCIPgetSyncstore(scip);
136  assert(syncstore != NULL);
137  syncstore->mainscip = scip;
138  syncstore->lastsync = NULL;
139  syncstore->nsolvers = SCIPgetNConcurrentSolvers(scip);
140 
141  syncstore->ninitvars = SCIPgetNVars(scip);
142  SCIP_CALL( SCIPgetIntParam(scip, "concurrent/sync/maxnsols", &syncstore->maxnsols) );
143  SCIP_CALL( SCIPgetIntParam(scip, "concurrent/sync/maxnsyncdelay", &syncstore->maxnsyncdelay) );
144  SCIP_CALL( SCIPgetRealParam(scip, "concurrent/sync/minsyncdelay", &syncstore->minsyncdelay) );
145  SCIP_CALL( SCIPgetRealParam(scip, "concurrent/sync/freqinit", &syncstore->syncfreqinit) );
146  SCIP_CALL( SCIPgetRealParam(scip, "concurrent/sync/freqmax", &syncstore->syncfreqmax) );
147  syncstore->nsyncdata = getNSyncdata(scip);
148  SCIP_CALL( SCIPallocBlockMemoryArray(syncstore->mainscip, &(syncstore->syncdata), syncstore->nsyncdata) );
149 
150  for( i = 0; i < syncstore->nsyncdata; ++i )
151  {
152  syncstore->syncdata[i].syncnum = -1;
153  SCIP_CALL( SCIPboundstoreCreate(syncstore->mainscip, &syncstore->syncdata[i].boundstore, syncstore->ninitvars) );
154  SCIP_CALL( SCIPallocBlockMemoryArray(syncstore->mainscip, &syncstore->syncdata[i].solobj, syncstore->maxnsols) );
155  SCIP_CALL( SCIPallocBlockMemoryArray(syncstore->mainscip, &syncstore->syncdata[i].solsource, syncstore->maxnsols) );
156  SCIP_CALL( SCIPallocBlockMemoryArray(syncstore->mainscip, &syncstore->syncdata[i].sols, syncstore->maxnsols) );
157 
158  for( j = 0; j < syncstore->maxnsols; ++j )
159  {
160  SCIP_CALL( SCIPallocBlockMemoryArray(syncstore->mainscip, &syncstore->syncdata[i].sols[j], syncstore->ninitvars) );
161  }
162 
163  SCIP_CALL( SCIPtpiInitLock(&(syncstore->syncdata[i].lock)) );
164  SCIP_CALL( SCIPtpiInitCondition(&(syncstore->syncdata[i].allsynced)) );
165  }
166 
167  syncstore->initialized = TRUE;
168  syncstore->stopped = FALSE;
169 
170  SCIP_CALL( SCIPgetIntParam(scip, "parallel/mode", &paramode) );
171  syncstore->mode = (SCIP_PARALLELMODE) paramode;
172 
173  SCIP_CALL( SCIPtpiInit(syncstore->nsolvers, INT_MAX, FALSE) );
175 
176  if( syncstore->mode == SCIP_PARA_DETERMINISTIC )
177  {
178  /* in deterministic mode use the number of non-zeros and the number of variables to get a good
179  * syncdelay and maximum syncfreq
180  */
181  syncstore->minsyncdelay *= 0.01 * (SCIPgetNNZs(scip) * SCIPgetNVars(scip));
182  syncstore->syncfreqmax *= 0.01 * (SCIPgetNNZs(scip) * SCIPgetNVars(scip));
183  }
184 
185  return SCIP_OKAY;
186 }
187 
188 /** deinitializes the synchronization store */
190  SCIP_SYNCSTORE* syncstore /**< the synchronization store */
191  )
192 {
193  int i;
194  int j;
195 
196  assert(syncstore != NULL);
197  assert(syncstore->initialized);
198 
199  SCIP_CALL( SCIPtpiExit() );
200 
201  for( i = 0; i < syncstore->nsyncdata; ++i )
202  {
203  SCIPtpiDestroyLock(&(syncstore->syncdata[i].lock));
204  SCIPtpiDestroyCondition(&(syncstore->syncdata[i].allsynced));
205  SCIPfreeBlockMemoryArray(syncstore->mainscip, &syncstore->syncdata[i].solobj, syncstore->maxnsols);
206  SCIPfreeBlockMemoryArray(syncstore->mainscip, &syncstore->syncdata[i].solsource, syncstore->maxnsols);
207  SCIPboundstoreFree(syncstore->mainscip, &syncstore->syncdata[i].boundstore);
208 
209  for( j = 0; j < syncstore->maxnsols; ++j )
210  {
211  SCIPfreeBlockMemoryArray(syncstore->mainscip, &syncstore->syncdata[i].sols[j], syncstore->ninitvars);
212  }
213 
214  SCIPfreeBlockMemoryArray(syncstore->mainscip, &syncstore->syncdata[i].sols, syncstore->maxnsols);
215  }
216 
217  SCIPfreeBlockMemoryArray(syncstore->mainscip, &syncstore->syncdata, syncstore->nsyncdata);
218 
219  syncstore->initialized = FALSE;
220  syncstore->stopped = FALSE;
221 
222  return SCIP_OKAY;
223 }
224 
225 /** checks whether the solve-is-stopped flag in the syncstore has been set by any thread */
227  SCIP_SYNCSTORE* syncstore /**< the synchronization store */
228  )
229 {
230  SCIP_Bool stopped;
231 
232  SCIP_CALL_ABORT( SCIPtpiAcquireLock(&syncstore->lock) );
233 
234  stopped = syncstore->stopped;
235 
236  SCIP_CALL_ABORT( SCIPtpiReleaseLock(&syncstore->lock) );
237 
238  return stopped;
239 }
240 
241 /** sets the solve-is-stopped flag in the syncstore so that subsequent calls to
242  * SCIPsyncstoreSolveIsStopped will return the given value in any thread
243  */
245  SCIP_SYNCSTORE* syncstore, /**< the synchronization store */
246  SCIP_Bool stopped /**< flag if the solve is stopped */
247  )
248 {
249  SCIP_CALL_ABORT( SCIPtpiAcquireLock(&syncstore->lock) );
250 
251  syncstore->stopped = stopped;
252 
253  SCIP_CALL_ABORT( SCIPtpiReleaseLock(&syncstore->lock) );
254 }
255 
256 /** gets the upperbound from the last synchronization */
258  SCIP_SYNCSTORE* syncstore /**< the synchronization store */
259  )
260 {
261  assert(syncstore != NULL);
262  assert(syncstore->initialized);
263 
264  return syncstore->lastsync == NULL ? SCIPinfinity(syncstore->mainscip) : syncstore->lastsync->bestupperbound;
265 }
266 
267 /** gets the lowerbound from the last synchronization */
269  SCIP_SYNCSTORE* syncstore /**< the synchronization store */
270  )
271 {
272  assert(syncstore != NULL);
273  assert(syncstore->initialized);
274 
275  return syncstore->lastsync == NULL ? -SCIPinfinity(syncstore->mainscip) : syncstore->lastsync->bestlowerbound;
276 }
277 
278 /** gets the number of solutions from the last synchronization */
280  SCIP_SYNCSTORE* syncstore /**< the synchronization store */
281  )
282 {
283  assert(syncstore != NULL);
284  assert(syncstore->initialized);
285 
286  return syncstore->lastsync == NULL ? 0 : syncstore->lastsync->nsols;
287 }
288 
289 /** gets the number of boundchanges from the last synchronization */
291  SCIP_SYNCSTORE* syncstore /**< the synchronization store */
292  )
293 {
294  assert(syncstore != NULL);
295  assert(syncstore->initialized);
296 
297  return syncstore->lastsync == NULL ? 0 : SCIPboundstoreGetNChgs(syncstore->lastsync->boundstore);
298 }
299 
300 /** gets total memory used by all solvers from the last synchronization */
302  SCIP_SYNCSTORE* syncstore /**< the synchronization store */
303  )
304 {
305  assert(syncstore != NULL);
306  assert(syncstore->initialized);
307 
308  return syncstore->lastsync == NULL ? 0 : syncstore->lastsync->memtotal;
309 }
310 
311 /** gets the synchronization frequency from the last synchronization */
313  SCIP_SYNCSTORE* syncstore /**< the synchronization store */
314  )
315 {
316  assert(syncstore != NULL);
317  assert(syncstore->initialized);
318 
319  return syncstore->lastsync == NULL ? 0.0 : syncstore->lastsync->syncfreq;
320 }
321 
322 /** get synchronization data with given number. It is the responsibility of the caller
323  * to only ask for a synchronization number that still exists, which is checked
324  * with an assert in debug mode. */
326  SCIP_SYNCSTORE* syncstore, /**< the synchronization store */
327  SCIP_Longint syncnum /**< the number of the synchronization to start, which
328  * must be increasing between calls of the same thread */
329  )
330 {
331  int j;
332 
333  assert(syncstore != NULL);
334  assert(syncstore->initialized);
335 
336  j = syncnum % syncstore->nsyncdata;
337 
338  /* check if requested syncnumber still exists if in debug mode */
339  assert(syncstore->syncdata[j].syncnum == syncnum);
340 
341  return &syncstore->syncdata[j];
342 }
343 
344 /** get the next synchronization data that should be read and
345  * adjust the delay. Returns NULL if no more data should be read due to minimum delay */
347  SCIP_SYNCSTORE* syncstore, /**< the synchronization store */
348  SCIP_SYNCDATA* syncdata, /**< the synchronization data */
349  SCIP_Real syncfreq, /**< the current synchronization frequency */
350  SCIP_Longint writenum, /**< number of synchronizations the solver has written to */
351  SCIP_Real* delay /**< pointer holding the current synchronization delay */
352  )
353 {
354  SCIP_Real newdelay;
355  SCIP_Longint nextsyncnum;
356 
357  assert(syncstore != NULL);
358  assert(syncstore->initialized);
359  assert(delay != NULL);
360 
361  if( syncdata == NULL )
362  {
363  nextsyncnum = 0;
364  }
365  else
366  {
367  if( syncdata->status != SCIP_STATUS_UNKNOWN )
368  return NULL;
369 
370  nextsyncnum = syncdata->syncnum + 1;
371  }
372 
373  if( nextsyncnum == writenum )
374  return NULL;
375 
376  newdelay = *delay - syncfreq;
377 
378  /* if the delay would get too small we dont want to read the next syncdata.
379  * But due to the limited length of the syncdata array we might need to
380  * read this synchronization data anyways which is checked by the second part
381  * of the if condition
382  */
383  if( newdelay < syncstore->minsyncdelay && nextsyncnum >= writenum - syncstore->maxnsyncdelay )
384  return NULL;
385 
386  *delay = newdelay;
387  assert(syncstore->syncdata[nextsyncnum % syncstore->nsyncdata].syncnum == nextsyncnum);
388 
389  return &syncstore->syncdata[nextsyncnum % syncstore->nsyncdata];
390 }
391 
392 /** ensures that the given synchronization data has been written by
393  * all solvers upon return of this function and blocks the caller if necessary. */
395  SCIP_SYNCSTORE* syncstore, /**< the synchronization store */
396  SCIP_SYNCDATA* syncdata /**< the synchronization data */
397  )
398 {
399  assert(syncdata != NULL);
400  assert(syncstore != NULL);
401  assert(syncstore->initialized);
402 
403  /* check if waiting is required, make sure to hold the lock */
404  SCIP_CALL( SCIPtpiAcquireLock(&syncdata->lock) );
405 
406  while( syncdata->syncedcount < syncstore->nsolvers )
407  {
408  /* yes, so wait on the condition variable
409  * (automatically releases the lock and reacquires it after the waiting)
410  */
411  SCIP_CALL( SCIPtpiWaitCondition(&syncdata->allsynced, &syncdata->lock) );
412  }
413 
414  SCIP_CALL( SCIPtpiReleaseLock(&syncdata->lock) );
415 
416  return SCIP_OKAY;
417 }
418 
419 /** Start synchronization for the given concurrent solver.
420  * Needs to be followed by a call to SCIPsyncstoreFinishSync if
421  * the syncdata that is returned is not NULL
422  */
424  SCIP_SYNCSTORE* syncstore, /**< the synchronization store */
425  SCIP_Longint syncnum, /**< the number of the synchronization to start, which
426  * must be increasing between calls of the same thread */
427  SCIP_SYNCDATA** syncdata /**< pointer to return the synchronization data */
428  )
429 {
430  int i;
431 
432  assert(syncdata != NULL);
433  assert(syncstore != NULL);
434  assert(syncstore->initialized);
435 
436  if( SCIPsyncstoreSolveIsStopped(syncstore) )
437  {
438  *syncdata = NULL;
439  return SCIP_OKAY;
440  }
441 
442  i = syncnum % syncstore->nsyncdata;
443  *syncdata = &syncstore->syncdata[i];
444  assert(*syncdata != NULL);
445 
446  SCIP_CALL( SCIPtpiAcquireLock(&(*syncdata)->lock) );
447 
448  if( (*syncdata)->syncnum != syncnum )
449  {
450  SCIPboundstoreClear((*syncdata)->boundstore);
451  (*syncdata)->nsols = 0;
452  (*syncdata)->memtotal = SCIPgetMemTotal(syncstore->mainscip);
453  (*syncdata)->syncedcount = 0;
454  (*syncdata)->bestupperbound = SCIPinfinity(syncstore->mainscip);
455  (*syncdata)->bestlowerbound = -(*syncdata)->bestupperbound;
456  (*syncdata)->status = SCIP_STATUS_UNKNOWN;
457  (*syncdata)->winner = 0;
458  (*syncdata)->syncnum = syncnum;
459  (*syncdata)->syncfreq = 0.0;
460  }
461 
462  return SCIP_OKAY;
463 }
464 
465 /** finishes synchronization for the synchronization data */
467  SCIP_SYNCSTORE* syncstore, /**< the synchronization store */
468  SCIP_SYNCDATA** syncdata /**< the synchronization data */
469  )
470 {
471  SCIP_Bool printline = FALSE;
472 
473  assert(syncdata != NULL);
474  assert((*syncdata) != NULL);
475  assert(syncstore != NULL);
476  assert(syncstore->initialized);
477 
478  ++(*syncdata)->syncedcount;
479 
480  if( (*syncdata)->syncedcount == syncstore->nsolvers )
481  {
482  if( (*syncdata)->status != SCIP_STATUS_UNKNOWN )
484 
485  syncstore->lastsync = *syncdata;
486  printline = TRUE;
487 
488  SCIP_CALL( SCIPtpiBroadcastCondition(&(*syncdata)->allsynced) );
489  }
490 
491  SCIP_CALL( SCIPtpiReleaseLock(&(*syncdata)->lock) );
492 
493  if( printline )
494  {
496  }
497 
498  *syncdata = NULL;
499 
500  return SCIP_OKAY;
501 }
502 
503 /** gets status in synchronization data */
505  SCIP_SYNCDATA* syncdata /**< the synchronization data */
506  )
507 {
508  assert(syncdata != NULL);
509 
510  return syncdata->status;
511 }
512 
513 /** gets the solver that had the best status, or -1 if solve is not stopped yet */
515  SCIP_SYNCSTORE* syncstore /**< the synchronization store */
516  )
517 {
518  assert(syncstore != NULL);
519  assert(syncstore->initialized);
520 
521  if( syncstore->lastsync == NULL || syncstore->lastsync->status == SCIP_STATUS_UNKNOWN )
522  return -1;
523 
524  return syncstore->lastsync->winner;
525 }
526 
527 /** how many solvers have already finished synchronizing on this sychronization data */
529  SCIP_SYNCDATA* syncdata /**< the synchronization data */
530  )
531 {
532  assert(syncdata != NULL);
533 
534  return syncdata->syncedcount;
535 }
536 
537 /** how many solvers have are running concurrently */
539  SCIP_SYNCSTORE* syncstore /**< the synchronization store */
540  )
541 {
542  assert(syncstore != NULL);
543  assert(syncstore->initialized);
544 
545  return syncstore->nsolvers;
546 }
547 
548 
549 /** read amount total memory used from synchronization data */
551  SCIP_SYNCDATA* syncdata /**< the synchronization data */
552  )
553 {
554  assert(syncdata != NULL);
555 
556  return syncdata->memtotal;
557 }
558 
559 /** read the synchronization frequency from a synchronization data */
561  SCIP_SYNCDATA* syncdata /**< the synchronization data */
562  )
563 {
564  assert(syncdata != NULL);
565 
566  return syncdata->syncfreq;
567 }
568 
569 /** read the upperbound stored in a synchronization data */
571  SCIP_SYNCDATA* syncdata /**< the synchronization data */
572  )
573 {
574  assert(syncdata != NULL);
575 
576  return syncdata->bestupperbound;
577 }
578 
579 /** read the lowerbound stored in a synchronization data */
581  SCIP_SYNCDATA* syncdata /**< the synchronization data */
582  )
583 {
584  assert(syncdata != NULL);
585 
586  return syncdata->bestlowerbound;
587 }
588 
589 /** read the solutions stored in a synchronization data */
591  SCIP_SYNCDATA* syncdata, /**< the synchronization data */
592  SCIP_Real*** solvalues, /**< array of buffers containing the solution values */
593  int** solowner, /**< array of ownerids of solutions */
594  int* nsols /**< pointer to return number of solutions */
595  )
596 {
597  assert(syncdata != NULL);
598  assert(solvalues != NULL);
599  assert(solowner != NULL);
600  assert(nsols != NULL);
601 
602  *solvalues = syncdata->sols;
603  *solowner = syncdata->solsource;
604  *nsols = syncdata->nsols;
605 }
606 
607 /** read bound changes stored in the synchronization data */
609  SCIP_SYNCDATA* syncdata /**< the synchronization data */
610  )
611 {
612  assert(syncdata != NULL);
613 
614  return syncdata->boundstore;
615 }
616 
617 /** write the synchronization frequency to a synchronization data */
619  SCIP_SYNCSTORE* syncstore, /**< the synchronization store */
620  SCIP_SYNCDATA* syncdata, /**< the synchronization data */
621  SCIP_Real syncfreq /**< the synchronization frequency */
622  )
623 {
624  assert(syncstore != NULL);
625  assert(syncstore->initialized);
626  assert(syncdata != NULL);
627 
628  syncdata->syncfreq = MIN(syncfreq, syncstore->syncfreqmax);
629 }
630 
631 /** set status in the synchronization data */
633  SCIP_SYNCDATA* syncdata, /**< the synchronization data the upperbound should be added to */
634  SCIP_STATUS status, /**< the status */
635  int solverid /**< identifier of te solver that has this status */
636  )
637 {
638  assert(syncdata != NULL);
639 
640  /* check if status is better than current one (closer to SCIP_STATUS_OPTIMAL),
641  * break ties by the solverid, and remember the solver wit the best status
642  * so that the winner will be selected deterministically
643  */
644  if( syncdata->status < SCIP_STATUS_OPTIMAL )
645  {
646 
647  if( status > syncdata->status || (status == syncdata->status && solverid < syncdata->winner) )
648  {
649  syncdata->status = status;
650  syncdata->winner = solverid;
651  }
652  }
653  else if( syncdata->status > SCIP_STATUS_OPTIMAL && status >= SCIP_STATUS_OPTIMAL )
654  {
655  if( status < syncdata->status || (status == syncdata->status && solverid < syncdata->winner) )
656  {
657  syncdata->status = status;
658  syncdata->winner = solverid;
659  }
660  }
661 }
662 
663 /** adds memory used to the synchronization data */
665  SCIP_SYNCDATA* syncdata, /**< the synchronization data the solution should be added to */
666  SCIP_Longint memtotal /**< the number of bytes used */
667  )
668 {
669  assert(syncdata != NULL);
670 
671  syncdata->memtotal += memtotal;
672 }
673 
674 /** set upperbound to the synchronization data */
676  SCIP_SYNCDATA* syncdata, /**< the synchronization data the upperbound should be added to */
677  SCIP_Real upperbound /**< the upperbound */
678  )
679 {
680  assert(syncdata != NULL);
681 
682  syncdata->bestupperbound = MIN(syncdata->bestupperbound, upperbound);
683 }
684 
685 /** set lowerbound to the synchronization data */
687  SCIP_SYNCDATA* syncdata, /**< the synchronization data the lowerbound should be added to */
688  SCIP_Real lowerbound /**< the lowerbound */
689  )
690 {
691  assert(syncdata != NULL);
692 
693  syncdata->bestlowerbound = MAX(syncdata->bestlowerbound, lowerbound);
694 }
695 
696 /** gives a buffer to store the solution values, or NULL if solution should not be stored
697  * because there are already better solutions stored.
698  */
700  SCIP_SYNCSTORE* syncstore, /**< the synchronization store */
701  SCIP_SYNCDATA* syncdata, /**< the synchronization data the solution should be added to */
702  SCIP_Real solobj, /**< the objective value of the solution */
703  int ownerid, /**< an identifier for the owner of the solution, e.g. the thread number */
704  SCIP_Real** buffer /**< pointer to return a buffer for the solution values, which must be set
705  * if the buffer is not NULL */
706  )
707 {
708  int pos;
709  int i;
710 
711  assert(syncstore != NULL);
712  assert(syncstore->initialized);
713  assert(syncdata != NULL);
714  assert(buffer != NULL);
715 
716  for( pos = 0; pos < syncdata->nsols; ++pos )
717  {
718  if( syncdata->solobj[pos] < solobj || (syncdata->solobj[pos] == solobj && ownerid < syncdata->solsource[pos]) ) /*lint !e777*/
719  break;
720  }
721 
722  if( syncdata->nsols < syncstore->maxnsols )
723  {
724  for( i = syncdata->nsols; i > pos; --i )
725  {
726  syncdata->solobj[i] = syncdata->solobj[i - 1];
727  syncdata->solsource[i] = syncdata->solsource[i - 1];
728  SCIPswapPointers((void**) &syncdata->sols[i], (void**) &syncdata->sols[i - 1]);
729  }
730 
731  ++syncdata->nsols;
732  }
733  else
734  {
735  --pos;
736 
737  for( i = 0; i < pos; ++i )
738  {
739  syncdata->solobj[i] = syncdata->solobj[i + 1];
740  syncdata->solsource[i] = syncdata->solsource[i + 1];
741  SCIPswapPointers((void**) &syncdata->sols[i], (void**) &syncdata->sols[i + 1]);
742  }
743  }
744 
745  if( pos >= 0 )
746  {
747  syncdata->solobj[pos] = solobj;
748  syncdata->solsource[pos] = ownerid;
749  *buffer = syncdata->sols[pos];
750  }
751  else
752  {
753  *buffer = NULL;
754  }
755 }
756 
757 /** adds bound changes to the synchronization data */
759  SCIP_SYNCSTORE* syncstore, /**< the synchronization store */
760  SCIP_SYNCDATA* syncdata, /**< the synchronization data */
761  SCIP_BOUNDSTORE* boundstore /**< bound store containing the bounds to add */
762  )
763 {
764  assert(syncstore != NULL);
765  assert(syncstore->initialized);
766  assert(syncdata != NULL);
767  assert(boundstore != NULL);
768 
769  SCIP_CALL( SCIPboundstoreMerge(syncstore->mainscip, syncdata->boundstore, boundstore) );
770 
771  return SCIP_OKAY;
772 }
773 
774 /** is synchronization store initialized */
776  SCIP_SYNCSTORE* syncstore /**< the synchronization store */
777  )
778 {
779  assert(syncstore != NULL);
780 
781  return syncstore->initialized;
782 }
783 
784 /** returns the mode of the synchronization store */
786  SCIP_SYNCSTORE* syncstore /**< the synchronization store */
787  )
788 {
789  assert(syncstore != NULL);
790 
791  return syncstore->mode;
792 }
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip.h:21975
SCIP_PARALLELMODE mode
SCIP_RETCODE SCIPtpiWaitCondition(SCIP_CONDITION *condition, SCIP_LOCK *lock)
Definition: tpi_openmp.c:286
SCIP_SYNCDATA * lastsync
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip.h:21958
SCIP_RETCODE SCIPsyncstoreRelease(SCIP_SYNCSTORE **syncstore)
Definition: syncstore.c:77
int SCIPboundstoreGetNChgs(SCIP_BOUNDSTORE *boundstore)
Definition: boundstore.c:188
int SCIPgetNConcurrentSolvers(SCIP *scip)
Definition: concurrent.c:107
SCIP_RETCODE SCIPsyncstoreEnsureAllSynced(SCIP_SYNCSTORE *syncstore, SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:394
SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
Definition: scip.c:4461
SCIP_STATUS SCIPsyncdataGetStatus(SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:504
void SCIPsyncdataSetUpperbound(SCIP_SYNCDATA *syncdata, SCIP_Real upperbound)
Definition: syncstore.c:675
SCIP_SYNCDATA * SCIPsyncstoreGetSyncdata(SCIP_SYNCSTORE *syncstore, SCIP_Longint syncnum)
Definition: syncstore.c:325
SCIP_RETCODE SCIPprintDisplayLine(SCIP *scip, FILE *file, SCIP_VERBLEVEL verblevel, SCIP_Bool endline)
Definition: scip.c:44946
void SCIPswapPointers(void **pointer1, void **pointer2)
Definition: misc.c:8996
#define FALSE
Definition: def.h:64
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:46050
#define TRUE
Definition: def.h:63
void SCIPsyncdataSetLowerbound(SCIP_SYNCDATA *syncdata, SCIP_Real lowerbound)
Definition: syncstore.c:686
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_RETCODE SCIPtpiBroadcastCondition(SCIP_CONDITION *condition)
Definition: tpi_openmp.c:274
SCIP_RETCODE SCIPtpiAcquireLock(SCIP_LOCK *lock)
SCIP_Longint SCIPgetNNZs(SCIP *scip)
Definition: scip.c:41635
datastructures for concurrent solvers
SCIP_RETCODE SCIPtpiInitCondition(SCIP_LOCK *lock)
datastructures for concurrent solvers
static int getNSyncdata(SCIP *scip)
Definition: syncstore.c:45
#define SCIPdebugMessage
Definition: pub_message.h:77
the struct definitions for the synchronization store
#define BMSfreeMemory(ptr)
Definition: memory.h:104
SCIP_Real SCIPsyncstoreGetLastUpperbound(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:257
SCIP_SYNCDATA * SCIPsyncstoreGetNextSyncdata(SCIP_SYNCSTORE *syncstore, SCIP_SYNCDATA *syncdata, SCIP_Real syncfreq, SCIP_Longint writenum, SCIP_Real *delay)
Definition: syncstore.c:346
void SCIPsyncdataGetSolutionBuffer(SCIP_SYNCSTORE *syncstore, SCIP_SYNCDATA *syncdata, SCIP_Real solobj, int ownerid, SCIP_Real **buffer)
Definition: syncstore.c:699
SCIP_PARALLELMODE SCIPsyncstoreGetMode(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:785
void SCIPsyncdataSetSyncFreq(SCIP_SYNCSTORE *syncstore, SCIP_SYNCDATA *syncdata, SCIP_Real syncfreq)
Definition: syncstore.c:618
SCIP_RETCODE SCIPtpiReleaseLock(SCIP_LOCK *lock)
internal methods for storing and manipulating the main problem
SCIP_Real SCIPsyncstoreGetLastLowerbound(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:268
SCIP_Bool SCIPsyncstoreIsInitialized(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:775
void SCIPboundstoreFree(SCIP *scip, SCIP_BOUNDSTORE **boundstore)
Definition: boundstore.c:51
the type definitions for the SCIP parallel interface
SCIP_Real minsyncdelay
void SCIPsyncdataSetStatus(SCIP_SYNCDATA *syncdata, SCIP_STATUS status, int solverid)
Definition: syncstore.c:632
struct SCIP_SyncData SCIP_SYNCDATA
#define NULL
Definition: lpi_spx1.cpp:137
the interface of the boundstore structure
SCIP_RETCODE SCIPgetIntParam(SCIP *scip, const char *name, int *value)
Definition: scip.c:4423
SCIP_Real SCIPsyncstoreGetLastSyncfreq(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:312
#define SCIP_CALL(x)
Definition: def.h:316
SCIP_Bool initialized
SCIP_SYNCDATA * syncdata
the function declarations for the synchronization store
SCIP_RETCODE SCIPtpiExit(void)
Definition: tpi_none.c:82
#define SCIP_Bool
Definition: def.h:61
void SCIPsyncdataAddMemTotal(SCIP_SYNCDATA *syncdata, SCIP_Longint memtotal)
Definition: syncstore.c:664
enum SCIP_Status SCIP_STATUS
Definition: type_stat.h:57
SCIP_RETCODE SCIPautoselectDisps(SCIP *scip)
Definition: scip.c:9378
SCIP_SYNCSTORE * SCIPgetSyncstore(SCIP *scip)
Definition: scip.c:41293
SCIP_RETCODE SCIPtpiInitLock(SCIP_LOCK *lock)
SCIP_RETCODE SCIPsyncstoreInit(SCIP *scip)
Definition: syncstore.c:125
SCIP_Real SCIPsyncdataGetLowerbound(SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:580
enum SCIP_Parallelmode SCIP_PARALLELMODE
SCIP_RETCODE SCIPsyncstoreStartSync(SCIP_SYNCSTORE *syncstore, SCIP_Longint syncnum, SCIP_SYNCDATA **syncdata)
Definition: syncstore.c:423
#define MAX(x, y)
Definition: tclique_def.h:75
SCIP_Longint SCIPsyncdataGetMemTotal(SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:550
SCIP_Longint SCIPsyncstoreGetLastMemTotal(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:301
int SCIPsyncstoreGetWinner(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:514
helper functions for concurrent scip solvers
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:11680
SCIP_RETCODE SCIPsyncstoreExit(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:189
SCIP_RETCODE SCIPsyncstoreCreate(SCIP_SYNCSTORE **syncstore)
Definition: syncstore.c:56
int SCIPsyncdataGetNSynced(SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:528
int SCIPsyncstoreGetLastNSols(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:279
SCIP_Longint SCIPgetMemTotal(SCIP *scip)
Definition: scip.c:45809
void SCIPtpiDestroyLock(SCIP_LOCK *lock)
void SCIPtpiDestroyCondition(SCIP_LOCK *lock)
SCIP_BOUNDSTORE * SCIPsyncdataGetBoundChgs(SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:608
void SCIPsyncstoreSetSolveIsStopped(SCIP_SYNCSTORE *syncstore, SCIP_Bool stopped)
Definition: syncstore.c:244
public methods for message output
SCIP_Real SCIPsyncdataGetSyncFreq(SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:560
SCIP_Real syncfreqmax
#define SCIP_Real
Definition: def.h:145
#define MIN(x, y)
Definition: memory.c:75
SCIP_Real syncfreqinit
#define BMSallocMemory(ptr)
Definition: memory.h:78
SCIP_Bool SCIPsyncstoreSolveIsStopped(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:226
#define SCIP_Longint
Definition: def.h:130
SCIP_RETCODE SCIPboundstoreCreate(SCIP *scip, SCIP_BOUNDSTORE **boundstore, int nvars)
Definition: boundstore.c:30
SCIP_RETCODE SCIPsyncstoreFinishSync(SCIP_SYNCSTORE *syncstore, SCIP_SYNCDATA **syncdata)
Definition: syncstore.c:466
SCIP_RETCODE SCIPboundstoreMerge(SCIP *scip, SCIP_BOUNDSTORE *target, SCIP_BOUNDSTORE *source)
Definition: boundstore.c:115
SCIP_RETCODE SCIPsyncstoreCapture(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:111
int SCIPsyncstoreGetLastNBounds(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:290
common defines and data types used in all packages of SCIP
SCIP_RETCODE SCIPtpiInit(int nthreads, int queuesize, SCIP_Bool blockwhenfull)
Definition: tpi_none.c:68
#define SCIP_CALL_ABORT(x)
Definition: def.h:295
SCIP_Real SCIPsyncdataGetUpperbound(SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:570
#define SCIP_ALLOC(x)
Definition: def.h:327
int SCIPsyncstoreGetNSolvers(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:538
SCIP_RETCODE SCIPsyncdataAddBoundChanges(SCIP_SYNCSTORE *syncstore, SCIP_SYNCDATA *syncdata, SCIP_BOUNDSTORE *boundstore)
Definition: syncstore.c:758
void SCIPsyncdataGetSolutions(SCIP_SYNCDATA *syncdata, SCIP_Real ***solvalues, int **solowner, int *nsols)
Definition: syncstore.c:590
SCIP callable library.
void SCIPboundstoreClear(SCIP_BOUNDSTORE *boundstore)
Definition: boundstore.c:137
memory allocation routines