Will do. But I am investigating some odd behavior. The duals I get from CPX after a few iterations of my algorithm are different with this patch versus without. I don't understand why since the only change was to move the env/lp vars from static to class members. I will get back to you.<br>
<br><div class="gmail_quote"><br><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><div class="im">On Mon, 2009-09-14 at 22:59 -0400, Matthew Galati wrote:<br>
> Here's a patch (against Osi releases 0.100.0) for what I did to make<br>
> it thread-safe (at least fixing the obvious stuff).<br>
<br>
</div>Thanks, Matt. Can you add the patch to the ticket?<br>
<div><div></div><div class="h5"><br>
><br>
> Thanks,<br>
> Matt<br>
><br>
><br>
><br>
><br>
><br>
> magh@shark:~/COIN/coin-Decomp/Osi/src/OsiCpx$ svn diff<br>
> OsiCpxSolverInterface.cpp<br>
> Index: OsiCpxSolverInterface.cpp<br>
> ===================================================================<br>
> --- OsiCpxSolverInterface.cpp (revision 1399)<br>
> +++ OsiCpxSolverInterface.cpp (working copy)<br>
> @@ -30,7 +30,7 @@<br>
> #include "CoinWarmStartBasis.hpp"<br>
><br>
><br>
> -// #define DEBUG 1<br>
> +//#define DEBUG 1<br>
><br>
> #ifdef DEBUG<br>
> #define debugMessage printf<br>
> @@ -1291,6 +1291,7 @@<br>
> {<br>
> double *rowslack = new double[nrows];<br>
> int err = CPXgetmipslack( env_, getMutableLpPtr(),<br>
> rowslack, 0, nrows-1 );<br>
> + printf("err=%d\n", err);<br>
> if ( err == CPXERR_NO_SOLN || err ==<br>
> CPXERR_NO_INT_SOLN )<br>
> CoinFillN( rowact_, nrows, 0.0 );<br>
> else<br>
> @@ -1304,6 +1305,7 @@<br>
> else<br>
> {<br>
> int err = CPXgetax( env_, getMutableLpPtr(), rowact_, 0,<br>
> nrows-1 );<br>
> + printf("err2=%d\n", err);<br>
> if ( err == CPXERR_NO_SOLN )<br>
> CoinFillN( rowact_, nrows, 0.0 );<br>
> else<br>
> @@ -2558,8 +2560,10 @@<br>
><br>
> void OsiCpxSolverInterface::incrementInstanceCounter()<br>
> {<br>
> - if ( numInstances_ == 0 )<br>
> - {<br>
> + printf("numInstances_ = %d\n", numInstances_);<br>
> + //MVG<br>
> + if ( numInstances_ == 0 )<br>
> + {<br>
> int err;<br>
><br>
> #if CPX_VERSION >= 800<br>
> @@ -2568,6 +2572,8 @@<br>
> env_ = CPXopenCPLEXdevelop( &err );<br>
> #endif<br>
><br>
> + printf("open env = %p\n", env_);<br>
> +<br>
> checkCPXerror( err, "CPXopenCPLEXdevelop",<br>
> "incrementInstanceCounter" );<br>
> assert( env_ != NULL );<br>
> #ifndef NDEBUG<br>
> @@ -2580,7 +2586,7 @@<br>
> //CPXsetlogfile( env_, fp );<br>
> err = sscanf( CPXversion( env_ ), "%d.%d.%d",<br>
> &cpxVersionMajor_, &cpxVersionMinor_, &cpxVersionMinorMinor_ );<br>
> assert( err == 3 );<br>
> - }<br>
> + }<br>
> numInstances_++;<br>
> }<br>
><br>
> @@ -2636,7 +2642,13 @@<br>
> matrixByCol_(NULL),<br>
> coltype_(NULL),<br>
> coltypesize_(0),<br>
> - probtypemip_(false)<br>
> + probtypemip_(false),<br>
> + //MVG<br>
> + env_(NULL),<br>
> + cpxVersionMajor_(0),<br>
> + cpxVersionMinor_(0),<br>
> + cpxVersionMinorMinor_(0),<br>
> + numInstances_(0)<br>
> {<br>
> debugMessage("OsiCpxSolverInterface::OsiCpxSolverInterface()\n");<br>
><br>
> @@ -2805,12 +2817,13 @@<br>
> //------------------------------------------------------------------<br>
> // Static data<br>
> //------------------------------------------------------------------<br>
> -CPXENVptr OsiCpxSolverInterface::env_ = NULL;<br>
> +//CPXENVptr OsiCpxSolverInterface::env_ = NULL;<br>
><br>
> -int OsiCpxSolverInterface::cpxVersionMajor_ = 0;<br>
> -int OsiCpxSolverInterface::cpxVersionMinor_ = 0;<br>
> -int OsiCpxSolverInterface::cpxVersionMinorMinor_ = 0;<br>
> -unsigned int OsiCpxSolverInterface::numInstances_ = 0;<br>
> +//MVG<br>
> +//int OsiCpxSolverInterface::cpxVersionMajor_ = 0;<br>
> +//int OsiCpxSolverInterface::cpxVersionMinor_ = 0;<br>
> +//int OsiCpxSolverInterface::cpxVersionMinorMinor_ = 0;<br>
> +//unsigned int OsiCpxSolverInterface::numInstances_ = 0;<br>
><br>
> //-------------------------------------------------------------------<br>
> // Get pointer to CPXLPptr.<br>
><br>
><br>
><br>
><br>
><br>
> magh@shark:~/COIN/coin-Decomp/Osi/src/OsiCpx$ svn diff<br>
> OsiCpxSolverInterface.hpp<br>
> Index: OsiCpxSolverInterface.hpp<br>
> ===================================================================<br>
> --- OsiCpxSolverInterface.hpp (revision 1399)<br>
> +++ OsiCpxSolverInterface.hpp (working copy)<br>
> @@ -641,7 +641,8 @@<br>
> 1 from 0.<br>
> </ul><br>
> */<br>
> - static void incrementInstanceCounter();<br>
> + //static void incrementInstanceCounter();<br>
> + void incrementInstanceCounter(); //MVG<br>
><br>
> /** CPLEX has a context which should be deleted after CPLEX calls.<br>
> This method:<br>
> @@ -651,10 +652,12 @@<br>
> 0 from 1.<br>
> </ul><br>
> */<br>
> - static void decrementInstanceCounter();<br>
> + void decrementInstanceCounter();//MVG<br>
> + //static void decrementInstanceCounter();<br>
><br>
> /// Return the number of instances of instantiated objects using<br>
> CPLEX services.<br>
> - static unsigned int getNumInstances();<br>
> + //static unsigned int getNumInstances();<br>
> + unsigned int getNumInstances();//MVG<br>
> //@}<br>
> //@}<br>
><br>
> @@ -787,13 +790,20 @@<br>
> /**@name Private static class data */<br>
> //@{<br>
> /// CPLEX environment pointer<br>
> - static CPXENVptr env_;<br>
> + //static CPXENVptr env_;<br>
> + CPXENVptr env_; //MVG<br>
> /// CPLEX version<br>
> - static int cpxVersionMajor_;<br>
> - static int cpxVersionMinor_;<br>
> - static int cpxVersionMinorMinor_;<br>
> + //static int cpxVersionMajor_;<br>
> + //static int cpxVersionMinor_;<br>
> + //static int cpxVersionMinorMinor_;<br>
> /// Number of live problem instances<br>
> - static unsigned int numInstances_;<br>
> + //static unsigned int numInstances_;<br>
> + /// CPLEX version<br>
> + int cpxVersionMajor_;<br>
> + int cpxVersionMinor_;<br>
> + int cpxVersionMinorMinor_;<br>
> + /// Number of live problem instances<br>
> + unsigned int numInstances_;<br>
> //@}<br>
><br>
><br>
><br>
><br>
><br>
><br>
><br>
><br>
> Ok. Thanks Matt. For the tests I have run so far, my simple<br>
> fix of removing all the static vars from OsiCpx seems to have<br>
> worked. However, my usage for this case is very simple. I am<br>
> essentially just solving the same N models on T threads over<br>
> and over again with just a minor problem modifications. So, I<br>
> think the thread-safey in my case is primarly cplex's - which<br>
> we know that part is fine. The main "connector" through OSI<br>
> seems to be the env_, lp_ vars - of which env_ was static.<br>
><br>
> I'll definitely keep my eye out for other issues and I'll let<br>
> you know / add tickets.<br>
><br>
> Thanks,<br>
> Matt G<br>
><br>
><br>
><br>
><br>
><br>
> Matt-<br>
><br>
> I'm not sure that thread safety is quite that simple.<br>
> You may have<br>
> eliminated some of the obvious races, but it wouldn't<br>
> surprise me to<br>
> find other hidden ones that don't crop up as<br>
> frequently. OSI really<br>
> needs a more comprehensive audit for thread safety,<br>
> which we are aware<br>
> of and which is on my agenda.<br>
><br>
> If you have patches that you think make a good<br>
> starting point, I'm glad<br>
> to have them. The best place to keep them is probably<br>
> attached to a<br>
> ticket.<br>
><br>
> Thanks.<br>
><br>
> Matt<br>
><br>
><br>
><br>
><br>
> On Fri, 2009-08-28 at 01:57 -0400, Matthew Galati<br>
> wrote:<br>
> > FYI. If I remove all the references to static env_,<br>
> version, etc...<br>
> > things seem to work fine now. OsiCpx is then<br>
> thread-safe.<br>
> ><br>
> > Can this be changed? or at least provided as an<br>
> option? It is a shame<br>
> > if one cannot use Osi in a multi-threaded<br>
> environment.<br>
> > ________________________________________<br>
> > From: <a href="mailto:osi-bounces@list.coin-or.org">osi-bounces@list.coin-or.org</a><br>
> [<a href="mailto:osi-bounces@list.coin-or.org">osi-bounces@list.coin-or.org</a>] On<br>
> > Behalf Of Matthew Galati [<a href="mailto:magh@lehigh.edu">magh@lehigh.edu</a>]<br>
> > Sent: Thursday, August 27, 2009 11:55 PM<br>
> > To: <a href="mailto:osi@list.coin-or.org">osi@list.coin-or.org</a><br>
> > Subject: [Osi] osicpx threaded<br>
> ><br>
> > Has anyone successfully used more than one<br>
> instance/thread of OsiCpx<br>
> > simultaneously? I am trying to do this. Constructing<br>
> 2 instances of<br>
> > OsiCpx and using standard pthreads, solve two MILPs<br>
> on 2 threads. It<br>
> > crashes. Valgrind/Helgrind is showing lots of<br>
> potential race<br>
> > conditions. Looking a little deeper into OsiCpx, I<br>
> noticed that<br>
> > although I have two different CpxLp ptrs, I have one<br>
> CpxEnv ptr. In<br>
> > fact, the cpx env is a static variable in OsiCpx.<br>
> Doesn't this make<br>
> > OsiCpx not thread-safe? Is there any easy way around<br>
> this?<br>
> ><br>
> > Thanks,<br>
> > Matt<br>
> ><br>
> ><br>
><br>
> > _______________________________________________<br>
> > Osi mailing list<br>
> > <a href="mailto:Osi@list.coin-or.org">Osi@list.coin-or.org</a><br>
> > <a href="http://list.coin-or.org/mailman/listinfo/osi" target="_blank">http://list.coin-or.org/mailman/listinfo/osi</a><br>
> --<br>
> Matthew Saltzman<br>
><br>
> Clemson University Math Sciences<br>
> mjs AT clemson DOT edu<br>
> <a href="http://www.math.clemson.edu/%7Emjs" target="_blank">http://www.math.clemson.edu/~mjs</a><br>
><br>
><br>
><br>
</div></div>--<br>
<div><div></div><div class="h5"> Matthew Saltzman<br>
<br>
Clemson University Math Sciences<br>
mjs AT clemson DOT edu<br>
<a href="http://www.math.clemson.edu/%7Emjs" target="_blank">http://www.math.clemson.edu/~mjs</a><br>
</div></div></blockquote></div><br>