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