In [1] a problem is described:
The standard loop is the most self-explanatory. But we incur quite some overhead. In each cycle we have:
The last approach is to setup asynchronous scenario solves. We split the 1,000 scenarios in 4 batches of 250 scenarios. We then solve each batch in parallel and use the scenario solver to solve a batch using 1 solver thread. This more coarse-grained parallelism is way more effective than using multiple threads inside the MIP solver. A disadvantage is that the tools for this are rather poorly designed and the setup for this is quite cumbersome: different loops are needed to launch solvers asynchronously and retrieving results after threads terminate.
Select 2 teams of 6 players from a population of 24 players such that the average ELO rating of each team is a close as possible.It came as a surprise to me, given some random data for the ratings, I was always able to find two teams with exactly the same average rating. When we try this for say 1,000 cases, we have to solve 1,000 independent scenarios, each of them solving a small MIP model. It is interesting to see how we can optimize this loop using GAMS.
| Approach | Description | Elapsed Time mm:ss |
|---|---|---|
| A. Standard loop | Solve 1,000 modelsloop(k, | 12:12 |
| B. Optimized loop | Reduce printing to listing file and use DLL interface.m.solvelink=5; | 3:33 |
| C. Scenario solver | Solve 1,000 scenarios by updating model. Solver threads: 1.solve m min z using mip scenario dict; | 1:32 |
| D. Scenario solver | Tell MIP solver to use 4 threadsm.threads=4; | 2:19 |
| E. Asynchronous scenario solver | Each asynchronous solve calls scenario solver with 250 scenariosm.solveLink = 3;Note that these solves operate asynchronously. | 0:25 |
The standard loop is the most self-explanatory. But we incur quite some overhead. In each cycle we have:
- GAMS generates the model and prints equation and column listing
- GAMS shuts down after saving its environment
- The solver executable is called
- GAMS restarts and reads back the environment
- GAMS reads the solution and prints it
The optimized loop will keep GAMS in memory and calls the solver as a DLL instead of an executable. In addition printing is omitted. GAMS is still generating each model, and a solver is loading and solving the model from scratch.
The scenario solver will keep the model stored inside the solver and applies updates. In essence the GAMS loop is moved closer to the solver. To enable the scenario solver, we calculate all random ratings in advance:
rk(k,i) = round(normal(1400,400));
As these are very small MIP models, adding solver threads to solve each model is not very useful. In our case it was even slightly worsening things. For small models most of the work is sequential (presolve, scaling, preprocessing etc) and there is also some overhead in doing parallel MIP (fork, wait, join).
rk(k,i) = round(normal(1400,400));
As these are very small MIP models, adding solver threads to solve each model is not very useful. In our case it was even slightly worsening things. For small models most of the work is sequential (presolve, scaling, preprocessing etc) and there is also some overhead in doing parallel MIP (fork, wait, join).
The last approach is to setup asynchronous scenario solves. We split the 1,000 scenarios in 4 batches of 250 scenarios. We then solve each batch in parallel and use the scenario solver to solve a batch using 1 solver thread. This more coarse-grained parallelism is way more effective than using multiple threads inside the MIP solver. A disadvantage is that the tools for this are rather poorly designed and the setup for this is quite cumbersome: different loops are needed to launch solvers asynchronously and retrieving results after threads terminate.
Conclusions:
- The end result: even for 1000 random scenarios, we can find two teams that have exactly the same average ELO rating.
- Solving many different independent scenarios may require some attention to achieve best performance.
References
- Selecting Chess Players, https://yetanothermathprogrammingconsultant.blogspot.com/2018/11/selecting-chess-players.html