You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
For example, consider this code to build a sparse matrix in the coordinate format:
using TKey = std::pair<size_t, size_t>;
using TVal = std::atomic<double>;
tbb::concurrent_map<TKey, TVal> sparse_matrix;
tbb::parallel_for(i_start, i_stop, [&](size_t i) {
// some computation for the i-th index is performed, resulting in a key and a corresponding value
// key may or may not have been computed before
// update map
sparse_matrix[key].fetch_add(val); // is this thread safe?
});
Although rare, two threads may need to fetch/insert the same key and update the corresponding value.
My understanding is that, if the key does not exist, concurrent_map ensures safe insertion, and if the key does exist concurrent_map ensures safe lookup. std::atomic<T>::fetch_add ensures the value itself is updated safely.
My questions:
Is sparse_matrix[key].fetch_add(val), as shown above, safe? Or should I precompute every key and preallocate the map with 0s using insert (is insert or emplace safer)?
Do I need std::atomic or is sparse_matrix[key] += val safe?
The text was updated successfully, but these errors were encountered:
@carlos-souto, I agree with @pavelkumbrasev,
Just want to explain the answer a bit: that usage of std::atomic is strictly required if for some indices [i_start, i_stop) the same key can be produced and hence the same variable in the concurrent_map would be accessed (that is unsafe as Pavel mentioned).
The std::atomic is not required if for each index of parallel_for the unique key is produced and the container is only used to ensure concurrent insertion from multiple threads.
Following your comments and the code snippet provided, it seems like you are in the first scenario, I just wanted to highlight the second one in case some of our understanding is incorrect:)
For example, consider this code to build a sparse matrix in the coordinate format:
Although rare, two threads may need to fetch/insert the same key and update the corresponding value.
My understanding is that, if the key does not exist,
concurrent_map
ensures safe insertion, and if the key does existconcurrent_map
ensures safe lookup.std::atomic<T>::fetch_add
ensures the value itself is updated safely.My questions:
sparse_matrix[key].fetch_add(val)
, as shown above, safe? Or should I precompute every key and preallocate the map with 0s usinginsert
(isinsert
oremplace
safer)?std::atomic
or issparse_matrix[key] += val
safe?The text was updated successfully, but these errors were encountered: