-
Notifications
You must be signed in to change notification settings - Fork 506
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
introduce custom schedulers for parallel iterators #353
Conversation
OK, I see I was not running all the tests and some broke. Bah. Well, I've got to run now, but I'll get them working. |
The scheduler gets threaded down through the calls to `drive()` and `with_producer()`. It replaces the existing "bridge" functions. This version includes two schedulers -- the adaptive scheduler and the fixed-length scheduler. (Note that the existing `min_len()` and `max_len()` combinators are ignored by this commit; they will be replaced by uses of `in_scheduler()` in the next commit.)
This is a breaking change because `iter.with_min(N).with_max(X)` must now be rewritten into `iter.with_min_max(N, X)`. This is because we do not permit more than one `in_scheduler()` call on any particular parallel iterator chain. Also, simplify `Producer` trait by removing `min_len` and `max_len`.
We're not really ready to commit to this interface yet -- not even remotely. Anyhow, if people can override the scheduler, they can already do (in principle) everything they need to do to customize the runtime, though it may involve some copy-and-paste.
9a28faa
to
7958976
Compare
Rebased and fixed the broken tests. (Well, let's see what travis has to say.) |
Yet another custom scheduler (branch and diff). The design is not finalized and we wish to get feedback early. We tried another design which diverges in following ways:
Some consequences of the design:
Some minor designs that could change:
Some obstacle we are facing:
Features we wish to implement in the future:
|
A lot of performance depends on sufficient inlining -- it could just be that your additional code changed some thresholds in the module that caused LLVM to make different inlining decisions. Apart from raw performance, you could also try to evaluate your changes at a higher level, like @wagnerf42 has been doing with his rayon-adaptive. He has logging infrastructure that can show exactly how the jobs were divided, so differences can be compared and justified. |
Perhaps a breaking change can be avoided by adding a new trait for scheduling purposes. Anyway, I'd suggest opening your own issue or pull request to discuss your design further. |
I'm going to close this PR as being obviously stalled and outdated. |
This PR introduces the notion of "custom schedulers". The idea is that you can invoke, for any parallel iterator
iter
,iter.in_scheduler(S)
, and it will run with the schedulerS
. The scheduler basically takes the place of the (currently hard-coded) "bridge" functions -- it connects a parallel producer and a parallel consumer.We introduce a
Scheduler
associated type into theParallelIterator
trait. This is used to ensure that the user cannot invokein_scheduler()
twice on any given parallel iterator. For implicity, we also forbid customized schedulers from the "inputs" where mutiple parallel iterators are "joined" (likezip()
orchain()
). Hencea.in_scheduler().zip(b)
is illegal, buta.zip(b).in_scheduler()
is fine. We could alter these rules to permit both (but we want to avoida.in_scheduler().zip(b.in_scheduler())
).In this PR, Rayon exposes three schedulers:
DefaultScheduler
-- what you get if you don't say anything; also encodes the fact thatin_scheduler
has never been called. Currently, this delegates toAdaptiveScheduler
.AdaptiveScheduler
-- the default strategy of "split to depth N, and more if stolen"FixedLenScheduler
-- like above, but where we adjust N to try and respect the user's min/max requestsOriginally, the idea here was to allow you to swap out the Rayon runtime completely. In fact, you can still see this in the
Runtime
trait introduced by the first commit, though I've removed it by the end -- basically because I don't feel we're ready to commit to this trait yet (and in principle no flexibility is lost). I imagine we'll probably add this back at some point in some form.Some unknowns:
iter::scheduler
.Scheduler
associated type inParallelIterator
?DefaultScheduler
orCustomScheduler
. This is just used to prevent multiplein_scheduler()
calls. I think I'd rather just give a semantics to multiple calls in some useful way. This interacts with the next question.in_scheduler
, but I was thinking that it'd also be possible to permit "combining" schedulers (e.g.,with_min
andwith_max
). I have to play around with this a bit more.chain()
and other ad-hoc calls tojoin()
?drive()
impl ofchain()
so that it will drive in parallel, usingjoin()
. This kind of goes against the grain of this PR, so we probably want to either extend the scheduler interface with ajoin
method or reframe that as a parallel producer consumer, or something like that.cc #93 -- this permits a user-provided "backend", though I think ultimately more flexibility might be desired. (This only works for parallel iterators, for one thing.)