feat: add numa feature flag and automate release workflow
Refactor the Gitea release pipeline to generate releases via API and upload binaries using a shared ID. Automate changelog generation by fetching recent commits with `jj log` and producing markdown notes via `aichat`. Convert `hwlocality` to an optional dependency gated by a default `numa` feature, providing fallback implementations for graceful degradation when NUMA support is disabled. Bump obikmer to 1.1.18.
This commit is contained in:
@@ -17,4 +17,8 @@ serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
indicatif = "0.17"
|
||||
tracing = "0.1.44"
|
||||
hwlocality = { version = "1.0.0-alpha.11", features = ["vendored"] }
|
||||
hwlocality = { version = "1.0.0-alpha.11", features = ["vendored"], optional = true }
|
||||
|
||||
[features]
|
||||
default = ["numa"]
|
||||
numa = ["hwlocality"]
|
||||
|
||||
@@ -12,9 +12,13 @@ use std::sync::Arc;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use crossbeam_channel::unbounded;
|
||||
#[cfg(feature = "numa")]
|
||||
use hwlocality::Topology;
|
||||
#[cfg(feature = "numa")]
|
||||
use hwlocality::cpu::binding::CpuBindingFlags;
|
||||
#[cfg(feature = "numa")]
|
||||
use hwlocality::cpu::cpuset::CpuSet;
|
||||
#[cfg(feature = "numa")]
|
||||
use hwlocality::object::types::ObjectType;
|
||||
use obisys::CpuSample;
|
||||
use tracing::debug;
|
||||
@@ -40,6 +44,7 @@ impl NumaSetup {
|
||||
|
||||
/// Detect NUMA topology and build per-node Rayon pools.
|
||||
/// Always succeeds: falls back to a single synthetic UMA node on failure.
|
||||
#[cfg(feature = "numa")]
|
||||
pub fn build() -> NumaSetup {
|
||||
if let Ok(topology) = Topology::new() {
|
||||
let nodes: Vec<Vec<usize>> = topology
|
||||
@@ -81,8 +86,21 @@ pub fn build() -> NumaSetup {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "numa"))]
|
||||
pub fn build() -> NumaSetup {
|
||||
let n_cores = std::thread::available_parallelism()
|
||||
.map(|n| n.get())
|
||||
.unwrap_or(1);
|
||||
debug!("UMA: single synthetic node, {} core(s)", n_cores);
|
||||
NumaSetup {
|
||||
pools: vec![None],
|
||||
cpus_per_node: vec![(0..n_cores).collect()],
|
||||
}
|
||||
}
|
||||
|
||||
/// Bind the calling thread to `cpu_indices` using hwloc.
|
||||
/// Silently returns on any error so the thread still runs, just unbound.
|
||||
#[cfg(feature = "numa")]
|
||||
pub fn pin_current_thread(cpu_indices: &[usize]) {
|
||||
let Ok(topology) = Topology::new() else { return };
|
||||
let mut cpuset = CpuSet::new();
|
||||
@@ -92,8 +110,12 @@ pub fn pin_current_thread(cpu_indices: &[usize]) {
|
||||
let _ = topology.bind_cpu(&cpuset, CpuBindingFlags::THREAD);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "numa"))]
|
||||
pub fn pin_current_thread(_cpu_indices: &[usize]) {}
|
||||
|
||||
// ── Internal helpers ──────────────────────────────────────────────────────────
|
||||
|
||||
#[cfg(feature = "numa")]
|
||||
fn build_pool(cpus: &[usize]) -> Option<rayon::ThreadPool> {
|
||||
let cpus = cpus.to_vec();
|
||||
rayon::ThreadPoolBuilder::new()
|
||||
|
||||
Reference in New Issue
Block a user