$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';