Here&#39;s a patch (against Osi releases 0.100.0) for what I did to make it thread-safe (at least fixing the obvious stuff). <br><br>Thanks,<br>Matt<br><br><br><br><br><br>magh@shark:~/COIN/coin-Decomp/Osi/src/OsiCpx$ svn diff OsiCpxSolverInterface.cpp<br>

Index: OsiCpxSolverInterface.cpp<br>===================================================================<br>--- OsiCpxSolverInterface.cpp   (revision 1399)<br>+++ OsiCpxSolverInterface.cpp   (working copy)<br>@@ -30,7 +30,7 @@<br>

 #include &quot;CoinWarmStartBasis.hpp&quot;<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(), rowslack, 0, nrows-1 );<br>+            printf(&quot;err=%d\n&quot;, err);<br>              if ( err == CPXERR_NO_SOLN || err == 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, nrows-1 );<br>+            printf(&quot;err2=%d\n&quot;, 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(&quot;numInstances_ = %d\n&quot;, numInstances_);<br>

+   //MVG<br>+   if ( numInstances_ == 0 )<br>+   {<br>       int err;<br><br> #if CPX_VERSION &gt;= 800<br>@@ -2568,6 +2572,8 @@<br>       env_ = CPXopenCPLEXdevelop( &amp;err );<br> #endif<br><br>+      printf(&quot;open env = %p\n&quot;, env_);<br>

+<br>       checkCPXerror( err, &quot;CPXopenCPLEXdevelop&quot;, &quot;incrementInstanceCounter&quot; );<br>       assert( env_ != NULL );<br> #ifndef NDEBUG<br>@@ -2580,7 +2586,7 @@<br>       //CPXsetlogfile( env_, fp );<br>

       err = sscanf( CPXversion( env_ ), &quot;%d.%d.%d&quot;, &amp;cpxVersionMajor_, &amp;cpxVersionMinor_, &amp;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(&quot;OsiCpxSolverInterface::OsiCpxSolverInterface()\n&quot;);<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 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>       &lt;/ul&gt;<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>
       &lt;/ul&gt;<br>   */<br>-  static void decrementInstanceCounter();<br>+   void decrementInstanceCounter();//MVG<br>+   //static void decrementInstanceCounter();<br><br>   /// Return the number of instances of instantiated objects using 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><div class="gmail_quote"><span dir="ltr"></span><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Ok. Thanks Matt. For the tests I have run so far, my simple fix of removing all the static vars from OsiCpx seems to have worked. However, my usage for this case is very simple. I am essentially just solving the same N models on T threads over and over again with just a minor problem modifications. So, I think the thread-safey in my case is primarly cplex&#39;s - which we know that part is fine. The main &quot;connector&quot; through OSI seems to be the env_, lp_ vars - of which env_ was static.<br>


<br>I&#39;ll definitely keep my eye out for other issues and I&#39;ll let you know / add tickets.<br><br>Thanks,<br>Matt G<div><div></div><div class="h5"><br><br><br><div class="gmail_quote"><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">


Matt-<br>
<br>
I&#39;m not sure that thread safety is quite that simple.  You may have<br>
eliminated some of the obvious races, but it wouldn&#39;t surprise me to<br>
find other hidden ones that don&#39;t crop up as frequently.  OSI really<br>
needs a more comprehensive audit for thread safety, which we are aware<br>
of and which is on my agenda.<br>
<br>
If you have patches that you think make a good starting point, I&#39;m glad<br>
to have them.  The best place to keep them is probably attached to a<br>
ticket.<br>
<br>
Thanks.<br>
<br>
                Matt<br>
<div><div></div><div><br>
<br>
<br>
On Fri, 2009-08-28 at 01:57 -0400, Matthew Galati wrote:<br>
&gt; FYI. If I remove all the references to static env_, version, etc...<br>
&gt; things seem to work fine now. OsiCpx is then thread-safe.<br>
&gt;<br>
&gt; Can this be changed? or at least provided as an option? It is a shame<br>
&gt; if one cannot use Osi in a multi-threaded environment.<br>
&gt; ________________________________________<br>
&gt; From: <a href="mailto:osi-bounces@list.coin-or.org" target="_blank">osi-bounces@list.coin-or.org</a> [<a href="mailto:osi-bounces@list.coin-or.org" target="_blank">osi-bounces@list.coin-or.org</a>] On<br>
&gt; Behalf Of Matthew Galati [<a href="mailto:magh@lehigh.edu" target="_blank">magh@lehigh.edu</a>]<br>
&gt; Sent: Thursday, August 27, 2009 11:55 PM<br>
&gt; To: <a href="mailto:osi@list.coin-or.org" target="_blank">osi@list.coin-or.org</a><br>
&gt; Subject: [Osi] osicpx threaded<br>
&gt;<br>
&gt; Has anyone successfully used more than one instance/thread of OsiCpx<br>
&gt; simultaneously? I am trying to do this. Constructing 2 instances of<br>
&gt; OsiCpx and using standard pthreads, solve two MILPs on 2 threads. It<br>
&gt; crashes. Valgrind/Helgrind is showing lots of potential race<br>
&gt; conditions. Looking a little deeper into OsiCpx, I noticed that<br>
&gt; although I have two different CpxLp ptrs, I have one CpxEnv ptr. In<br>
&gt; fact, the cpx env is a static variable in OsiCpx. Doesn&#39;t this make<br>
&gt; OsiCpx not thread-safe? Is there any easy way around this?<br>
&gt;<br>
&gt; Thanks,<br>
&gt; Matt<br>
&gt;<br>
&gt;<br>
</div></div>&gt; _______________________________________________<br>
&gt; Osi mailing list<br>
&gt; <a href="mailto:Osi@list.coin-or.org" target="_blank">Osi@list.coin-or.org</a><br>
&gt; <a href="http://list.coin-or.org/mailman/listinfo/osi" target="_blank">http://list.coin-or.org/mailman/listinfo/osi</a><br>
<font color="#888888">--<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>
</font></blockquote></div><br>
</div></div></blockquote></div><br>