Anton Z
Anton Z

Reputation: 21

tbb::parallel_for with preserved order

I have a single loop which I want to parallelize. The loop implies doing the following:

std::vector<int> input = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
std::vector<int> output;
for(size_t i(0); i < input.size(); ++i)
{
    output.emplace_back(input[i] * 2);
}

However, I would like to preserve the order in the output. I tried to use tbb::enumerable_thread_specific to do that:

tbb::enumerable_thread_specific<std::vector<int>> threadData;
tbb::parallel_for(size_t{0}, input.size(), [&](size_t i)
{
    auto& local = threadData.local();
    local.emplace_back(2 * input[i]);
});

for (const auto& local : threadData)
{
    output.insert(output.begin() + output.size(), local.begin(), local.end());
}

However, the order is not preserved. I also tried to specify the partitioner:

tbb::static_partitioner()

but it didn't help as well.

What is the correct way to parallelize a for loop while preserving the order in the output?

Upvotes: 2

Views: 860

Answers (1)

J&#233;r&#244;me Richard
J&#233;r&#244;me Richard

Reputation: 50836

Doing a task in parallel while preserving a given order is generally hard (and not always possible) since it often means some things should be done sequentially.

Here you can easily solve this thanks to direct indexing:

std::vector<int> input = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
std::vector<int> output(input.size());

tbb::parallel_for(size_t{0}, input.size(), [&](size_t i)
{
    output[i] = input[i] * 2;
}

Keep in mind that resizing vectors (and more generally working on dynamically sized data) in a parallel context is often a bad idea.

Upvotes: 0

Related Questions