Skip to content

Commit 92a974f

Browse files
committed
Auto merge of #153768 - zetanumbers:consistent-par-slice, r=<try>
Make `par_slice` consistent with single-threaded execution
2 parents d1ee5e5 + 7c25475 commit 92a974f

1 file changed

Lines changed: 26 additions & 2 deletions

File tree

compiler/rustc_data_structures/src/sync/parallel.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,30 @@ fn par_slice<I: DynSend>(
128128
guard: &ParallelGuard,
129129
for_each: impl Fn(&mut I) + DynSync + DynSend,
130130
) {
131+
match items {
132+
[] => return,
133+
[item] => {
134+
guard.run(|| for_each(item));
135+
return;
136+
}
137+
_ => (),
138+
}
139+
131140
let for_each = FromDyn::from(for_each);
132141
let mut items = for_each.derive(items);
133142
rustc_thread_pool::scope(|s| {
134143
let proof = items.derive(());
135-
let group_size = std::cmp::max(items.len() / 128, 1);
136-
for group in items.chunks_mut(group_size) {
144+
145+
const MAX_GROUP_COUNT: usize = 128;
146+
let group_size = items.len().div_ceil(MAX_GROUP_COUNT);
147+
let mut groups = items.chunks_mut(group_size);
148+
149+
let Some(first_group) = groups.next() else { return };
150+
151+
// Reverse the order of the later functions since Rayon executes them in reverse
152+
// order when using a single thread. This ensures the execution order matches
153+
// that of a single threaded rustc.
154+
for group in groups.rev() {
137155
let group = proof.derive(group);
138156
s.spawn(|_| {
139157
let mut group = group;
@@ -142,6 +160,12 @@ fn par_slice<I: DynSend>(
142160
}
143161
});
144162
}
163+
164+
// Run the first function without spawning to
165+
// ensure it executes immediately on this thread.
166+
for i in first_group.iter_mut() {
167+
guard.run(|| for_each(i));
168+
}
145169
});
146170
}
147171

0 commit comments

Comments
 (0)