这个并行循环会导致数据竞争吗?
Can this parallel loop cause a data race?
我在 std::pair<Object, bool>
的并行循环之前填充了一个 std::vector
。布尔值都被初始化为 true
。循环大致如下:
for (int x = 0; x < xMax; ++x) // can parallelising the loop in x cause a data race?
for (int y = 0; y < yMax; ++y)
for (auto& i : vector)
if (i.first.ConstantFunctionDependingOnlyOnInput(x, y))
i.second = false;
因为我们只将 bool 设置为 false
我不认为这会导致数据争用,但我不相信我对多线程的直觉。对该 bool 结果的操作随后在单个线程中完成(使用标准算法擦除向量中 bool == true
处的所有元素。
不胜感激。我打算使用 std::atomics
,但当然,它们不能用于 std::vector
,因为它们不可复制构造。
干杯!
你是对的 - 这将在任何真实世界的系统上完全符合你的预期(没有数据竞争)。虽然根据 C++ 标准官方 未定义的行为,但现实世界的系统不会那样工作。 Here 是对包含此问题的更广泛问题的回答。
这是来自标准的文本,表示这是官方未定义的,不过:
Two expression evaluations conflict if one of them modifies a memory
location (1.7) and the other one accesses or modifies the same memory
location.
如果要标准保证安全,可以考虑atomic内存访问。
这是一个失败的例子,现实世界的代码正是这样失败的。
for (auto& i : vector)
if (i.first.ConstantFunctionDependingOnlyOnInput(x, y))
i.second = false;
编译器可能会按如下方式优化此代码:
for (auto& i : vector);
{
bool j = i.second;
bool k = i.first.Function(x, y);
i.second = k ? false : j;
}
这会导致一个线程覆盖另一个线程的结果。这可能是一个合理的优化,因为无条件写入比有条件写入成本更低,因为它不会被错误预测。
我在 std::pair<Object, bool>
的并行循环之前填充了一个 std::vector
。布尔值都被初始化为 true
。循环大致如下:
for (int x = 0; x < xMax; ++x) // can parallelising the loop in x cause a data race?
for (int y = 0; y < yMax; ++y)
for (auto& i : vector)
if (i.first.ConstantFunctionDependingOnlyOnInput(x, y))
i.second = false;
因为我们只将 bool 设置为 false
我不认为这会导致数据争用,但我不相信我对多线程的直觉。对该 bool 结果的操作随后在单个线程中完成(使用标准算法擦除向量中 bool == true
处的所有元素。
不胜感激。我打算使用 std::atomics
,但当然,它们不能用于 std::vector
,因为它们不可复制构造。
干杯!
你是对的 - 这将在任何真实世界的系统上完全符合你的预期(没有数据竞争)。虽然根据 C++ 标准官方 未定义的行为,但现实世界的系统不会那样工作。 Here 是对包含此问题的更广泛问题的回答。
这是来自标准的文本,表示这是官方未定义的,不过:
Two expression evaluations conflict if one of them modifies a memory location (1.7) and the other one accesses or modifies the same memory location.
如果要标准保证安全,可以考虑atomic内存访问。
这是一个失败的例子,现实世界的代码正是这样失败的。
for (auto& i : vector)
if (i.first.ConstantFunctionDependingOnlyOnInput(x, y))
i.second = false;
编译器可能会按如下方式优化此代码:
for (auto& i : vector);
{
bool j = i.second;
bool k = i.first.Function(x, y);
i.second = k ? false : j;
}
这会导致一个线程覆盖另一个线程的结果。这可能是一个合理的优化,因为无条件写入比有条件写入成本更低,因为它不会被错误预测。