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"
41#include "scip/prob.h"
42#include "scip/scip.h"
44#include "tpi/tpi.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 */
54static
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;
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
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
246
247 stopped = syncstore->stopped;
248
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{
263
264 syncstore->stopped = stopped;
265
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}
SCIP_RETCODE SCIPboundstoreMerge(SCIP *scip, SCIP_BOUNDSTORE *target, SCIP_BOUNDSTORE *source)
Definition: boundstore.c:124
void SCIPboundstoreFree(SCIP *scip, SCIP_BOUNDSTORE **boundstore)
Definition: boundstore.c:60
SCIP_RETCODE SCIPboundstoreCreate(SCIP *scip, SCIP_BOUNDSTORE **boundstore, int nvars)
Definition: boundstore.c:39
void SCIPboundstoreClear(SCIP_BOUNDSTORE *boundstore)
Definition: boundstore.c:146
int SCIPboundstoreGetNChgs(SCIP_BOUNDSTORE *boundstore)
Definition: boundstore.c:197
the interface of the boundstore structure
datastructures for concurrent solvers
int SCIPgetNConcurrentSolvers(SCIP *scip)
Definition: concurrent.c:117
helper functions for concurrent scip solvers
common defines and data types used in all packages of SCIP
#define NULL
Definition: def.h:267
#define SCIP_Longint
Definition: def.h:158
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:243
#define SCIP_ALLOC(x)
Definition: def.h:385
#define SCIP_Real
Definition: def.h:173
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:239
#define SCIP_CALL_ABORT(x)
Definition: def.h:353
#define SCIP_CALL(x)
Definition: def.h:374
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:1992
SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
Definition: scip_param.c:307
SCIP_RETCODE SCIPgetIntParam(SCIP *scip, const char *name, int *value)
Definition: scip_param.c:269
void SCIPswapPointers(void **pointer1, void **pointer2)
Definition: misc.c:10396
SCIP_RETCODE SCIPautoselectDisps(SCIP *scip)
Definition: scip_disp.c:132
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:110
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:93
SCIP_Longint SCIPgetMemTotal(SCIP *scip)
Definition: scip_mem.c:113
SCIP_SYNCSTORE * SCIPgetSyncstore(SCIP *scip)
SCIP_RETCODE SCIPprintDisplayLine(SCIP *scip, FILE *file, SCIP_VERBLEVEL verblevel, SCIP_Bool endline)
SCIP_Longint SCIPgetNNZs(SCIP *scip)
SCIP_Real SCIPinfinity(SCIP *scip)
memory allocation routines
#define BMSfreeMemory(ptr)
Definition: memory.h:145
#define BMSallocMemory(ptr)
Definition: memory.h:118
internal methods for storing and manipulating the main problem
public methods for message output
#define SCIPdebugMessage
Definition: pub_message.h:96
SCIP callable library.
SCIP_Bool initialized
SCIP_SYNCDATA * syncdata
SCIP_Real syncfreqmax
SCIP_Real syncfreqinit
SCIP_PARALLELMODE mode
SCIP_LOCK * lock
SCIP_SYNCDATA * lastsync
SCIP_Real minsyncdelay
datastructures for concurrent solvers
the struct definitions for the synchronization store
SCIP_Bool SCIPsyncstoreSolveIsStopped(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:239
SCIP_Real SCIPsyncdataGetSyncFreq(SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:572
SCIP_Longint SCIPsyncdataGetMemTotal(SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:562
SCIP_BOUNDSTORE * SCIPsyncdataGetBoundChgs(SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:620
SCIP_Real SCIPsyncstoreGetLastUpperbound(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:270
SCIP_RETCODE SCIPsyncstoreFinishSync(SCIP_SYNCSTORE *syncstore, SCIP_SYNCDATA **syncdata)
Definition: syncstore.c:479
SCIP_Real SCIPsyncstoreGetLastLowerbound(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:281
SCIP_Real SCIPsyncdataGetUpperbound(SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:582
void SCIPsyncdataSetUpperbound(SCIP_SYNCDATA *syncdata, SCIP_Real upperbound)
Definition: syncstore.c:691
SCIP_RETCODE SCIPsyncdataAddBoundChanges(SCIP_SYNCSTORE *syncstore, SCIP_SYNCDATA *syncdata, SCIP_BOUNDSTORE *boundstore)
Definition: syncstore.c:774
int SCIPsyncstoreGetWinner(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:527
SCIP_RETCODE SCIPsyncstoreEnsureAllSynced(SCIP_SYNCSTORE *syncstore, SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:407
void SCIPsyncdataSetSyncFreq(SCIP_SYNCSTORE *syncstore, SCIP_SYNCDATA *syncdata, SCIP_Real syncfreq)
Definition: syncstore.c:630
SCIP_Real SCIPsyncstoreGetLastSyncfreq(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:325
void SCIPsyncdataGetSolutions(SCIP_SYNCDATA *syncdata, SCIP_Real ***solvalues, int **solowner, int *nsols)
Definition: syncstore.c:602
void SCIPsyncdataSetStatus(SCIP_SYNCDATA *syncdata, SCIP_STATUS status, int solverid)
Definition: syncstore.c:644
void SCIPsyncstoreSetSolveIsStopped(SCIP_SYNCSTORE *syncstore, SCIP_Bool stopped)
Definition: syncstore.c:257
SCIP_RETCODE SCIPsyncstoreRelease(SCIP_SYNCSTORE **syncstore)
Definition: syncstore.c:89
SCIP_Longint SCIPsyncstoreGetLastMemTotal(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:314
SCIP_RETCODE SCIPsyncstoreExit(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:202
void SCIPsyncdataSetLowerbound(SCIP_SYNCDATA *syncdata, SCIP_Real lowerbound)
Definition: syncstore.c:702
SCIP_RETCODE SCIPsyncstoreCapture(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:124
int SCIPsyncstoreGetLastNBounds(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:303
static int getNSyncdata(SCIP *scip)
Definition: syncstore.c:55
int SCIPsyncstoreGetLastNSols(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:292
SCIP_RETCODE SCIPsyncstoreStartSync(SCIP_SYNCSTORE *syncstore, SCIP_Longint syncnum, SCIP_SYNCDATA **syncdata)
Definition: syncstore.c:436
void SCIPsyncdataGetSolutionBuffer(SCIP_SYNCSTORE *syncstore, SCIP_SYNCDATA *syncdata, SCIP_Real solobj, int ownerid, SCIP_Real **buffer)
Definition: syncstore.c:715
SCIP_Real SCIPsyncdataGetLowerbound(SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:592
SCIP_PARALLELMODE SCIPsyncstoreGetMode(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:801
SCIP_RETCODE SCIPsyncstoreCreate(SCIP_SYNCSTORE **syncstore)
Definition: syncstore.c:67
int SCIPsyncdataGetNSynced(SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:541
SCIP_SYNCDATA * SCIPsyncstoreGetSyncdata(SCIP_SYNCSTORE *syncstore, SCIP_Longint syncnum)
Definition: syncstore.c:338
SCIP_Bool SCIPsyncstoreIsInitialized(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:791
SCIP_SYNCDATA * SCIPsyncstoreGetNextSyncdata(SCIP_SYNCSTORE *syncstore, SCIP_SYNCDATA *syncdata, SCIP_Real syncfreq, SCIP_Longint writenum, SCIP_Real *delay)
Definition: syncstore.c:359
void SCIPsyncdataAddMemTotal(SCIP_SYNCDATA *syncdata, SCIP_Longint memtotal)
Definition: syncstore.c:680
int SCIPsyncstoreGetNSolvers(SCIP_SYNCSTORE *syncstore)
Definition: syncstore.c:551
SCIP_STATUS SCIPsyncdataGetStatus(SCIP_SYNCDATA *syncdata)
Definition: syncstore.c:517
SCIP_RETCODE SCIPsyncstoreInit(SCIP *scip)
Definition: syncstore.c:138
the function declarations for the synchronization store
the type definitions for the SCIP parallel interface
SCIP_RETCODE SCIPtpiWaitCondition(SCIP_CONDITION *condition, SCIP_LOCK *lock)
Definition: tpi_none.c:124
SCIP_RETCODE SCIPtpiAcquireLock(SCIP_LOCK *lock)
Definition: tpi_none.c:64
SCIP_RETCODE SCIPtpiExit(void)
Definition: tpi_none.c:216
SCIP_RETCODE SCIPtpiBroadcastCondition(SCIP_CONDITION *condition)
Definition: tpi_none.c:114
void SCIPtpiDestroyLock(SCIP_LOCK **lock)
Definition: tpi_none.c:55
void SCIPtpiDestroyCondition(SCIP_CONDITION **condition)
Definition: tpi_none.c:97
SCIP_RETCODE SCIPtpiInitLock(SCIP_LOCK **lock)
Definition: tpi_none.c:44
SCIP_RETCODE SCIPtpiReleaseLock(SCIP_LOCK *lock)
Definition: tpi_none.c:72
SCIP_RETCODE SCIPtpiInitCondition(SCIP_CONDITION **condition)
Definition: tpi_none.c:86
SCIP_RETCODE SCIPtpiInit(int nthreads, int queuesize, SCIP_Bool blockwhenfull)
Definition: tpi_none.c:202
@ SCIP_VERBLEVEL_HIGH
Definition: type_message.h:56
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_STATUS_OPTIMAL
Definition: type_stat.h:61
@ SCIP_STATUS_UNKNOWN
Definition: type_stat.h:42
enum SCIP_Status SCIP_STATUS
Definition: type_stat.h:67
enum SCIP_Parallelmode SCIP_PARALLELMODE
@ SCIP_PARA_DETERMINISTIC
struct SCIP_SyncData SCIP_SYNCDATA