Deterministic query cycles for parallel front-end#149849
Deterministic query cycles for parallel front-end#149849zetanumbers wants to merge 20 commits intorust-lang:mainfrom
Conversation
|
These commits modify the If this was unintentional then you should revert the changes before this PR is merged. |
This comment has been minimized.
This comment has been minimized.
|
@bors try @rust-timer queue |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Deterministic query cycles for parallel front-end
|
Ok this is surprising |
This comment has been minimized.
This comment has been minimized.
|
Finished benchmarking commit (306a768): comparison URL. Overall result: ❌ regressions - please read the text belowBenchmarking this pull request means it may be perf-sensitive – we'll automatically label it not fit for rolling up. You can override this, but we strongly advise not to, due to possible changes in compiler perf. Next Steps: If you can justify the regressions found in this try perf run, please do so in sufficient writing along with @bors rollup=never Instruction countOur most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.
Max RSS (memory usage)Results (secondary -1.0%)A less reliable metric. May be of interest, but not used to determine the overall result above.
CyclesResults (primary 2.2%, secondary 2.0%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Binary sizeThis benchmark run did not return any relevant results for this metric. Bootstrap: 471.42s -> 474.532s (0.66%) |
|
It's a bit unclear to me what source of non-determinism this tries to fix. Does this alter parallel execution in any way other than picking which query in the cycle use for resumption? It looks to me like you're trying to pick the point in the cycle to break which corresponds to a single threaded execution, but I don't think that point is guaranteed to be resumable. Currently it looks like we're not deterministically picking which query in a cycle to resume when multiple is present. That's fairly simple to improve, though I think the queries available for resumption is non-deterministic to start with. |
I make an assumption that when we get a query cycle there is the "point in the cycle to break which corresponds to a single threaded execution" which currently
That's what I am trying to make deterministic. |
0a5000f to
ba45f0b
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
ba45f0b to
206fec5
Compare
|
Some changes occurred in compiler/rustc_codegen_cranelift cc @bjorn3 |
This comment has been minimized.
This comment has been minimized.
I believe it requires a rewrite in I plan to work on parallel testsuite one way or another. |
|
@zetanumbers: thanks for the additional commits, they have good improvements. I have marked most of my comments as resolved. There are still a small number that need action. @Zoxc: any thoughts? |
|
Just to clarify, my example shows that it's not possible to make cycle recovery deterministic with the way we're currently executing multiple queries on a single stack.
Resuming thread 1 in my example leads to the |
Yes, my query cycle breaking code does this. |
|
So I have isolated new |
15674b4 to
743c2d9
Compare
View all comments
The mechanism is similar to cycle detection in single-threaded mode. We traverse the deadlocked query graph from the top active query downwards to subqueries until we visit some query a second time, thus finding a cycle. With multi-thread front-end enabled one query may now have more than one active subqueries, aka we used one of parallel interfaces
parallel!,join,par_for_each, etc. As such we have to traverse the "leftmost" active subquery to recover the sequential behavior of these parallel interfaces in single-threaded mode. NewTreeNodeIndexsaves implicit context information about whatjoin(orscope) task we entered while executing a query, which we then use inbreak_query_cycle.However we then have to guarantee the query stack from single-threaded mode is included in the active query graph. This is true for
joinfunction as their first task will be completed on the same thread and same will be tried for the second task unless stolen which is fine for us.scopeplaces tasks in local queue and pops them in LIFO maner, while other worker threads could only steal from that queue in FIFO maner, thus we can guarantee the next task is either stolen or available for execution.Fixes #153391
Fixes #142064
Fixes #142063
Fixes #127971
UPDATE: commits are sliced to the finest detail