Description
With GAMS 24.6 a new variant for the SolveLink option and model attribute has been added. If SolveLink is set to %solveLink.aSyncThreads%, GAMS does not wait for the solver to return and does not collect the result when a solve statement is executed. Instead, the model is generated and then passed to the solver in a separate thread while GAMS continues the execution. This way, multiple models can be solved in parallel and the results can be collected later. This is similar to the Grid Facility (SolveLink = %solveLink.asyncGrid%) with the difference, that the solver does not operate in its own process space but in a separate thread, which allows efficient in-memory communication between GAMS and the solver (like it is done with SolveLink = %solveLink.loadLibrary%). After the solve statement, one can store a handle of the model instance (using the model attribute mymodel.handle) and use the same functions that are used for the Grid Facility to collect the solution and deal with the model instance: HandleCollect(handle), HandleStatus(handle), and HandleDelete(handle). The new function ReadyCollect(handleParameter [, maxWait]) can be used to wait until a model is ready to be collected. It can be used for both SolveLink = %solveLink.aSyncThreads% and SolveLink = %solveLink.asyncGrid%. In this model the basic functionality is tested. Keyword: solveLink=%solveLink.aSyncThreads% Contributor: Lutz Westermann, January 2016
Small Model of Type : GAMS
Category : GAMS Test library
Main file : sl601.gms
$title 'Check correct behavior when using solveLink=%solveLink.aSyncThreads%' (SL601,SEQ=691)
$onText
With GAMS 24.6 a new variant for the SolveLink option and model attribute has
been added. If SolveLink is set to %solveLink.aSyncThreads%, GAMS does not wait
for the solver to return and does not collect the result when a solve statement
is executed. Instead, the model is generated and then passed to the solver in a
separate thread while GAMS continues the execution. This way, multiple models
can be solved in parallel and the results can be collected later.
This is similar to the Grid Facility (SolveLink = %solveLink.asyncGrid%) with
the difference, that the solver does not operate in its own process space but in
a separate thread, which allows efficient in-memory communication between GAMS
and the solver (like it is done with SolveLink = %solveLink.loadLibrary%).
After the solve statement, one can store a handle of the model instance (using
the model attribute mymodel.handle) and use the same functions that are used for
the Grid Facility to collect the solution and deal with the model instance:
HandleCollect(handle), HandleStatus(handle), and HandleDelete(handle).
The new function ReadyCollect(handleParameter [, maxWait]) can be used to wait
until a model is ready to be collected. It can be used for both SolveLink =
%solveLink.aSyncThreads% and SolveLink = %solveLink.asyncGrid%.
In this model the basic functionality is tested.
Keyword: solveLink=%solveLink.aSyncThreads%
Contributor: Lutz Westermann, January 2016
$offText
Sets
i canning plants / seattle, san-diego /
j markets / new-york, chicago, topeka / ;
Parameters
a(i) capacity of plant i in cases
/ seattle 350
san-diego 600 /
b(j) demand at market j in cases
/ new-york 325
chicago 300
topeka 275 / ;
Table d(i,j) distance in thousands of miles
new-york chicago topeka
seattle 2.5 1.7 1.8
san-diego 2.5 1.8 1.4 ;
Scalar f freight in dollars per case per thousand miles /90/ ;
Parameter c(i,j) transport cost in thousands of dollars per case ;
c(i,j) = f * d(i,j) / 1000 ;
Variables
x(i,j) shipment quantities in cases
z total transportation costs in thousands of dollars ;
Positive Variable x ;
Equations
cost define objective function
supply(i) observe supply limit at plant i
demand(j) satisfy demand at market j ;
cost .. z =e= sum((i,j), c(i,j)*x(i,j)) ;
supply(i) .. sum(j, x(i,j)) =l= a(i) ;
demand(j) .. sum(i, x(i,j)) =g= b(j) ;
Model transport /all/ ;
*Solve model, wait for results, collect result, delete handle and do some checks
$onEcho > SolveWaitCollectDelete.inc
Solve transport using lp minimizing z ;
abort$(ReadyCollect (transport.handle)<>0) 'Problem waiting for model', transport.handle;
abort$(HandleCollect(transport.handle)<>1) 'Problem collecting results', transport.handle;
abort$(transport.objVal<>153.675) 'wrong objective value';
abort$(z.l<>153.675) 'wrong value for z';
z.l = 0;
* Looks odd, but there was an error, that did not allow this for sl=6
transport.handle = transport.handle;
execute_loadhandle transport;
abort$(HandleDelete (transport.handle)<>0) 'Problem deleteing result', transport.handle;
$offEcho
* Set solvelink
option solvelink = %solveLink.aSyncThreads%;
* Not every solver works with sl=6, test that the resetting to 3 works if 6 cannot be used
* Select a solver that supports %solveLink.aSyncThreads%
option lp=cplex;
$include SolveWaitCollectDelete.inc
abort$(transport.LinkUsed<>%solveLink.aSyncThreads%) 'sl was reset unexpectedly'
* Select a solver that does not support %solveLink.aSyncThreads%
option lp=minos;
$include SolveWaitCollectDelete.inc
abort$(transport.LinkUsed<>%solveLink.asyncGrid%) 'sl should be reset to %solveLink.asyncGrid%'
* Check return codes of functions
Scalar wrongHandle /111/;
abort$(ReadyCollect(wrongHandle)<>1) 'Expected ReadyCollect to signal that there is no job to wait for';
abort$(HandleStatus(wrongHandle)<>0) 'Expected error return from HandleStatus';
abort$(HandleCollect(wrongHandle)<>0) 'Expected error return from HandleCollect';
abort$(HandleDelete(wrongHandle)<>1) 'Expected error return from HandleDelete';
set s /s1*s3/;
parameter handles(s);
handles(s)=no;
abort$(ReadyCollect(handles)<>2) 'Expected ReadyCollect to signal that the provided symbol is empty';