c - OpenMP 并行 for 循环中可能的竞争条件
问题描述
我正在使用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);
}
此循环的每次迭代都会写入数组values
、max_strategy
和的不同部分min_strategies
。
删除#pragma omp parallel for
会产生正确的结果。添加它会产生不正确的结果,包括 nan 值。因此,我怀疑我的循环中存在竞争条件,但我无法找到它。有谁知道可能出了什么问题?我在循环体中只看到两种类型的写入:
- To
cind
,cval
, andmodel_copy
(by GRBgetdblattrarray ),它们是在循环体内声明的局部变量,因此对每个线程都是私有的。 values
到、max_strategy
和的非重叠部分min_strategies
。
解决方案
https://www.gurobi.com/documentation/8.1/refman/py_env2.html
根据文档,每次循环迭代中的模型都不是独立的副本。它们共享相同的环境变量。这意味着它们可能从同一内存中读取/写入。如果您确保每个副本都有自己的环境,它可能会成功。
我看到您正在从 python 调用此代码。如果你只使用 C 是为了使用多线程计算,我建议使用带有 joblib 或 dask 的纯 python 代码来获得相同的结果。由于无法序列化不同的模型,因此竞态条件在 python 中也很明显。请参阅此支持问题
推荐阅读
- powershell - 如何使用 Powershell 将对象与数组进行比较?
- java - 使用 iText 将文本添加到 pdf 的特定页面
- reactjs - 如何在 Reactjs 中卸载组件
- sql - 连接代码以获得总和
- c++ - 在不使用任何 STL 容器的情况下删除重复项
- java - Android - 我将如何动态更改 clickListener
- video - 我想禁用视频元素的所有默认控件并构建自己的控件
- javascript - 令人沮丧的 Javascript 错误
- javascript - 如何检查字符串是否仅包含某些字母,如果有其他字母,则返回 false
- php - Woocommerce 订单到期日