rt(alt): track which workers are idle. (#5886)

The scheduler uses this map to avoid trying to steal from idle workers.
This commit is contained in:
Carl Lerche 2023-07-21 14:00:33 -07:00 committed by GitHub
parent 4165601b1b
commit a58beb3aca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 18 additions and 27 deletions

View File

@ -16,7 +16,7 @@ pub(super) struct Idle {
num_idle: AtomicUsize, num_idle: AtomicUsize,
/// Map of idle cores /// Map of idle cores
// idle_map: IdleMap, idle_map: IdleMap,
/// Used to catch false-negatives when waking workers /// Used to catch false-negatives when waking workers
needs_searching: AtomicBool, needs_searching: AtomicBool,
@ -30,7 +30,7 @@ pub(super) struct IdleMap {
} }
pub(super) struct Snapshot { pub(super) struct Snapshot {
// chunks: Vec<usize>, chunks: Vec<usize>,
} }
/// Data synchronized by the scheduler mutex /// Data synchronized by the scheduler mutex
@ -47,7 +47,7 @@ impl Idle {
let idle = Idle { let idle = Idle {
num_searching: AtomicUsize::new(0), num_searching: AtomicUsize::new(0),
num_idle: AtomicUsize::new(cores.len()), num_idle: AtomicUsize::new(cores.len()),
// idle_map: IdleMap::new(&cores), idle_map: IdleMap::new(&cores),
needs_searching: AtomicBool::new(false), needs_searching: AtomicBool::new(false),
num_cores: cores.len(), num_cores: cores.len(),
}; };
@ -69,22 +69,22 @@ impl Idle {
self.num_searching.load(Acquire) self.num_searching.load(Acquire)
} }
pub(super) fn snapshot(&self, _snapshot: &mut Snapshot) { pub(super) fn snapshot(&self, snapshot: &mut Snapshot) {
// snapshot.update(&self.idle_map) snapshot.update(&self.idle_map)
} }
/// Try to acquire an available core /// Try to acquire an available core
pub(super) fn try_acquire_available_core(&self, synced: &mut Synced) -> Option<Box<Core>> { pub(super) fn try_acquire_available_core(&self, synced: &mut Synced) -> Option<Box<Core>> {
let ret = synced.available_cores.pop(); let ret = synced.available_cores.pop();
if let Some(_core) = &ret { if let Some(core) = &ret {
// Decrement the number of idle cores // Decrement the number of idle cores
let num_idle = self.num_idle.load(Acquire) - 1; let num_idle = self.num_idle.load(Acquire) - 1;
debug_assert_eq!(num_idle, synced.available_cores.len()); debug_assert_eq!(num_idle, synced.available_cores.len());
self.num_idle.store(num_idle, Release); self.num_idle.store(num_idle, Release);
// self.idle_map.unset(core.index); self.idle_map.unset(core.index);
// debug_assert!(self.idle_map.matches(&synced.available_cores)); debug_assert!(self.idle_map.matches(&synced.available_cores));
} }
ret ret
@ -151,8 +151,8 @@ impl Idle {
debug_assert!(!core.is_searching); debug_assert!(!core.is_searching);
core.is_searching = true; core.is_searching = true;
// self.idle_map.unset(core.index); self.idle_map.unset(core.index);
// debug_assert!(self.idle_map.matches(&synced.idle.available_cores)); debug_assert!(self.idle_map.matches(&synced.idle.available_cores));
// Assign the core to the worker // Assign the core to the worker
synced.assigned_cores[worker] = Some(core); synced.assigned_cores[worker] = Some(core);
@ -201,7 +201,7 @@ impl Idle {
if let Some(core) = synced.idle.available_cores.pop() { if let Some(core) = synced.idle.available_cores.pop() {
debug_assert!(!core.is_searching); debug_assert!(!core.is_searching);
// self.idle_map.unset(core.index); self.idle_map.unset(core.index);
synced.assigned_cores[worker] = Some(core); synced.assigned_cores[worker] = Some(core);
@ -217,7 +217,7 @@ impl Idle {
} }
if !workers.is_empty() { if !workers.is_empty() {
// debug_assert!(self.idle_map.matches(&synced.idle.available_cores)); debug_assert!(self.idle_map.matches(&synced.idle.available_cores));
let num_idle = synced.idle.available_cores.len(); let num_idle = synced.idle.available_cores.len();
self.num_idle.store(num_idle, Release); self.num_idle.store(num_idle, Release);
} else { } else {
@ -237,7 +237,7 @@ impl Idle {
let worker = synced.idle.sleepers.pop().unwrap(); let worker = synced.idle.sleepers.pop().unwrap();
let core = synced.idle.available_cores.pop().unwrap(); let core = synced.idle.available_cores.pop().unwrap();
// self.idle_map.unset(core.index); self.idle_map.unset(core.index);
synced.assigned_cores[worker] = Some(core); synced.assigned_cores[worker] = Some(core);
shared.condvars[worker].notify_one(); shared.condvars[worker].notify_one();
@ -246,7 +246,7 @@ impl Idle {
.store(synced.idle.available_cores.len(), Release); .store(synced.idle.available_cores.len(), Release);
} }
// debug_assert!(self.idle_map.matches(&synced.idle.available_cores)); debug_assert!(self.idle_map.matches(&synced.idle.available_cores));
// Wake up any other workers // Wake up any other workers
while let Some(index) = synced.idle.sleepers.pop() { while let Some(index) = synced.idle.sleepers.pop() {
@ -267,12 +267,12 @@ impl Idle {
let num_idle = synced.idle.available_cores.len(); let num_idle = synced.idle.available_cores.len();
debug_assert_eq!(num_idle, self.num_idle.load(Acquire)); debug_assert_eq!(num_idle, self.num_idle.load(Acquire));
// self.idle_map.set(core.index); self.idle_map.set(core.index);
// Store the core in the list of available cores // Store the core in the list of available cores
synced.idle.available_cores.push(core); synced.idle.available_cores.push(core);
// debug_assert!(self.idle_map.matches(&synced.idle.available_cores)); debug_assert!(self.idle_map.matches(&synced.idle.available_cores));
// Update `num_idle` // Update `num_idle`
self.num_idle.store(num_idle + 1, Release); self.num_idle.store(num_idle + 1, Release);
@ -386,25 +386,19 @@ impl IdleMap {
} }
impl Snapshot { impl Snapshot {
pub(crate) fn new(_idle: &Idle) -> Snapshot { pub(crate) fn new(idle: &Idle) -> Snapshot {
/*
let chunks = vec![0; idle.idle_map.chunks.len()]; let chunks = vec![0; idle.idle_map.chunks.len()];
let mut ret = Snapshot { chunks }; let mut ret = Snapshot { chunks };
ret.update(&idle.idle_map); ret.update(&idle.idle_map);
ret ret
*/
Snapshot {}
} }
fn update(&mut self, _idle_map: &IdleMap) { fn update(&mut self, idle_map: &IdleMap) {
/*
for i in 0..self.chunks.len() { for i in 0..self.chunks.len() {
self.chunks[i] = idle_map.chunks[i].load(Acquire); self.chunks[i] = idle_map.chunks[i].load(Acquire);
} }
*/
} }
/*
pub(super) fn is_idle(&self, index: usize) -> bool { pub(super) fn is_idle(&self, index: usize) -> bool {
let (chunk, mask) = index_to_mask(index); let (chunk, mask) = index_to_mask(index);
debug_assert!( debug_assert!(
@ -415,7 +409,6 @@ impl Snapshot {
); );
self.chunks[chunk] & mask == mask self.chunks[chunk] & mask == mask
} }
*/
} }
fn num_chunks(max_cores: usize) -> usize { fn num_chunks(max_cores: usize) -> usize {

View File

@ -865,12 +865,10 @@ impl Worker {
continue; continue;
} }
/*
// If the core is currently idle, then there is nothing to steal. // If the core is currently idle, then there is nothing to steal.
if self.idle_snapshot.is_idle(i) { if self.idle_snapshot.is_idle(i) {
continue; continue;
} }
*/
let target = &cx.shared().remotes[i]; let target = &cx.shared().remotes[i];