Goobley
Goobley

Reputation: 341

Can this parallel loop cause a data race?

I have a std::vector filled before the parallel loop with std::pair<Object, bool>. The bools are all initialised to true. The loop is approximately as follows:

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;

Since we're only ever setting the bool tofalse I don't see this causing a data-race, but I don't trust my gut on multi-threading. Operations made on the result of this bool are done in a single thread afterwards (erasing all elements where bool == true in the vector using standard algorithms.

Advice here would be appreciated. I was going to use std::atomics, but of course, they can't be used in a std::vector since they're not copy-constructible.

Cheers!

Upvotes: 2

Views: 216

Answers (2)

David Schwartz
David Schwartz

Reputation: 182753

Here's an example of a way this can fail, and real-world code has failed precisely this way.

    for (auto& i : vector)
        if (i.first.ConstantFunctionDependingOnlyOnInput(x, y))
            i.second = false;

The compiler might optimize this code as follows:

for (auto& i : vector);
{
     bool j = i.second;
     bool k = i.first.Function(x, y);
     i.second = k ? false : j;
}

This can cause one thread to overwrite the results of another thread. This can be a legitimate optimization because an unconditional write can be cheaper than a conditional one since it can't be mispredicted.

Upvotes: 3

IanPudney
IanPudney

Reputation: 6021

You're correct - this will behave exactly as you expect (no data race) on any real-world system. While officially undefined behavior according to the C++ standard, real-world systems don't work that way. Here's an answer to a more broad question that includes this one.

Here's the text from the standard that says this is officially undefined, though:

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.

If you want standard-guaranteed safety, you could consider atomic memory accesses.

Upvotes: -2

Related Questions