Reputation: 21
I am writing C++ multithreaded code using GCC C++20 on Intel Broadwell XEONs or AMD EPYC 7551s, Intel TBB, and Pagmo2 libraries for optimization problems. If I declare concurrent_vector<double> X
and the elements of X
are concurrently modified by multiple running threads, I believe the operations would be thread-safe. Please kindly correct me if I'm wrong.
My real question is this: If multiple threads access the elements of X
, i.e. more than one thread attempts to simultaneously modify an element of X
, e.g. X.at(5)
, will the operation be atomic and lock-free or will there be a lock with significant performance consequences? Also, let's say that thread 0 modifies X.at(i)
while thread 1 simultaneously modifies X.at(j)
with i != j
. What will be the performance implications and will the operation be lock-free i.e. atomic?
I am new to concurrent C++/TBB and was not able to find a definitive, clear answer using a Google search.
I have searched Google and the TBB documentation but have not found a clear answer to the above question yet. I'm not sure if TBB concurrent containers are actually atomic?
Upvotes: 0
Views: 242
Reputation: 1988
...will the operation be lock-free i.e. atomic?
There will be no locks, but that does not mean it behaves like std::atomic
concurrent_vector allows multiple threads to access (read, write, take the address) of the same element. It does not serialize the accesses, so whether those accesses are safe depends upon the data type.
What will be the performance implications ...
tbb::concurrent_vector deals with the problem by not moving existing storage when resizing. Instead, in order to grow, it creates a new chunk of storage. The chunks are accessed by a fast constant-time indexing scheme. See tbb/concurrent_vector.h for how it is implemented.
However, there is no free lunch here. The concurrent_vector indexing introduces an extra level of complexity compared to std::vector. So if you do not need to concurrently grow and access a vector, I recommend using std::vector. But if you do have multiple threads appending to a dynamically growing array, then concurrent_vector can be a good fit.
The performance cost to access an element is non-negligible due to the implementation, which is required to support the use case of concurrently growing & accessing a vector.
Note: Quotes are taken from https://community.intel.com/t5/Intel-oneAPI-Threading-Building/concurrent-vector-thread-safety/m-p/912060 for an answer from a likely Intel employee (since their username contains _INTEL).
Upvotes: 1