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