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