title: Possible race condition in OpenMP parallel for loop
body: <p>I'm using <a href="https://en.wikipedia.org/wiki/OpenMP" rel="nofollow noreferrer">OpenMP</a> to parallelize a for loop. This program uses the <a href="https://www.gurobi.com/documentation/9.0/refman/c_api_details.html" rel="nofollow noreferrer">Gurobi C API</a>.</p>
  
  <pre><code>GRBupdatemodel(model);
  
  #pragma omp parallel for
  for (int batch = 0; batch &lt; n_batch; ++batch)
  {
  
      int cind[1 + n_max];
      for (int j = 0; j &lt; n_max; ++j)
      {
          cind[1 + j] = n_sum + j;
      }
  
      double cval[1 + n_max];
      cval[0] = 1;
  
      GRBmodel* model_copy = GRBcopymodel(model);
      for (int i = 0; i &lt; n_sum; ++i)
      {
          cind[0] = i;
          for (int k = 0; k &lt; n_min; ++k)
          {
              for (int j = 0; j &lt; n_max; ++j) 
              {
                  cval[1 + j] = -*((double*) PyArray_GetPtr(array, (long []) {batch, i, j, k}));
              }
              GRBaddconstr(model_copy, 1 + n_max, cind, cval, GRB_LESS_EQUAL, 0, NULL);
          }
      }
      GRBoptimize(model_copy);
      GRBgetdblattrarray(model_copy, GRB_DBL_ATTR_X, 0, n_sum, values[batch]);
      GRBgetdblattrarray(model_copy, GRB_DBL_ATTR_X, n_sum, n_max, max_strategy[batch]);
      GRBgetdblattrarray(model_copy, GRB_DBL_ATTR_PI, 1, n_sum * n_min, (double *) min_strategies[batch]);
      GRBfreemodel(model_copy);
  }
  </code></pre>
  
  <p>Each iteration of this loop writes to a different section of the arrays <code>values</code>, <code>max_strategy</code>, and <code>min_strategies</code>.</p>
  
  <p>Removing <code>#pragma omp parallel for</code> yields correct results. Adding it yields incorrect results, including nan values. Thus I suspect there is a race condition in my loop, but I haven't been able to find it. Does anyone know what might be going wrong? I only see two types of writes in my loop body:</p>
  
  <ul>
  <li>To <code>cind</code>, <code>cval</code>, and <code>model_copy</code> (by <a href="https://www.gurobi.com/documentation/9.0/refman/c_getdblattrarray.html" rel="nofollow noreferrer">GRBgetdblattrarray</a>), which are local variables declared inside the loop body and therefore private to each thread.</li>
  <li>To non-overlapping sections of <code>values</code>, <code>max_strategy</code>, and <code>min_strategies</code>.</li>
  </ul>