-
Notifications
You must be signed in to change notification settings - Fork 502
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
[Discussion] Is it possible to impl IntoIterator
for ParallelIterator
?
#1179
Comments
So to be clear, you are not asking for a parallel iterator with serialized output, like #210 or #858. You just want to avoid parallel overhead for smaller inputs? IMO, the difference between
It would certainly be a breaking change. For You can tune that however you like. Maybe you'll set a known serial/parallel threshold like indexed_par_iter
.with_min_len(if len < 16 {
usize::MAX // no parallelism
} else {
1 // full parallelism
})
.for_each(f); ... or some gradient therein, as you find makes sense for your workload. To some extent, you can write your zip variations based on |
This would be true for most of the workloads. But GUI library with a virtual-dom layer is another area. The most notorious case is perhaps Google's Flutter. In realistic Flutter apps, you will frequently see widget tree up to hundreds of levels deep. If at each node (there would be numerous of nodes throughout the tree), it spins up the whole But to be fair, I currently don't have the test case to test this theory. So it may not be that impactful in the end
This is not entirely what I want. The reason to get a serialized iterator (besides switching to fully serialized behavior) is switching to The reason to use
Brilliant! I'll certainly employ this idea to my other projects. |
I think that Thanks for the reminder about those completion issues though. We should find a way to make that opt-in For a deep widget tree, I wonder if it's really worth parallelizing the deep/smaller parts at all? It might be fine to let inner parts run sequentially while the outer parts are divided in parallel. This will mostly happen naturally anyway with both |
This is a realistic need surfaced during development of EPGI, a parallel GUI library using rayon. I'll explain the motivation step-by-step
Motivation
Variable parallelism in GUI framework
EPGI uses rayon in various pipeline stages, and the most common way to use rayon is to visit a node's children in parallel. However, child count across the node tree is hugely variable. It is known that different rayon parallelism primitive (or simply non-rayon serial code) have vastly different performance characteristics regarding child count.
For dynamic children widgets, it calls for a runtime selection mechanism for parallelism. A
Column
widget painting a layout may have two children but get nested 100 times deep, while anotherColumn
widget painting a data science visualziation may have no nesting but have 10k children instead. Both of these cases are computationally heavy and need respective optimization.Limitation of runtime selection mechanism API designs
Given a
Vec
, a straightforward runtime selection mechanism is impl-ed as:We can duplicate this for
for_each/map/unzip
and forVec/&Vec/&mut Vec
. No problem for now.However, problem surfaces as we went into zip and
MultiZip
. We will provide an example belowSuppose we have a widget that could have a huge number of children. During its implementation we need to use rayon's MultiZip to zip three
&Vec
s. Now we want to introduce a runtime selection versionSeems fine. But this only handles
(&Vec, &Vec, &Vec)
case. What about(Vec, &mut Vec, &Vec)
? We get an combinatorial explosion! And it is just for a zip-3!As a legit real-world exmaple, here are two pieces of code in EPGI that is waiting to be parallelized. They both use different versions of zip-3.
https://github.com/ZhennanWu/epgi/blob/850ed7556bb8d619b430f337a0c90da05de72de8/epgi-common/src/basic/stack.rs#L216-L219
https://github.com/ZhennanWu/epgi/blob/850ed7556bb8d619b430f337a0c90da05de72de8/epgi-common/src/basic/stack.rs#L238-L241
Switching between
Iterator
andParallelIterator
One way to circumvent this issue is to somehow merge the capabilities of serial iterators and parallel iterators. Requiring
IntoIterator
as the supertrait ofIntoParallelIterator
seems implausible, since rayon'sIntoParallelIterator
is implemented for much more primitive types than std'sIntoIterator
, and we can't force feed the std. However, I think it is quite possible to makeParallelIterator: IntoIterator
.Then we can (psuedocode)
I wonder if this change is possible or is there any other practical concerns with regard to parallel iterators designs
(Note: of course the above examples can be worked around by introducing intermediate
Vec
s. But that would lose the purpose of tuning the performance in the first place. This is an experimental project so I want to see how far it can go w.r.t. zero-cost abstraction).The text was updated successfully, but these errors were encountered: