-
-
Notifications
You must be signed in to change notification settings - Fork 719
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
Cache root-ish-ness for consistency #7262
base: main
Are you sure you want to change the base?
Conversation
it's possible for tasks to not be rootish when they go into no-worker, but to be rootish when they come out.
@@ -7052,6 +7083,8 @@ def get_metadata(self, keys: list[str], default=no_default): | |||
def set_restrictions(self, worker: dict[str, Collection[str] | str]): | |||
for key, restrictions in worker.items(): | |||
ts = self.tasks[key] | |||
if ts._rootish is not None: |
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 don't like that set_restrictions
is a public API at all. Doesn't seem like something you should be able to do post-hoc.
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 fails test_reschedule_concurrent_requests_deadlock
, which sets restrictions on a processing task.
distributed/distributed/tests/test_steal.py
Lines 1292 to 1355 in 711997e
@gen_cluster( | |
client=True, | |
nthreads=[("", 1)] * 3, | |
config={ | |
"distributed.scheduler.work-stealing-interval": 1_000_000, | |
}, | |
) | |
async def test_reschedule_concurrent_requests_deadlock(c, s, *workers): | |
# https://github.com/dask/distributed/issues/5370 | |
steal = s.extensions["stealing"] | |
w0 = workers[0] | |
ev = Event() | |
futs1 = c.map( | |
lambda _, ev: ev.wait(), | |
range(10), | |
ev=ev, | |
key=[f"f1-{ix}" for ix in range(10)], | |
workers=[w0.address], | |
allow_other_workers=True, | |
) | |
while not w0.active_keys: | |
await asyncio.sleep(0.01) | |
# ready is a heap but we don't need last, just not the next | |
victim_key = list(w0.active_keys)[0] | |
victim_ts = s.tasks[victim_key] | |
wsA = victim_ts.processing_on | |
other_workers = [ws for ws in s.workers.values() if ws != wsA] | |
wsB = other_workers[0] | |
wsC = other_workers[1] | |
steal.move_task_request(victim_ts, wsA, wsB) | |
s.set_restrictions(worker={victim_key: [wsB.address]}) | |
s._reschedule(victim_key, stimulus_id="test") | |
assert wsB == victim_ts.processing_on | |
# move_task_request is not responsible for respecting worker restrictions | |
steal.move_task_request(victim_ts, wsB, wsC) | |
# Let tasks finish | |
await ev.set() | |
await c.gather(futs1) | |
assert victim_ts.who_has != {wsC} | |
msgs = steal.story(victim_ts) | |
msgs = [msg[:-1] for msg in msgs] # Remove random IDs | |
# There are three possible outcomes | |
expect1 = [ | |
("stale-response", victim_key, "executing", wsA.address), | |
("already-computing", victim_key, "executing", wsB.address, wsC.address), | |
] | |
expect2 = [ | |
("already-computing", victim_key, "executing", wsB.address, wsC.address), | |
("already-aborted", victim_key, "executing", wsA.address), | |
] | |
# This outcome appears only in ~2% of the runs | |
expect3 = [ | |
("already-computing", victim_key, "executing", wsB.address, wsC.address), | |
("already-aborted", victim_key, "memory", wsA.address), | |
] | |
assert msgs in (expect1, expect2, expect3) |
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 don't like that set_restrictions is a public API at all. Doesn't seem like something you should be able to do post-hoc.
We can change it. First step is a deprecation warning
Unit Test ResultsSee test report for an extended history of previous test failures. This is useful for diagnosing flaky tests. 15 files ± 0 15 suites ±0 6h 43m 28s ⏱️ + 13m 3s For more details on these failures, see this check. Results for commit 6f188bf. ± Comparison against base commit 4b00be1. ♻️ This comment has been updated with latest results. |
I don't like caching this. I don't consider it user friendly to pin the behavior of our decision logic pending on the time a computation is dispatched. I think this will be a hard to debug problem if users run into weird scheduling just because their cluster was still scaling up. |
I'm curious, what are some situations where rootish-ness can change? |
Broadly, it changes when either the size of the TaskGroup changes (add/cancel tasks) or the cluster size changes. Some specific examples:
|
We're going to take a different approach; see #7259 (comment). Rather than trying to make |
I think we're only worried about not queuing tasks when we should. That is,
So it won't happen when the cluster is scaling up. Just when submitting tasks before scaling down. And in that case:
So that case is fine. Only remaining case is the TaskGroup growing. That happens most commonly through
...and that's the same behavior as if we weren't caching. Having the group split like this isn't ideal, but there's nothing we can do about it, and caching doesn't change things. |
Also to clarify: the definition of caching in this approach is that We don't need to cache root-ish-ness for the lifetime of a task; that's overkill. I only care that
|
This is a way of avoiding the consistency issues in #7259 with less thinking. If root-ish-ness can't change, things are simpler.
I don't love having to do this. But hopefully this will be determined statically (and likely cached) anyway: #6922.
pre-commit run --all-files