Reputation: 6400
For some time, my Rust program used a DashMap with a parallel iterator bridge. This was a major performance bottleneck, and I have just found that these days, DashMap supposedly supports direct parallel iteration. So I updated my dependency crates and changed my code. Now I have my DashMap<K, V, S>
like this
let families_by_location: DashMap<
petgraph::graph::NodeIndex<usize>,
Vec<&mut Family>,
std::hash::BuildHasherDefault<FxHasher>,
> = DashMap::default();
families_by_location.into_par_iter().map(...).collect();
However, this does not compile, and surprisingly, the error message is very unhelpful for me.
error[E0599]: the method `into_par_iter` exists for struct `dashmap::DashMap<NodeIndex<usize>, Vec<&mut Family>, BuildHasherDefault<rustc_hash::FxHasher>>`, but its trait bounds were not satisfied
--> src/lib.rs:442:10
|
442 | .into_par_iter()
| ^^^^^^^^^^^^^ method cannot be called on `dashmap::DashMap<NodeIndex<usize>, Vec<&mut Family>, BuildHasherDefault<rustc_hash::FxHasher>>` due to unsatisfied trait bounds
|
::: /home/gereon/.cargo/registry/src/github.com-1ecc6299db9ec823/dashmap-5.2.0/src/lib.rs:67:1
|
67 | pub struct DashMap<K, V, S = RandomState> {
| -----------------------------------------
| |
| doesn't satisfy `_: rayon::iter::IntoParallelIterator`
| doesn't satisfy `_: rayon::iter::ParallelIterator`
|
= note: the following trait bounds were not satisfied:
`dashmap::DashMap<NodeIndex<usize>, Vec<&mut Family>, BuildHasherDefault<rustc_hash::FxHasher>>: rayon::iter::ParallelIterator`
which is required by `dashmap::DashMap<NodeIndex<usize>, Vec<&mut Family>, BuildHasherDefault<rustc_hash::FxHasher>>: rayon::iter::IntoParallelIterator`
`&dashmap::DashMap<NodeIndex<usize>, Vec<&mut Family>, BuildHasherDefault<rustc_hash::FxHasher>>: rayon::iter::ParallelIterator`
which is required by `&dashmap::DashMap<NodeIndex<usize>, Vec<&mut Family>, BuildHasherDefault<rustc_hash::FxHasher>>: rayon::iter::IntoParallelIterator`
`&mut dashmap::DashMap<NodeIndex<usize>, Vec<&mut Family>, BuildHasherDefault<rustc_hash::FxHasher>>: rayon::iter::ParallelIterator`
which is required by `&mut dashmap::DashMap<NodeIndex<usize>, Vec<&mut Family>, BuildHasherDefault<rustc_hash::FxHasher>>: rayon::iter::IntoParallelIterator`
For more information about this error, try `rustc --explain E0599`.
error: could not compile `dispersal_model_rust` due to previous error
I also tried families_by_location.par_iter_mut()
for a similarly unhelpful error concerning trait bounds.
I don't understand the issue. The trait bounds on DashMap<K, V, S> being an IntoParallelIterator are K: Send + Eq + Hash, V: Send, S: Send + Clone + BuildHasher
.
K
is NodeIndex<usize>
, which implements Send + Sync + Eq + Hash
because usize
does.
The FxHasher
Builder supposedly also supports Send + Sync + Clone + BuildHasher
, and Vec
is Send + Sync
if its object type is. Now I would understand it if &mut Family
is not Send
, sending around mutable pointers between threads sounds dangerous. However, something like
let a: Vec<&mut Family> = families.par_iter_mut().collect();
let b: &dyn Sync = &a;
does no throw a compilation error, so it seems that Vec<&mut Family>
is actually Send + Sync
.
So it seems to me that the trait bounds for DashMap<K, V, S>: IntoParallelIterator
trait bounds are fulfilled, why do I get the Rust compiler error?
Upvotes: 0
Views: 1227
Reputation: 6400
An old comment on the DashMap issue tracker, which I found when searching for “parallel” on there, pointed out to me that activating the rayon feature is necessary. I did, and lo and behold my code compiles.
(I still find the error message which I get when not doing it quite confusing.)
While the list of feature flags on dashmap's docs.rs page states
rayon
This feature flag does not enable additional features.
that statement is a bit misleading: As Kevin Reid pointed out, “unlike most of rustdoc and docs.rs content, there is no automatic reporting of what a feature flag does, except for enabling other feature flags.” So all this statement only means is that activating dashmap's rayon feature does not activate other feature flags.
Upvotes: 0