parallel_do requires copiable items, and parallel_for_each inherits this limitation

parallel_do requires copiable items, and parallel_for_each inherits this limitation


suppose we have a container C of objects T, C<T> and T is non-copiable, deriving from boost::noncopiable, and some tbb::parallel_do calls:

C<T> container;
tbb::parallel_do(container.begin(), container.end(), ...);

or suppose we have an abstract base class B:

boost::ptr_vector<B> container;
tbb::parallel_do(container.begin(), container.end(), ...);

These don't compile as Item, so T or B, is copied in do_iteration_task, there is an "Item my_value". It should be "Item& my_value" but I understand this violates the whole design, as you can feed objects to a tbb::parallel_do while it's still running so objects must (?) be part of internal tasks. I'm not a big fan of that but fine, even if I haven't spotted this limitation in any documentation.

BUT this doesn't justify tbb::parallel_for_each to fail. It's currently implemented using tbb::parallel_do that has this constraint, so you cannot use it with non-copiable items or complex containers like boost::ptr_* BUT tbb::parallel_for_each doesn't need to copy object.

Can we have it reimplemented in terms of tbb::parallel_for? Or possibly have the limitation in tbb::parallel_do removed?

At affects al least any TBB version <= 4.1.

Thank you.


5 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

C container;

tbb::parallel_do(container.begin(), container.end(), [&]{ });
tbb::parallel_do(container.begin(), container.end(), [&container]{ });

Jim Dempsey

Yes, ok, the lambda were wrong, but the point is still valid.

Don't pass the container entries by value, pass by reference or pointer, or {container reference/pointer and index}.

If you do not want copy operators (or can't have), then do not use a syntax that requires a copy operator.

Jim Dempsey

The problem with the proposed solution would be that parallel_for implies random iteration and parallel_for_each implies input iteration, which does not require the iterators' referents to persist beyond reference incrementation, so even without feeder functionality a copy is required to achieve parallelism. Perhaps template specialisation magic could save the day (tell me if I should have had a coffee first), but that can get complicated to implement and maintain and would muddle the situation, so why not instead make the intention clear by using parallel_for directly?

Leave a Comment

Please sign in to add a comment. Not a member? Join today