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
When I went to profile it, with a very large X and Y I found that most of my execution time was spent on malloc. The natural next step, then, was to try and preallocate the Vec to have the correct size, as this at least means no calls to realloc. I learned about collect_into_vec() and decided to try and use it:
This, however, fails due to there not being collect_into_vec() for ParallelIterator, and the call to flat_map() I think converts the IndexedParallelIterator into a plain ParallelIterator.
error[E0599]: no method named `collect_into_vec` found for struct `rayon::iter::map::Map<rayon::iter::flat_map::FlatMap<rayon::range::Iter<u64>, [closure@src/main.rs:32:19: 32:66]>, [closure@src/main.rs:33:14: 33:43]>` in the current scope
--> src/main.rs:34:10
|
34 | .collect_into_vec(&mut pairs);
| ^^^^^^^^^^^^^^^^ method not found in `rayon::iter::map::Map<rayon::iter::flat_map::FlatMap<rayon::range::Iter<u64>, [closure@src/main.rs:32:19: 32:66]>, [closure@src/main.rs:33:14: 33:43]>`
|
= note: the method `collect_into_vec` exists but the following trait bounds were not satisfied:
`rayon::iter::map::Map<rayon::iter::flat_map::FlatMap<rayon::range::Iter<u64>, [closure@src/main.rs:32:19: 32:66]>, [closure@src/main.rs:33:14: 33:43]> : rayon::iter::IndexedParallelIterator`
I'm kind of at a loss with how to correctly create an iterator over the cartesian product of two ranges and then collect it into a preallocated vector. The only solution I can see is to implement cartesian() for IndexedParallelIterator so that I can retain the indices instead of losing them in the flat_map(). This, of course, would have to be done inside rayon, but I am hoping there are other solutions.
What is the right way to get an IndexedParallelIterator that's the cartesian product of two IndexedParallelIterators?
The text was updated successfully, but these errors were encountered:
the call to flat_map() I think converts the IndexedParallelIterator into a plain ParallelIterator.
Yes, since flat_map only has to return some IntoParallelIterator type, it doesn't have to be indexed, so we don't have any idea how to offset each parallel flat_map invocation. Actually, even if we did have a variant that required the inner part to be IndexedParallelIterator, we still wouldn't know each of their lengths ahead of time -- there's nothing to say they even have to be the same!
The only solution I can see is to implement cartesian() for IndexedParallelIterator so that I can retain the indices instead of losing them in the flat_map(). This, of course, would have to be done inside rayon, but I am hoping there are other solutions.
I think that's possible, and it doesn't have to be part of rayon if you do it as your own extension trait. We made iter::plumbing public exactly to allow third party iterators. It won't be trivial to handle splits at possible odd boundaries, but not insurmountable.
If we do add something like this to rayon, it would be nice to model it after Itertools::cartesian_product for feature parity.
PS - I hope you have more than simple initialization to do in parallel -- I expect once we solve pre-allocation, your example would quickly run into a barrier of memory bandwidth when you try to scale up. It might not be much better than serial code.
cuviper
changed the title
Avoinding reallocations when doing a cartesian product
Avoiding reallocations when doing a cartesian product
Jun 4, 2024
I have some code that looks like this:
playground
When I went to profile it, with a very large
X
andY
I found that most of my execution time was spent on malloc. The natural next step, then, was to try and preallocate theVec
to have the correct size, as this at least means no calls to realloc. I learned aboutcollect_into_vec()
and decided to try and use it:playground
This, however, fails due to there not being
collect_into_vec()
forParallelIterator
, and the call toflat_map()
I think converts theIndexedParallelIterator
into a plainParallelIterator
.I'm kind of at a loss with how to correctly create an iterator over the cartesian product of two ranges and then collect it into a preallocated vector. The only solution I can see is to implement
cartesian()
forIndexedParallelIterator
so that I can retain the indices instead of losing them in theflat_map()
. This, of course, would have to be done inside rayon, but I am hoping there are other solutions.What is the right way to get an
IndexedParallelIterator
that's the cartesian product of twoIndexedParallelIterator
s?The text was updated successfully, but these errors were encountered: