OpenMP并行for循环中的可能竞争条件

时间:2019-12-25 20:25:01

标签: c parallel-processing openmp shared-memory race-condition

我正在使用OpenMP并行化for循环。该程序使用Gurobi C API

GRBupdatemodel(model);

#pragma omp parallel for
for (int batch = 0; batch < n_batch; ++batch)
{

    int cind[1 + n_max];
    for (int j = 0; j < 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 < n_sum; ++i)
    {
        cind[0] = i;
        for (int k = 0; k < n_min; ++k)
        {
            for (int j = 0; j < 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);
}

此循环的每次迭代都会写入数组valuesmax_strategymin_strategies的不同部分。

删除#pragma omp parallel for会得到正确的结果。添加它会产生不正确的结果,包括nan值。因此,我怀疑循环中存在竞赛条件,但我找不到它。有谁知道可能出了什么问题?我在循环体内仅看到两种类型的写入:

  • 对于cindcvalmodel_copy(由GRBgetdblattrarray而言),它们是在循环体内声明的局部变量,因此对每个线程都是私有的。
  • valuesmax_strategymin_strategies的非重叠部分。

1 个答案:

答案 0 :(得分:2)

https://www.gurobi.com/documentation/8.1/refman/py_env2.html

根据文档,每次循环迭代中的模型都不是独立的副本。它们共享相同的环境变量。这意味着它们可能从同一内存进行读/写操作。如果您确保每个副本都有自己的环境,则可能会成功。

我看到您正在从python调用此代码。如果仅使用C来使用多线程计算,我建议将纯python代码与joblib或dask一起使用,以得到相同的结果。竞争条件在python中也很明显,因为无法对不同的模型进行序列化。看到这个support question