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-2020 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 visit scipopt.org. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file syncstore.c
17  * @ingroup PARALLEL
18  * @brief the function definitions of the synchronization store
19  * @author Leona 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 
51  SCIP_CALL_ABORT( SCIPgetIntParam(scip, "concurrent/sync/maxnsyncdelay", &maxnsyncdelay) );
52 
53  return 2 * (maxnsyncdelay + 1);
54 }
55 
56 /** creates and captures a new synchronization store */
58  SCIP_SYNCSTORE** syncstore /**< pointer to return the created synchronization store */
59  )
60 {
61  assert(syncstore != NULL);
62 
63  SCIPdebugMessage("SCIPsyncstoreCreate()\n");
64 
65  SCIP_ALLOC( BMSallocMemory(syncstore) );
66 
67  (*syncstore)->mode = SCIP_PARA_DETERMINISTIC; /* initialising the mode */
68  (*syncstore)->initialized = FALSE;
69  (*syncstore)->syncdata = NULL;
70  (*syncstore)->stopped = FALSE;
71  (*syncstore)->nuses = 1;
72  SCIP_CALL( SCIPtpiInitLock(&(*syncstore)->lock) );
73 
74  return SCIP_OKAY;
75 }
76 
77 /** releases a synchronization store */
79  SCIP_SYNCSTORE** syncstore /**< pointer to the synchronization store */
80  )
81 {
82  int references;
83 
84  assert(syncstore != NULL);
85  if( *syncstore == NULL )
86  return SCIP_OKAY;
87 
88  SCIP_CALL( SCIPtpiAcquireLock(&(*syncstore)->lock) );
89  (*syncstore)->nuses -= 1;
90  references = (*syncstore)->nuses;
91  SCIP_CALL( SCIPtpiReleaseLock(&(*syncstore)->lock) );
92 
93  if( references == 0 )
94  {
95  if( (*syncstore)->initialized )
96  {
97  SCIP_CALL( SCIPsyncstoreExit(*syncstore) );
98  }
99 
100  assert(!(*syncstore)->initialized);
101  SCIPtpiDestroyLock(&(*syncstore)->lock);
102  BMSfreeMemory(syncstore);
103  }
104  else
105  {
106  *syncstore = NULL;
107  }
108 
109  return SCIP_OKAY;
110 }
111 
112 /** captures a synchronization store */
114  SCIP_SYNCSTORE* syncstore /**< the synchronization store */
115  )
116 {
117  SCIP_CALL( SCIPtpiAcquireLock(&syncstore->lock) );
118 
119  ++(syncstore->nuses);
120 
121  SCIP_CALL( SCIPtpiReleaseLock(&syncstore->lock) );
122 
123  return SCIP_OKAY;
124 }
125 
126 /** initialize the syncstore for the given SCIP instance */
128  SCIP* scip /**< SCIP main datastructure */
129  )
130 {
131  SCIP_SYNCSTORE* syncstore;
132  int i;
133  int j;
134  int paramode;
135 
136  assert(scip != NULL);
137  syncstore = SCIPgetSyncstore(scip);
138  assert(syncstore != NULL);
139  syncstore->mainscip = scip;
140  syncstore->lastsync = NULL;
141  syncstore->nsolvers = SCIPgetNConcurrentSolvers(scip);
142 
143  syncstore->ninitvars = SCIPgetNVars(scip);
144  SCIP_CALL( SCIPgetIntParam(scip, "concurrent/sync/maxnsols", &syncstore->maxnsols) );
145  SCIP_CALL( SCIPgetIntParam(scip, "concurrent/sync/maxnsyncdelay", &syncstore->maxnsyncdelay) );
146  SCIP_CALL( SCIPgetRealParam(scip, "concurrent/sync/minsyncdelay", &syncstore->minsyncdelay) );
147  SCIP_CALL( SCIPgetRealParam(scip, "concurrent/sync/freqinit", &syncstore->syncfreqinit) );
148  SCIP_CALL( SCIPgetRealParam(scip, "concurrent/sync/freqmax", &syncstore->syncfreqmax) );
149  syncstore->nsyncdata = getNSyncdata(scip);
150  SCIP_CALL( SCIPallocBlockMemoryArray(syncstore->mainscip, &(syncstore->syncdata), syncstore->nsyncdata) );
151 
152  for( i = 0; i < syncstore->nsyncdata; ++i )
153  {
154  syncstore->syncdata[i].syncnum = -1;
155  SCIP_CALL( SCIPboundstoreCreate(syncstore->mainscip, &syncstore->syncdata[i].boundstore, syncstore->ninitvars) );
156  SCIP_CALL( SCIPallocBlockMemoryArray(syncstore->mainscip, &syncstore->syncdata[i].solobj, syncstore->maxnsols) );
157  SCIP_CALL( SCIPallocBlockMemoryArray(syncstore->mainscip, &syncstore->syncdata[i].solsource, syncstore->maxnsols) );
158  SCIP_CALL( SCIPallocBlockMemoryArray(syncstore->mainscip, &syncstore->syncdata[i].sols, syncstore->maxnsols) );
159 
160  for( j = 0; j < syncstore->maxnsols; ++j )
161  {
162  SCIP_CALL( SCIPallocBlockMemoryArray(syncstore->mainscip, &syncstore->syncdata[i].sols[j], syncstore->ninitvars) );
163  }
164 
165  SCIP_CALL( SCIPtpiInitLock(&(syncstore->syncdata[i].lock)) );
166  SCIP_CALL( SCIPtpiInitCondition(&(syncstore->syncdata[i].allsynced)) );
167  }
168 
169  syncstore->initialized = TRUE;
170  syncstore->stopped = FALSE;
171 
172  SCIP_CALL( SCIPgetIntParam(scip, "parallel/mode", &paramode) );
173  syncstore->mode = (SCIP_PARALLELMODE) paramode;
174 
175  SCIP_CALL( SCIPtpiInit(syncstore->nsolvers, INT_MAX, FALSE) );
177 
178  if( syncstore->mode == SCIP_PARA_DETERMINISTIC )
179  {
180  /* in deterministic mode use the number of non-zeros and the number of variables to get a good
181  * syncdelay and maximum syncfreq
182  */
183  syncstore->minsyncdelay *= 0.01 * (SCIPgetNNZs(scip) * SCIPgetNVars(scip));
184  syncstore->syncfreqmax *= 0.01 * (SCIPgetNNZs(scip) * SCIPgetNVars(scip));
185  }
186 
187  return SCIP_OKAY;
188 }
189 
190 /** deinitializes the synchronization store */
192  SCIP_SYNCSTORE* syncstore /**< the synchronization store */
193  )
194 {
195  int i;
196  int j;
197 
198  assert(syncstore != NULL);
199  assert(syncstore->initialized);
200 
201  SCIP_CALL( SCIPtpiExit() );
202 
203  for( i = 0; i < syncstore->nsyncdata; ++i )
204  {
205  SCIPtpiDestroyLock(&(syncstore->syncdata[i].lock));
206  SCIPtpiDestroyCondition(&(syncstore->syncdata[i].allsynced));
207  SCIPfreeBlockMemoryArray(syncstore->mainscip, &syncstore->syncdata[i].solobj, syncstore->maxnsols);
208  SCIPfreeBlockMemoryArray(syncstore->mainscip, &syncstore->syncdata[i].solsource, syncstore->maxnsols);
209  SCIPboundstoreFree(syncstore->mainscip, &syncstore->syncdata[i].boundstore);
210 
211  for( j = 0; j < syncstore->maxnsols; ++j )
212  {
213  SCIPfreeBlockMemoryArray(syncstore->mainscip, &syncstore->syncdata[i].sols[j], syncstore->ninitvars);
214  }
215 
216  SCIPfreeBlockMemoryArray(syncstore->mainscip, &syncstore->syncdata[i].sols, syncstore->maxnsols);
217  }
218 
219  SCIPfreeBlockMemoryArray(syncstore->mainscip, &syncstore->syncdata, syncstore->nsyncdata);
220 
221  syncstore->initialized = FALSE;
222  syncstore->stopped = FALSE;
223 
224  return SCIP_OKAY;
225 }
226 
227 /** checks whether the solve-is-stopped flag in the syncstore has been set by any thread */
229  SCIP_SYNCSTORE* syncstore /**< the synchronization store */
230  )
231 {
232  SCIP_Bool stopped;
233 
234  SCIP_CALL_ABORT( SCIPtpiAcquireLock(&syncstore->lock) );
235 
236  stopped = syncstore->stopped;
237 
238  SCIP_CALL_ABORT( SCIPtpiReleaseLock(&syncstore->lock) );
239 
240  return stopped;
241 }
242 
243 /** sets the solve-is-stopped flag in the syncstore so that subsequent calls to
244  * SCIPsyncstoreSolveIsStopped will return the given value in any thread
245  */
247  SCIP_SYNCSTORE* syncstore, /**< the synchronization store */
248  SCIP_Bool stopped /**< flag if the solve is stopped */
249  )
250 {
251  SCIP_CALL_ABORT( SCIPtpiAcquireLock(&syncstore->lock) );
252 
253  syncstore->stopped = stopped;
254 
255  SCIP_CALL_ABORT( SCIPtpiReleaseLock(&syncstore->lock) );
256 }
257 
258 /** gets the upperbound from the last synchronization */
260  SCIP_SYNCSTORE* syncstore /**< the synchronization store */
261  )
262 {
263  assert(syncstore != NULL);
264  assert(syncstore->initialized);
265 
266  return syncstore->lastsync == NULL ? SCIPinfinity(syncstore->mainscip) : syncstore->lastsync->bestupperbound;
267 }
268 
269 /** gets the lowerbound from the last synchronization */
271  SCIP_SYNCSTORE* syncstore /**< the synchronization store */
272  )
273 {
274  assert(syncstore != NULL);
275  assert(syncstore->initialized);
276 
277  return syncstore->lastsync == NULL ? -SCIPinfinity(syncstore->mainscip) : syncstore->lastsync->bestlowerbound;
278 }
279 
280 /** gets the number of solutions from the last synchronization */
282  SCIP_SYNCSTORE* syncstore /**< the synchronization store */
283  )
284 {
285  assert(syncstore != NULL);
286  assert(syncstore->initialized);
287 
288  return syncstore->lastsync == NULL ? 0 : syncstore->lastsync->nsols;
289 }
290 
291 /** gets the number of boundchanges from the last synchronization */
293  SCIP_SYNCSTORE* syncstore /**< the synchronization store */
294  )
295 {
296  assert(syncstore != NULL);
297  assert(syncstore->initialized);
298 
299  return syncstore->lastsync == NULL ? 0 : SCIPboundstoreGetNChgs(syncstore->lastsync->boundstore);
300 }
301 
302 /** gets total memory used by all solvers from the last synchronization */
304  SCIP_SYNCSTORE* syncstore /**< the synchronization store */
305  )
306 {
307  assert(syncstore != NULL);
308  assert(syncstore->initialized);
309 
310  return syncstore->lastsync == NULL ? 0 : syncstore->lastsync->memtotal;
311 }
312 
313 /** gets the synchronization frequency from the last synchronization */
315  SCIP_SYNCSTORE* syncstore /**< the synchronization store */
316  )
317 {
318  assert(syncstore != NULL);
319  assert(syncstore->initialized);
320 
321  return syncstore->lastsync == NULL ? 0.0 : syncstore->lastsync->syncfreq;
322 }
323 
324 /** get synchronization data with given number. It is the responsibility of the caller
325  * to only ask for a synchronization number that still exists, which is checked
326  * with an assert in debug mode. */
328  SCIP_SYNCSTORE* syncstore, /**< the synchronization store */
329  SCIP_Longint syncnum /**< the number of the synchronization to start, which
330  * must be increasing between calls of the same thread */
331  )
332 {
333  int j;
334 
335  assert(syncstore != NULL);
336  assert(syncstore->initialized);
337 
338  j = syncnum % syncstore->nsyncdata;
339 
340  /* check if requested syncnumber still exists if in debug mode */
341  assert(syncstore->syncdata[j].syncnum == syncnum);
342 
343  return &syncstore->syncdata[j];
344 }
345 
346 /** get the next synchronization data that should be read and
347  * adjust the delay. Returns NULL if no more data should be read due to minimum delay */
349  SCIP_SYNCSTORE* syncstore, /**< the synchronization store */
350  SCIP_SYNCDATA* syncdata, /**< the synchronization data */
351  SCIP_Real syncfreq, /**< the current synchronization frequency */
352  SCIP_Longint writenum, /**< number of synchronizations the solver has written to */
353  SCIP_Real* delay /**< pointer holding the current synchronization delay */
354  )
355 {
356  SCIP_Real newdelay;
357  SCIP_Longint nextsyncnum;
358 
359  assert(syncstore != NULL);
360  assert(syncstore->initialized);
361  assert(delay != NULL);
362 
363  if( syncdata == NULL )
364  {
365  nextsyncnum = 0;
366  }
367  else
368  {
369  if( syncdata->status != SCIP_STATUS_UNKNOWN )
370  return NULL;
371 
372  nextsyncnum = syncdata->syncnum + 1;
373  }
374 
375  if( nextsyncnum == writenum )
376  return NULL;
377 
378  newdelay = *delay - syncfreq;
379 
380  /* if the delay would get too small we dont want to read the next syncdata.
381  * But due to the limited length of the syncdata array we might need to
382  * read this synchronization data anyways which is checked by the second part
383  * of the if condition
384  */
385  if( newdelay < syncstore->minsyncdelay && nextsyncnum >= writenum - syncstore->maxnsyncdelay )
386  return NULL;
387 
388  *delay = newdelay;
389  assert(syncstore->syncdata[nextsyncnum % syncstore->nsyncdata].syncnum == nextsyncnum);
390 
391  return &syncstore->syncdata[nextsyncnum % syncstore->nsyncdata];
392 }
393 
394 /** ensures that the given synchronization data has been written by
395  * all solvers upon return of this function and blocks the caller if necessary. */
397  SCIP_SYNCSTORE* syncstore, /**< the synchronization store */
398  SCIP_SYNCDATA* syncdata /**< the synchronization data */
399  )
400 {
401  assert(syncdata != NULL);
402  assert(syncstore != NULL);
403  assert(syncstore->initialized);
404 
405  /* check if waiting is required, make sure to hold the lock */
406  SCIP_CALL( SCIPtpiAcquireLock(&syncdata->lock) );
407 
408  while( syncdata->syncedcount < syncstore->nsolvers )
409  {
410  /* yes, so wait on the condition variable
411  * (automatically releases the lock and reacquires it after the waiting)
412  */
413  SCIP_CALL( SCIPtpiWaitCondition(&syncdata->allsynced, &syncdata->lock) );
414  }
415 
416  SCIP_CALL( SCIPtpiReleaseLock(&syncdata->lock) );
417 
418  return SCIP_OKAY;
419 }
420 
421 /** Start synchronization for the given concurrent solver.
422  * Needs to be followed by a call to SCIPsyncstoreFinishSync if
423  * the syncdata that is returned is not NULL
424  */
426  SCIP_SYNCSTORE* syncstore, /**< the synchronization store */
427  SCIP_Longint syncnum, /**< the number of the synchronization to start, which
428  * must be increasing between calls of the same thread */
429  SCIP_SYNCDATA** syncdata /**< pointer to return the synchronization data */
430  )
431 {
432  int i;
433 
434  assert(syncdata != NULL);
435  assert(syncstore != NULL);
436  assert(syncstore->initialized);
437 
438  if( SCIPsyncstoreSolveIsStopped(syncstore) )
439  {
440  *syncdata = NULL;
441  return SCIP_OKAY;
442  }
443 
444  i = syncnum % syncstore->nsyncdata;
445  *syncdata = &syncstore->syncdata[i];
446  assert(*syncdata != NULL);
447 
448  SCIP_CALL( SCIPtpiAcquireLock(&(*syncdata)->lock) );
449 
450  if( (*syncdata)->syncnum != syncnum )
451  {
452  SCIPboundstoreClear((*syncdata)->boundstore);
453  (*syncdata)->nsols = 0;
454  (*syncdata)->memtotal = SCIPgetMemTotal(syncstore->mainscip);
455  (*syncdata)->syncedcount = 0;
456  (*syncdata)->bestupperbound = SCIPinfinity(syncstore->mainscip);
457  (*syncdata)->bestlowerbound = -(*syncdata)->bestupperbound;
458  (*syncdata)->status = SCIP_STATUS_UNKNOWN;
459  (*syncdata)->winner = 0;
460  (*syncdata)->syncnum = syncnum;
461  (*syncdata)->syncfreq = 0.0;
462  }
463 
464  return SCIP_OKAY;
465 }
466 
467 /** finishes synchronization for the synchronization data */
469  SCIP_SYNCSTORE* syncstore, /**< the synchronization store */
470  SCIP_SYNCDATA** syncdata /**< the synchronization data */
471  )
472 {
473  SCIP_Bool printline = FALSE;
474 
475  assert(syncdata != NULL);
476  assert((*syncdata) != NULL);
477  assert(syncstore != NULL);
478  assert(syncstore->initialized);
479 
480  ++(*syncdata)->syncedcount;
481 
482  if( (*syncdata)->syncedcount == syncstore->nsolvers )
483  {
484  if( (*syncdata)->status != SCIP_STATUS_UNKNOWN )
486 
487  syncstore->lastsync = *syncdata;
488  printline = TRUE;
489 
490  SCIP_CALL( SCIPtpiBroadcastCondition(&(*syncdata)->allsynced) );
491  }
492 
493  SCIP_CALL( SCIPtpiReleaseLock(&(*syncdata)->lock) );
494 
495  if( printline )
496  {
498  }
499 
500  *syncdata = NULL;
501 
502  return SCIP_OKAY;
503 }
504 
505 /** gets status in synchronization data */
507  SCIP_SYNCDATA* syncdata /**< the synchronization data */
508  )
509 {
510  assert(syncdata != NULL);
511 
512  return syncdata->status;
513 }
514 
515 /** gets the solver that had the best status, or -1 if solve is not stopped yet */
517  SCIP_SYNCSTORE* syncstore /**< the synchronization store */
518  )
519 {
520  assert(syncstore != NULL);
521  assert(syncstore->initialized);
522 
523  if( syncstore->lastsync == NULL || syncstore->lastsync->status == SCIP_STATUS_UNKNOWN )
524  return -1;
525 
526  return syncstore->lastsync->winner;
527 }
528 
529 /** how many solvers have already finished synchronizing on this sychronization data */
531  SCIP_SYNCDATA* syncdata /**< the synchronization data */
532  )
533 {
534  assert(syncdata != NULL);
535 
536  return syncdata->syncedcount;
537 }
538 
539 /** how many solvers have are running concurrently */
541  SCIP_SYNCSTORE* syncstore /**< the synchronization store */
542  )
543 {
544  assert(syncstore != NULL);
545  assert(syncstore->initialized);
546 
547  return syncstore->nsolvers;
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  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_mem.h:97
SCIP_PARALLELMODE mode
SCIP_RETCODE SCIPprintDisplayLine(SCIP *scip, FILE *file, SCIP_VERBLEVEL verblevel, SCIP_Bool endline)
SCIP_SYNCDATA * lastsync
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:80
SCIP_RETCODE SCIPsyncstoreRelease(SCIP_SYNCSTORE **syncstore)
Definition: syncstore.c:78
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:396
SCIP_STATUS SCIPsyncdataGetStatus(SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:506
void SCIPsyncdataSetUpperbound(SCIP_SYNCDATA *syncdata, SCIP_Real upperbound)
Definition: syncstore.c:675
SCIP_SYNCDATA * SCIPsyncstoreGetSyncdata(SCIP_SYNCSTORE *syncstore, SCIP_Longint syncnum)
Definition: syncstore.c:327
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:1986
#define FALSE
Definition: def.h:73
#define TRUE
Definition: def.h:72
void SCIPsyncdataSetLowerbound(SCIP_SYNCDATA *syncdata, SCIP_Real lowerbound)
Definition: syncstore.c:686
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:54
datastructures for concurrent solvers
SCIP_EXPORT SCIP_RETCODE SCIPtpiWaitCondition(SCIP_CONDITION *condition, SCIP_LOCK *lock)
Definition: tpi_openmp.c:287
datastructures for concurrent solvers
static int getNSyncdata(SCIP *scip)
Definition: syncstore.c:45
#define SCIPdebugMessage
Definition: pub_message.h:87
SCIP_Longint SCIPgetMemTotal(SCIP *scip)
Definition: scip_mem.c:104
the struct definitions for the synchronization store
#define BMSfreeMemory(ptr)
Definition: memory.h:137
SCIP_Real SCIPsyncstoreGetLastUpperbound(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:259
SCIP_SYNCDATA * SCIPsyncstoreGetNextSyncdata(SCIP_SYNCSTORE *syncstore, SCIP_SYNCDATA *syncdata, SCIP_Real syncfreq, SCIP_Longint writenum, SCIP_Real *delay)
Definition: syncstore.c:348
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
SCIP_EXPORT SCIP_RETCODE SCIPtpiInitCondition(SCIP_LOCK *lock)
void SCIPsyncdataSetSyncFreq(SCIP_SYNCSTORE *syncstore, SCIP_SYNCDATA *syncdata, SCIP_Real syncfreq)
Definition: syncstore.c:619
internal methods for storing and manipulating the main problem
SCIP_Real SCIPsyncstoreGetLastLowerbound(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:270
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_Longint SCIPgetNNZs(SCIP *scip)
SCIP_Real minsyncdelay
void SCIPsyncdataSetStatus(SCIP_SYNCDATA *syncdata, SCIP_STATUS status, int solverid)
Definition: syncstore.c:633
SCIP_EXPORT void SCIPtpiDestroyCondition(SCIP_LOCK *lock)
struct SCIP_SyncData SCIP_SYNCDATA
SCIP_EXPORT SCIP_RETCODE SCIPtpiInitLock(SCIP_LOCK *lock)
#define NULL
Definition: lpi_spx1.cpp:155
the interface of the boundstore structure
SCIP_Real SCIPsyncstoreGetLastSyncfreq(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:314
#define SCIP_CALL(x)
Definition: def.h:364
SCIP_RETCODE SCIPgetIntParam(SCIP *scip, const char *name, int *value)
Definition: scip_param.c:260
SCIP_Bool initialized
SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
Definition: scip_param.c:298
SCIP_SYNCDATA * syncdata
the function declarations for the synchronization store
SCIP_Real SCIPinfinity(SCIP *scip)
#define SCIP_Bool
Definition: def.h:70
SCIP_EXPORT SCIP_RETCODE SCIPtpiExit(void)
Definition: tpi_none.c:81
void SCIPsyncdataAddMemTotal(SCIP_SYNCDATA *syncdata, SCIP_Longint memtotal)
Definition: syncstore.c:664
enum SCIP_Status SCIP_STATUS
Definition: type_stat.h:58
SCIP_RETCODE SCIPsyncstoreInit(SCIP *scip)
Definition: syncstore.c:127
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:425
#define MAX(x, y)
Definition: tclique_def.h:83
SCIP_EXPORT SCIP_RETCODE SCIPtpiBroadcastCondition(SCIP_CONDITION *condition)
Definition: tpi_openmp.c:275
SCIP_Longint SCIPsyncdataGetMemTotal(SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:551
SCIP_Longint SCIPsyncstoreGetLastMemTotal(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:303
int SCIPsyncstoreGetWinner(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:516
SCIP_RETCODE SCIPautoselectDisps(SCIP *scip)
Definition: scip_disp.c:123
void SCIPswapPointers(void **pointer1, void **pointer2)
Definition: misc.c:10218
helper functions for concurrent scip solvers
SCIP_EXPORT void SCIPtpiDestroyLock(SCIP_LOCK *lock)
SCIP_RETCODE SCIPsyncstoreExit(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:191
SCIP_RETCODE SCIPsyncstoreCreate(SCIP_SYNCSTORE **syncstore)
Definition: syncstore.c:57
int SCIPsyncdataGetNSynced(SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:530
int SCIPsyncstoreGetLastNSols(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:281
SCIP_BOUNDSTORE * SCIPsyncdataGetBoundChgs(SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:609
SCIP_SYNCSTORE * SCIPgetSyncstore(SCIP *scip)
void SCIPsyncstoreSetSolveIsStopped(SCIP_SYNCSTORE *syncstore, SCIP_Bool stopped)
Definition: syncstore.c:246
public methods for message output
SCIP_EXPORT SCIP_RETCODE SCIPtpiAcquireLock(SCIP_LOCK *lock)
SCIP_Real SCIPsyncdataGetSyncFreq(SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:561
SCIP_Real syncfreqmax
#define SCIP_Real
Definition: def.h:163
SCIP_Real syncfreqinit
#define BMSallocMemory(ptr)
Definition: memory.h:111
SCIP_Bool SCIPsyncstoreSolveIsStopped(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:228
SCIP_EXPORT SCIP_RETCODE SCIPtpiInit(int nthreads, int queuesize, SCIP_Bool blockwhenfull)
Definition: tpi_none.c:67
#define SCIP_Longint
Definition: def.h:148
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:468
SCIP_RETCODE SCIPboundstoreMerge(SCIP *scip, SCIP_BOUNDSTORE *target, SCIP_BOUNDSTORE *source)
Definition: boundstore.c:115
SCIP_RETCODE SCIPsyncstoreCapture(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:113
int SCIPsyncstoreGetLastNBounds(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:292
common defines and data types used in all packages of SCIP
#define SCIP_CALL_ABORT(x)
Definition: def.h:343
SCIP_Real SCIPsyncdataGetUpperbound(SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:571
#define SCIP_ALLOC(x)
Definition: def.h:375
int SCIPsyncstoreGetNSolvers(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:540
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:591
SCIP callable library.
SCIP_EXPORT SCIP_RETCODE SCIPtpiReleaseLock(SCIP_LOCK *lock)
void SCIPboundstoreClear(SCIP_BOUNDSTORE *boundstore)
Definition: boundstore.c:137
memory allocation routines