-
Notifications
You must be signed in to change notification settings - Fork 176
Implement Rayon traits (optional) #45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
src/rayon.rs
Outdated
vec | ||
}) | ||
.collect() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Loll wut!! LinkedList is used in a real-life PR?!! 🥇 🐫 🎈
(Ahem I'll be back to my regular @bluss in a bit.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You know, it's funny, for all the strategies we benchmarked for Rayon collect, I don't think we actually tried a Vec<Vec<T>>
intermediate. I just assumed that a list was best for this purpose because of its O(1) append. I'm going to have to do some testing now...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've kept the LinkedList
, but now collect it with map-reduce -- see rayon-rs/rayon#479.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, I'll review this sooner or later. Not Either-PR late. Just not tonight. Thanks for the solid PR.
src/rayon.rs
Outdated
|
||
// NB: This allows indexed collection, e.g. directly into a `Vec`, but the | ||
// underlying iterator must really be indexed. We should remove this if we | ||
// start having tombstones that must be filtered out. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great comment.
479: ParallelExtend with map-reduce r=cuviper a=cuviper We were using a `LinkedList<Vec<_>>` intermediary for general `ParallelExtend` implementations, gathered using a `fold` to a vector and `collect` the list -- effectively a `fold`-`fold`-`reduce`. Now we explicitly `fold`-`map`-`reduce` it for better performance. Thanks to @bluss for [ridiculing](indexmap-rs/indexmap#45 (comment)) the use of `LinkedList`, which got me to look at this again. At first I tried `Vec<Vec<_>>` instead, which did perform better, but I had to do this using `fold`-`map`-`reduce` to avoid infinite `collect` recursion. Then I tried that same tweak on the original code, finding it slightly better yet. So I stand by the use of `LinkedList`. 😄 ``` test map_collect::i_mod_10_to_i::with_linked_list_collect_vec_sized ... bench: 5,112,790 ns/iter (+/- 78,988) test map_collect::i_mod_10_to_i::with_linked_list_map_reduce_vec_sized ... bench: 4,954,336 ns/iter (+/- 103,285) test map_collect::i_mod_10_to_i::with_vec_vec_sized ... bench: 4,965,241 ns/iter (+/- 80,797) test map_collect::i_to_i::with_linked_list_collect_vec_sized ... bench: 9,837,088 ns/iter (+/- 283,665) test map_collect::i_to_i::with_linked_list_map_reduce_vec_sized ... bench: 9,687,170 ns/iter (+/- 328,236) test map_collect::i_to_i::with_vec_vec_sized ... bench: 9,690,253 ns/iter (+/- 242,379) test vec_collect::vec_i::with_linked_list_collect_vec_sized ... bench: 12,639,762 ns/iter (+/- 260,212) test vec_collect::vec_i::with_linked_list_map_reduce_vec_sized ... bench: 9,805,660 ns/iter (+/- 170,434) test vec_collect::vec_i::with_vec_vec_sized ... bench: 9,904,740 ns/iter (+/- 226,382) test vec_collect::vec_i_filtered::with_linked_list_collect_vec_sized ... bench: 12,486,357 ns/iter (+/- 239,281) test vec_collect::vec_i_filtered::with_linked_list_map_reduce_vec_sized ... bench: 9,794,605 ns/iter (+/- 306,361) test vec_collect::vec_i_filtered::with_vec_vec_sized ... bench: 9,986,733 ns/iter (+/- 1,142,244) ```
As awesome as this is, it does interfere with easy 1.0'ing of ordermap. |
Would you want to wait for rayon-1.0? Or would you hesitate even then? Another idea is to add omap.as_slice().into_par_iter()
.map(|b| (b.key(), b.value())))
.for_each(|(k, v)| ...); That's not as ergonomic, but at least it would be possible to use Rayon with ordermap efficiently, and maybe enable other cool uses too! |
With rayon-1.0 I would not hesitate, but you're right, one could be worried about the version entanglement even then. For the record, we've decided that OrderMap will stay as it is with its current properties, indexing, exact size = no tombstones (and probably the same name too, if we don't find a better one). This data structure is useful as it is, so to implement a similar one with tombstones, it will be a new thing. We could end up with both. |
W.r.t order I'm very fond of a deterministic order (hash function independent). I had a different thought -- would it be possible to implement shared and mutable views for OrderMap. So that it would natively support splitting (by index) into two parts or even slicing. Both the shared and mutable view would mean shared/mutable access to the elements only, not inserting or removing elements. I think that means that the mutable views can all have the same shared immutable reference to the index/hash vector. The idea includes allowing lookup by key and indexing in a view. In a mutable view, the implementation peeking into another view's part of the entries vector would be verboten. |
I think views are a neat idea! It wouldn't directly enable rayon, but it could let there be something like |
Just a thought: IMO feature flags should be able to be independent of the crate stability. I.e. you can advertise that " |
Yes, maybe. I think the feature flag must have unstable in its name for it to work. It's different viewpoints among users in the role of docs vs formal API in defining the stable interface. |
I've now rebased, updated to rayon 1.0, and added the basic set implementations. |
That's cool! I'm fine with merging this, but I haven't looked through it in fine detail. rayon 1.0 is quite the thing, and maybe we can dare to go 1.0 with it as dependency. (Congratulations!) |
I was also thinking of The only thing left would be Anyway, I should at least write some documentation and tests here before we merge. 😅 One specific API question for you is whether it's good to have these |
This PR is clearly amazing. I think this is a great feature set for a hashmap library and in safe Rust no less (thanks to the giants of std::vec::Vec and rayon). I think that's a lot of functions. I'd probably drop the comparisons and I don't know about the module and name prefix question. Mirroring std fits well in the rayon crate. Here I don't mind either way. |
What's the status of this pull request? I'm a fan of IndexMap, but right now I'm in a situation where I'd really like to be able to use rayon to get a performance boost, and unfortunately can't. |
@ConnorGray -- It's kind of in that "Does anyone care?" limbo, so your direct request will help motivate me to revisit this. 🙂 I need to rebase it, at least, and then make some decision about those API questions. If you have any input, feel free to share your thoughts (but no worries if you're indifferent to the specifics). |
@cuviper Wow the quick response is much appreciated :) I don't have a much input -- I'm just hoping to take advantage of rayon's accessible parallelism (where not having to worry about the details is a selling point) with the determinism I get from using an IndexMap everywhere internally. I imagine there might be others in the same boat, who like IndexMap for it's determinism, but would also like to operate on the values in parallel. |
I think this is good. Rayon is rock solid 😉 and doesn't feel like a risk. The code is simple. Only review comment that is important to fix, is that the new methods (par_keys etc) need to be listed last in the docs, not first in the docs. I'd enable the rayon feature in docs.rs generation and make sure items are labelled in docs to require that feature (I can do that). |
What's the state of this? I would like to use this feature |
I think this is ready for reconsideration. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great, ready to merge! When the trivial conflict in .travis.yml is fixed
OK, that conflict was just in the compat downgrades, which #97 removed. Rebased without that, and CI passed -- r=bluss |
Great. I can do the release of 1.1.0 |
IntoParallelIterator
by value, ref, and ref mutParallelIterator
andIndexedParallelIterator
FromParallelIterator
ParallelExtend
by value and ref copy