Skip to main content

sc_neurocore_engine/bindings/
runtime_control.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Commercial license available
3// © Concepts 1996–2026 Miroslav Šotek. All rights reserved.
4// © Code 2020–2026 Miroslav Šotek. All rights reserved.
5// ORCID: 0009-0009-3560-0851
6// Contact: www.anulum.li | protoscience@anulum.li
7// SC-NeuroCore — Engine runtime-control PyO3 bindings
8
9//! Python bindings for runtime SIMD discovery and Rayon thread-pool control.
10
11use pyo3::exceptions::PyValueError;
12use pyo3::prelude::*;
13
14/// Register engine runtime-control functions with the extension module.
15pub(crate) fn register(module: &Bound<'_, PyModule>) -> PyResult<()> {
16    module.add_function(wrap_pyfunction!(simd_tier, module)?)?;
17    module.add_function(wrap_pyfunction!(set_num_threads, module)?)?;
18    Ok(())
19}
20
21/// Returns the highest SIMD tier available on this CPU.
22#[pyfunction]
23fn simd_tier() -> &'static str {
24    #[cfg(target_arch = "x86_64")]
25    {
26        if is_x86_feature_detected!("avx512vpopcntdq") {
27            return "avx512-vpopcntdq";
28        }
29        if is_x86_feature_detected!("avx512bw") {
30            return "avx512bw";
31        }
32        if is_x86_feature_detected!("avx512f") {
33            return "avx512f";
34        }
35        if is_x86_feature_detected!("avx2") {
36            return "avx2";
37        }
38        if is_x86_feature_detected!("popcnt") {
39            return "popcnt";
40        }
41    }
42    #[cfg(target_arch = "aarch64")]
43    {
44        return "neon";
45    }
46    "portable"
47}
48
49/// Set the number of threads in the global rayon thread pool.
50///
51/// Must be called before any parallel operation.
52/// Passing 0 uses rayon's default (number of CPU cores).
53#[pyfunction]
54fn set_num_threads(n: usize) -> PyResult<()> {
55    if n == 0 {
56        return Ok(());
57    }
58    rayon::ThreadPoolBuilder::new()
59        .num_threads(n)
60        .build_global()
61        .map_err(|e| PyValueError::new_err(format!("Cannot set thread pool: {e}")))
62}