Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

solve problem with multi-threads #918

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

liangbug
Copy link
Contributor

I want to solve problem with multi-threads and different random seeds
So I added some methods including

  1. model optimize without gil
  2. solveFirstInterruptOthers
  3. add copy model method
  4. add copy model solution
  5. add some Solution methods

The copyed model from init method argument sourceModel loses some scip components.
The new copy model method use full scip components.

2. solveFirstInterruptOthers
3. add copy model method
4. add copy model solution
5. add some Solution methods
for i in range(N_Threads):
models[i].setParam("randomization/permutationseed", i)

ori_model.optimize()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this optimize call need to come before the others are called?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ori_model.optimize() can be called anywhere.
It's ok before or after ori_model.copyModel(), models[i].setParam("randomization/permutationseed", i), Model.solveFirstInterruptOthers(executor=executor, models=models)

@Opt-Mucca
Copy link
Collaborator

Thanks for the PR @liangbug !
My concerns with the content:

  • Why did a new copy function need to be created? What is the difference between this new function and doing something like new_scip = Model(sourceModel=orig_scip)?
  • I am not sure that providing such easy functionality to parallel solver calls is a good idea. Providing transparency to the user on what exactly happened during the solution process is now a bit difficult. This implementation is also somewhat trying to mirror the functionality that solveConcurrent currently does, but doing so on the Python level.

@liangbug
Copy link
Contributor Author

liangbug commented Oct 29, 2024

  1. new_scip = Model(sourceModel=orig_scip) loses 226 parameters including dual presolvers, some heuristics. Solving new_scip is usually slow than solving orig_scip with same random seed. The new copy function can full copy orig_scip problem except solution storage.

  2. It's inconvenient. that solveConcurrent needs to compile scipopt source code with tpi. I test solveConcurrent with multi-threads that is usually slowly than optimize with one thread. I found that different random seeds influence different solving time and model.optimize() just use one thread. I want to solve model with different random seeds at the same time and return fastest one, so I created solveFirstInterruptOthers

Appendix 1.

from pyscipopt import Model

def main():
    orig_scip = Model()
    copy_scip = Model.copyModel(orig_scip)
    new_scip = Model(sourceModel=orig_scip)
    
    orig_scip_param_names = orig_scip.getParams().keys()
    copy_scip_param_names = copy_scip.getParams().keys()
    new_scip_param_names = new_scip.getParams().keys()
    lost_params = sorted(list(set(orig_scip_param_names) - set(new_scip_param_names))) 

    print('The count of orig scip params:', len(orig_scip_param_names))
    print('The count of copy scip params:', len(copy_scip_param_names))
    print('The count of  new scip params:', len(new_scip_param_names))
    print('The lost  of  new scip params:', lost_params)


if __name__ == "__main__":
    main()  
The count of orig scip params: 2973
The count of copy scip params: 2973
The count of  new scip params: 2747
The lost  of  new scip params: ['benders/default/auxvarsimplint', 'benders/default/benderscut/feas/enabled', 'benders/default/benderscut/feas/priority', 'benders/default/benderscut/feasalt/enabled', 'benders/default/benderscut/feasalt/priority', 'benders/default/benderscut/integer/addcuts', 'benders/default/benderscut/integer/cutsconstant', 'benders/default/benderscut/integer/enabled', 'benders/default/benderscut/integer/priority', 'benders/default/benderscut/nogood/addcuts', 'benders/default/benderscut/nogood/enabled', 'benders/default/benderscut/nogood/priority', 'benders/default/benderscut/optimality/addcuts', 'benders/default/benderscut/optimality/enabled', 'benders/default/benderscut/optimality/mir', 'benders/default/benderscut/optimality/priority', 'benders/default/checkconsconvexity', 'benders/default/corepointperturb', 'benders/default/cutcheck', 'benders/default/cutlp', 'benders/default/cutpseudo', 'benders/default/cutrelax', 'benders/default/cutsasconss', 'benders/default/cutstrengthenenabled', 'benders/default/cutstrengthenintpoint', 'benders/default/cutstrengthenmult', 'benders/default/execfeasphase', 'benders/default/lnscheck', 'benders/default/lnsmaxcalls', 'benders/default/lnsmaxcallsroot', 'benders/default/lnsmaxdepth', 'benders/default/maxslackvarcoef', 'benders/default/nlpiterlimit', 'benders/default/noimprovelimit', 'benders/default/numthreads', 'benders/default/priority', 'benders/default/slackvarcoef', 'benders/default/subprobfrac', 'benders/default/transfercuts', 'benders/default/updateauxvarbound', 'branching/cloud/maxbounddist', 'branching/cloud/maxdepth', 'branching/cloud/maxdepthunion', 'branching/cloud/maxpoints', 'branching/cloud/minsuccessrate', 'branching/cloud/minsuccessunion', 'branching/cloud/onlyF2', 'branching/cloud/priority', 'branching/cloud/usecloud', 'branching/cloud/useunion', 'branching/lookahead/abbreviated', 'branching/lookahead/abbrevpseudo', 'branching/lookahead/addbinconsrow', 'branching/lookahead/addclique', 'branching/lookahead/addnonviocons', 'branching/lookahead/applychildbounds', 'branching/lookahead/deeperscoringfunction', 'branching/lookahead/enforcemaxdomreds', 'branching/lookahead/filterbymaxgain', 'branching/lookahead/level2avgscore', 'branching/lookahead/level2zeroscore', 'branching/lookahead/maxbounddist', 'branching/lookahead/maxdepth', 'branching/lookahead/maxncands', 'branching/lookahead/maxndeepercands', 'branching/lookahead/maxnviolatedbincons', 'branching/lookahead/maxnviolatedcons', 'branching/lookahead/maxnviolateddomreds', 'branching/lookahead/maxproprounds', 'branching/lookahead/mergedomainreductions', 'branching/lookahead/minweight', 'branching/lookahead/onlyvioldomreds', 'branching/lookahead/prefersimplebounds', 'branching/lookahead/priority', 'branching/lookahead/propagate', 'branching/lookahead/recursiondepth', 'branching/lookahead/reevalage', 'branching/lookahead/reevalagefsb', 'branching/lookahead/reusebasis', 'branching/lookahead/scoringfunction', 'branching/lookahead/scoringscoringfunction', 'branching/lookahead/storeunviolatedsol', 'branching/lookahead/updatebranchingresults', 'branching/lookahead/usedomainreduction', 'branching/lookahead/useimpliedbincons', 'branching/lookahead/uselevel2data', 'branching/lookahead/worsefactor', 'compression/largestrepr/iterations', 'compression/largestrepr/mincommonvars', 'compression/largestrepr/minnleaves', 'compression/largestrepr/priority', 'compression/weakcompr/convertconss', 'compression/weakcompr/minnleaves', 'compression/weakcompr/priority', 'concurrent/scip-counter/prefprio', 'concurrent/scip-cpsolver/prefprio', 'concurrent/scip-default/prefprio', 'concurrent/scip-easycip/prefprio', 'concurrent/scip-feas/prefprio', 'concurrent/scip-hardlp/prefprio', 'concurrent/scip-opti/prefprio', 'concurrent/scip/prefprio', 'display/nnodesbelowinc/active', 'display/nrank1nodes/active', 'heuristics/dualval/dynamicdepth', 'heuristics/dualval/forceimprovements', 'heuristics/dualval/freq', 'heuristics/dualval/freqofs', 'heuristics/dualval/heurverblevel', 'heuristics/dualval/lambdaobj', 'heuristics/dualval/lambdaslack', 'heuristics/dualval/maxcalls', 'heuristics/dualval/maxdepth', 'heuristics/dualval/maxequalranks', 'heuristics/dualval/mingap', 'heuristics/dualval/nlpverblevel', 'heuristics/dualval/onlycheaper', 'heuristics/dualval/onlyleaves', 'heuristics/dualval/priority', 'heuristics/dualval/rankvalue', 'heuristics/dualval/relaxcontvars', 'heuristics/dualval/relaxindicators', 'heuristics/repair/alpha', 'heuristics/repair/filename', 'heuristics/repair/freq', 'heuristics/repair/freqofs', 'heuristics/repair/maxdepth', 'heuristics/repair/maxnodes', 'heuristics/repair/minfixingrate', 'heuristics/repair/minnodes', 'heuristics/repair/nodesofs', 'heuristics/repair/nodesquot', 'heuristics/repair/priority', 'heuristics/repair/roundit', 'heuristics/repair/useobjfactor', 'heuristics/repair/useslackvars', 'heuristics/repair/usevarfix', 'presolving/dualagg/maxrounds', 'presolving/dualagg/priority', 'presolving/dualagg/timing', 'presolving/redvub/maxrounds', 'presolving/redvub/priority', 'presolving/redvub/timing', 'propagating/nlobbt/addlprows', 'propagating/nlobbt/delay', 'propagating/nlobbt/feastolfac', 'propagating/nlobbt/freq', 'propagating/nlobbt/itlimitfactor', 'propagating/nlobbt/maxprerounds', 'propagating/nlobbt/minlinearfrac', 'propagating/nlobbt/minnonconvexfrac', 'propagating/nlobbt/nlpiterlimit', 'propagating/nlobbt/nlptimelimit', 'propagating/nlobbt/nlpverblevel', 'propagating/nlobbt/presolpriority', 'propagating/nlobbt/presoltiming', 'propagating/nlobbt/priority', 'propagating/nlobbt/relobjtolfac', 'propagating/nlobbt/timingmask', 'propagating/symmetry/addconflictcuts', 'propagating/symmetry/addconsstiming', 'propagating/symmetry/addstrongsbcs', 'propagating/symmetry/addsymresacks', 'propagating/symmetry/addweaksbcs', 'propagating/symmetry/checksymmetries', 'propagating/symmetry/compresssymmetries', 'propagating/symmetry/compressthreshold', 'propagating/symmetry/conssaddlp', 'propagating/symmetry/delay', 'propagating/symmetry/detectdoublelex', 'propagating/symmetry/detectorbitopes', 'propagating/symmetry/detectsubgroups', 'propagating/symmetry/displaynorbitvars', 'propagating/symmetry/doubleequations', 'propagating/symmetry/enforcecomputesymmetry', 'propagating/symmetry/freq', 'propagating/symmetry/maxgenerators', 'propagating/symmetry/maxnconsssubgroup', 'propagating/symmetry/maxprerounds', 'propagating/symmetry/ofsymcomptiming', 'propagating/symmetry/orbitopalreduction/columnordering', 'propagating/symmetry/performpresolving', 'propagating/symmetry/preferlessrows', 'propagating/symmetry/presolpriority', 'propagating/symmetry/presoltiming', 'propagating/symmetry/priority', 'propagating/symmetry/recomputerestart', 'propagating/symmetry/sstaddcuts', 'propagating/symmetry/sstleaderrule', 'propagating/symmetry/sstleadervartype', 'propagating/symmetry/sstmixedcomponents', 'propagating/symmetry/ssttiebreakrule', 'propagating/symmetry/symfixnonbinaryvars', 'propagating/symmetry/symtiming', 'propagating/symmetry/symtype', 'propagating/symmetry/timingmask', 'propagating/symmetry/usecolumnsparsity', 'propagating/symmetry/usedynamicprop', 'separating/convexproj/delay', 'separating/convexproj/expbackoff', 'separating/convexproj/freq', 'separating/convexproj/maxbounddist', 'separating/convexproj/maxdepth', 'separating/convexproj/nlpiterlimit', 'separating/convexproj/priority', 'separating/gauge/delay', 'separating/gauge/expbackoff', 'separating/gauge/freq', 'separating/gauge/maxbounddist', 'separating/gauge/nlpiterlimit', 'separating/gauge/priority', 'solvingphases/enabled', 'solvingphases/fallback', 'solvingphases/feassetname', 'solvingphases/improvesetname', 'solvingphases/interruptoptimal', 'solvingphases/nodeoffset', 'solvingphases/optimalvalue', 'solvingphases/proofsetname', 'solvingphases/testmode', 'solvingphases/transitionmethod', 'solvingphases/useemphsettings', 'solvingphases/userestart1to2', 'solvingphases/userestart2to3', 'solvingphases/xtype', 'table/symmetry/active']

@Joao-Dionisio
Copy link
Collaborator

Hey @liangbug! Last week, @Opt-Mucca, @mmghannam, and I discussed this PR and came to the following conclusions.

  1. Everything not related to copying and threading is very useful and should be part of the scip.pxi
  2. Your copyModel method, while fixing problems with sourceModel, should not be added to scip.pxi. Rather, we should look into sourceModel to find out what is causing the parameters to disappear.
  3. Your parallelism should not be added to scip.pxi. The main reason not already mentioned by @Opt-Mucca is that, when solving a problem using your method, it is not possible (or easy, rather) to copy the solving process of the model that reaches the optimal solution and move it to the model that calls the method. This could be a significant source of confusion for users who do not look into the source code, since they would not be able to query the model they created.

However, we understand the frustration with using solveConcurrent, especially with the difficulty of compiling SCIP. For this reason, we believe that your code is still beneficial, and should be added to the examples. This has the added benefit of being the first example in the repo of modifying the source code.

What do you think of this, @liangbug? Does it sound reasonable?

@liangbug
Copy link
Contributor Author

liangbug commented Nov 6, 2024

I understand yours concerns.
I'll remove copyModel solveFirstInterruptOthers and keep optimizeNogil.
I'll remove addCopyModelSols addCopyModelBestSol addCopyModelSol and add method using SCIPtranslateSubSol.

2.  model addOrigVarsConssObjectiveFrom
3.  add some Solution methods
@liangbug
Copy link
Contributor Author

liangbug commented Nov 8, 2024

Hi @Opt-Mucca @Joao-Dionisio
I made some changes.

  1. remove Model solveFirstInterruptOthers
  2. change copyModel to addOrigVarsConssObjectiveFrom
  3. remove Model addCopyModelSols addCopyModelBestSol addCopyModelSol, add Solution translate
    please review again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants