Unlocking Python's Cores: Hardware Usage and Energy Implications of Removing the GIL
Abstract: Python's Global Interpreter Lock prevents execution on more than one CPU core at the same time, even when multiple threads are used. However, starting with Python 3.13 an experimental build allows disabling the GIL. While prior work has examined speedup implications of this disabling, the effects on energy consumption and hardware utilization have received less attention. This study measures execution time, CPU utilization, memory usage, and energy consumption using four workload categories: NumPy-based, sequential kernels, threaded numerical workloads, and threaded object workloads, comparing GIL and free-threaded builds of Python 3.14.2. The results highlight a trade-off. For parallelizable workloads operating on independent data, the free-threaded build reduces execution time by up to 4 times, with a proportional reduction in energy consumption, and effective multi-core utilization, at the cost of an increase in memory usage. In contrast, sequential workloads do not benefit from removing the GIL and instead show a 13-43% increase in energy consumption. Similarly, workloads where threads frequently access and modify the same objects show reduced improvements or even degradation due to lock contention. Across all workloads, energy consumption is proportional to execution time, indicating that disabling the GIL does not significantly affect power consumption, even when CPU utilization increases. When it comes to memory, the no-GIL build shows a general increase, more visible in virtual memory than in physical memory. This increase is primarily attributed to per-object locking, additional thread-safety mechanisms in the runtime, and the adoption of a new memory allocator. These findings suggest that Python's no-GIL build is not a universal improvement. Developers should evaluate whether their workload can effectively benefit from parallel execution before adoption.
Paper Prompts
Sign up for free to create and run prompts on this paper.
Top Community Prompts
Explain it Like I'm 14
What this paper is about
This paper explores what happens when you remove a rule in Python called the GIL (Global Interpreter Lock). The GIL normally lets only one Python thread run at a time, even on a computer with many CPU cores. New experimental versions of Python (starting in 3.13, studied here with 3.14.2) can turn the GIL off so multiple Python threads can truly run in parallel. The paper asks: does turning off the GIL make Python faster, use the hardware better, and save energy—or not?
What the researchers wanted to find out
In simple terms, they asked three questions:
- Does turning off the GIL reduce the total energy used by Python programs?
- When programs run faster with no GIL, does the energy used drop by the same amount?
- How do CPU and memory usage change with and without the GIL?
How they studied it (in everyday terms)
Think of a computer like a kitchen with many cooks (CPU cores). The GIL is like a single special utensil that all cooks must share—only one can use it at a time—so the others wait. Removing the GIL gives each cook tools to work at the same time, but you add safety rules (extra locks and checks) so they don’t bump into each other when touching the same ingredients.
What they did:
- They ran many kinds of Python programs on the same computer (a 6‑core Intel laptop CPU) using two Python builds:
- Normal Python (with GIL).
- Free-threaded Python (no GIL).
- They measured:
- How long programs took (execution time).
- How busy the CPU cores were (CPU utilization).
- Memory in two ways:
- RAM (real memory actually used).
- Virtual memory (space reserved, like seats saved in a theater even if empty).
- Energy used by the whole system, read from the CPU’s built-in energy meter.
- They used four types of workloads:
- NumPy calculations (most work done by fast C code under the hood).
- Single-threaded pure-Python loops (sequential kernels).
- Multi-threaded number-crunching (threads work on separate numbers).
- Multi-threaded object-heavy tasks (threads create/modify Python objects, sometimes sharing them).
- They ran each test many times to make results trustworthy and compared the two Python builds by looking at ratios (no-GIL result divided by GIL result). They averaged these carefully to be fair.
A key energy idea they used: . If a program runs for less time, it often uses less total energy—even if it uses more cores at once—so long as the shorter time “wins” over the higher momentary power.
What they found and why it matters
Big picture: removing the GIL is great for some programs, useless for others, and harmful for a few.
- NumPy-heavy work (most math done in C libraries)
- Result: No real difference in speed or energy between GIL and no-GIL.
- Why: NumPy already releases the GIL internally and uses optimized native code, so Python’s lock doesn’t matter much here.
- Memory: No-GIL reserves more virtual memory (about ~1 GB extra), but actual RAM used is about the same.
- Single-threaded pure-Python code (no threads)
- Result: No-GIL is slower by about 13–43%. Energy used also goes up by about the same amount.
- Why: Turning off the GIL adds safety checks and extra work inside Python (thread-safety features) that don’t help if you aren’t using multiple threads.
- Memory: Both virtual memory and real RAM use increase under no-GIL.
- Multi-threaded number-crunching on separate data (low sharing)
- Result: No-GIL can be up to around 4× faster on this 6‑core machine when using enough threads. Energy drops by a similar factor because the program finishes much sooner.
- CPU use: With no-GIL, multiple cores become busy at the same time (as intended). With GIL, adding threads didn’t help—still effectively runs on one core.
- Memory: No-GIL reserves more virtual memory; RAM increases a little but stayed reasonable.
- Multi-threaded object-heavy work
- If threads mostly work on their own data (little sharing), no-GIL speeds things up a lot (similar to the number-crunching case), and energy drops similarly.
- If threads frequently touch and change the same Python objects, performance can get worse than with the GIL (sometimes much worse), because threads fight over locks on those shared objects (called lock contention). Energy goes up because it runs longer.
Across all tests:
- Energy closely followed time. When programs ran faster, they used less energy by about the same proportion. When they ran slower, they used more energy.
- Using more cores at once did not automatically waste more energy—the key factor was how much it shortened the total run time.
- No-GIL generally increased virtual memory a lot (due to a new memory allocator and extra thread-safety structures). RAM went up a bit for many pure-Python cases.
What this means going forward
- No-GIL is not a magic speed button. It helps when:
- You can split work across threads,
- Threads mostly work on different pieces of data,
- And you have multiple CPU cores to use.
- In these cases, you can finish much faster and use much less energy.
- No-GIL can hurt when:
- Your code runs in a single thread (no benefit, only overhead),
- Or your threads constantly modify the same Python objects (lots of lock fighting).
- For many data science and AI tasks using NumPy or other native libraries, you might not see a difference, because those libraries already handle parallelism efficiently.
- Memory-wise, expect higher virtual memory reservations with no-GIL and some increase in RAM for pure-Python work.
In short: choose no-GIL if your program can truly run work in parallel without lots of shared-object conflicts. Otherwise, stick with the regular GIL build. Making that choice wisely can save both time and energy—especially important as computing’s electricity use keeps growing.
Knowledge Gaps
Knowledge gaps, limitations, and open questions
Below is a concise, actionable list of what remains missing, uncertain, or unexplored in the study.
- Generalizability across hardware: Results are from a single Intel i7-8750H (6C/12T) laptop-class CPU on Linux; behavior on AMD (desktop/server), ARM64 (e.g., AWS Graviton, Apple M-series), and high-core-count servers remains untested.
- Operating systems: Only Ubuntu Linux is evaluated; potential differences on Windows and macOS (e.g., allocator behavior, thread scheduling, power management) are not assessed.
- Frequency/thermal controls: CPU frequency governors, Turbo Boost, and DVFS settings are not reported or fixed; the extent to which thermal throttling or governor changes influence time/energy results is unknown.
- Power vs. energy claims: The study infers that power is unaffected because energy scaled with time, but does not report instantaneous or average power; dedicated power measurements are needed to verify power draw changes under no-GIL.
- Energy measurement scope: RAPL package energy is system-wide and not per-process; background daemons and OS noise may contaminate readings. Isolation (e.g., CPU shielding, minimal services) or external power meters is needed for attribution.
- DRAM and uncore energy: The measured energy does not isolate CPU vs DRAM vs uncore domains (and DRAM may be unavailable on the tested CPU); the contribution of memory activity to total energy is not quantified.
- CPU affinity and isolation: No mention of core pinning, isolcpus, or cgroups; scheduler-induced thread migration could bias CPU utilization and energy.
- Temperature instrumentation: The study discusses temperature implications but does not record core/package temperatures; the role of thermal dynamics in performance/energy outcomes remains unverified.
- Hyperthreading effects: Scaling is evaluated up to 12 hardware threads without disabling SMT; the incremental benefit and energy impact of SMT vs physical cores is not disentangled.
- Scaling beyond 6 cores: Findings are limited by a 6-core CPU; it is unknown how no-GIL scales (performance and energy) on 16–128 core servers, where synchronization and contention may dominate.
- Workload representativeness: Benchmarks are micro/meso workloads; impacts on end-to-end, real-world applications (web services, ETL pipelines, scientific pipelines, build systems) are not evaluated.
- I/O-bound workloads: Asynchronous and I/O-heavy workloads (networking, disk, asyncio) are excluded; the net energy/performance impact of no-GIL on I/O-dominated programs is unknown.
- C-extension ecosystem: Only NumPy is covered; the behavior of other widely used extensions (Pandas, SciPy, TensorFlow/PyTorch, PIL, lxml) under free-threading (especially if not fully thread-safe) is not examined.
- Multiprocessing vs free-threading: The study does not compare no-GIL threads to multiprocessing (a common GIL workaround) for time/energy/memory trade-offs and inter-process communication overheads.
- Subinterpreters and alternative concurrency models: Interactions with subinterpreters, joblib, Dask, Ray, or concurrent queues (and their contention behavior) are unexplored.
- Contention diagnostics: Object-heavy benchmarks show degradation with shared mutation, but the study does not quantify contention (lock acquisition rates, wait times) or identify hotspots with profiling tools (e.g., perf, LTTng).
- Overhead sources: The relative costs of atomic refcounting, per-object locks, GC coordination, and allocator behavior are not decomposed; microbenchmarks or instrumentation to isolate each source would clarify where overhead accrues.
- Memory allocator sensitivity: Memory overhead is attributed to mimalloc (e.g., eager arena reservation) but the study does not vary allocator settings (e.g., disable eager commit) or compare against jemalloc/glibc to verify causality.
- Memory pressure and swapping: All tests avoid swap; how the no-GIL build behaves under memory pressure (e.g., cgroups limits, containerized deployments) and whether increased VMS/RSS induce paging is unknown.
- Memory activity metrics: Only peak VMS/RSS are reported; cache misses, page faults, bandwidth, and locality are not measured, limiting insight into why memory overhead sometimes translates to RSS increases.
- Short-duration task sensitivity: The 50 ms sampling interval can quantize short regions delimited by set_tag; accuracy for brief tasks or phase changes is not established against high-resolution timers.
- CPU utilization measurement accuracy: psutil with interval=0.0 and normalization by core count can be noisy/non-intuitive; validation against lower-level counters (proc/stat deltas, perf events) is missing.
- Run ordering and drift: The study pairs runs but does not describe randomization of run order; slow drift (thermal, background processes) may bias paired comparisons.
- Version variability: Experiments use Python 3.14.2; how results evolve across 3.13–3.14+ (or future no-GIL refinements) is not explored.
- Guidance thresholds: While the study suggests “independent data + low sharing” benefits, it does not provide quantitative thresholds (e.g., mutation rate per object, lock contention ratios) to predict when no-GIL helps or hurts.
- Data structures and operations: Only a few object patterns (lists, JSON) are tested; performance/energy impact for other common structures and patterns (dict/set heavy updates, counters, queues, heaps, graph traversals) is not evaluated.
- GC behavior: Potential changes in cyclic GC overhead under no-GIL are not measured (e.g., pause times, major/minor collections, allocation rates).
- Correctness and determinism: The study focuses on performance/energy but does not assess whether removing the GIL introduces data races, non-determinism, or subtle correctness issues in common patterns.
- Native-library parallelism: Interactions between no-GIL Python threads and native libraries’ own thread pools (OpenMP/BLAS/FFT) are not evaluated for oversubscription and energy waste.
- Mixed workloads: Scenarios combining Python-level parallelism with C-accelerated regions (and shared data structures crossing the boundary) are not examined.
- Power-supply/battery context: The energy implications on laptops (battery vs mains) or data-center nodes (PSU efficiency curves) are not considered; energy conclusions may vary with platform-level efficiencies.
- Container/cloud context: Effects under virtualization, container limits, noisy neighbors, and cloud power management are not studied, yet are critical for data-center relevance.
- Toolchain overhead: The profiler’s own overhead is verified with sleep, but not across CPU-bound workloads; further validation with external timing/power instruments would increase confidence.
- Practical mitigations: The study notes VMS/RSS increases but does not test mitigations (allocator env vars, object pooling, reduced sharing) or provide recipes to contain memory costs under no-GIL.
- Scheduling/tuning: The impact of chunk sizes, work-stealing, thread pool sizing (physical vs logical cores), and NUMA affinity on time/energy under no-GIL is left unexplored.
- Security/stability of experimental build: As no-GIL is experimental, stability, crash rates, or memory safety regressions under stress are not evaluated.
- Reproducibility of datasets: Full results are shared via a Google Drive link; long-term accessibility, scripts for end-to-end reproduction, and environment pinning are not detailed.
These gaps suggest concrete next steps: broaden hardware/OS coverage; measure power and temperature directly; isolate overhead sources with low-level profiling; vary allocator and GC settings; add real-world and I/O-bound workloads; compare with multiprocessing; and develop predictive, quantitative guidance for when free-threading reduces time and energy.
Practical Applications
Immediate Applications
The items below translate the paper’s findings into actionable use cases that can be deployed now, with sector links, suggested tools/workflows, and key assumptions/dependencies.
- Parallelize CPU-bound, pure-Python tasks that operate on independent data
- Sectors: software, data engineering, finance (Monte Carlo), energy (meter data processing), healthcare (EHR preprocessing), cybersecurity (log parsing)
- What to do: adopt the free-threaded (no-GIL) CPython 3.14 build and refactor workloads into chunked, independent units using ThreadPoolExecutor; cap workers to physical cores; use per-thread “slice-copy” and thread-local accumulators to minimize shared mutation.
- Tools/workflows: ThreadPoolExecutor; patterns like “copy-on-write per-thread slices” for lists; thread-local dicts/queues; simple autotuner that sets workers to the number of physical cores; use the provided sampling profiler + Intel RAPL for before/after energy checks.
- Expected impact: up to ~4× faster with ~4× lower energy for well-partitioned workloads; higher CPU utilization but energy tracks time (so total energy drops).
- Assumptions/dependencies: Python 3.14 free-threaded build available; sufficient RAM headroom (VMS increases, RSS modestly higher); C extensions used must be thread-safe; Intel RAPL (or alternative energy APIs) for measurement.
- Accelerate high-throughput API backends doing CPU-bound JSON and text transformations
- Sectors: software/web, fintech, adtech, observability
- What to do: shift per-request CPU-heavy parsing/transforms (e.g., json.loads, string normalization) to thread pools in a no-GIL process; avoid shared mutable state between threads; keep per-request accumulators local.
- Tools/workflows: WSGI/ASGI worker model with thread pools per process; per-thread buffers; “no shared in-place mutation” coding patterns.
- Expected impact: significant latency and throughput gains on CPU-bound endpoints, with proportional energy reductions for those code paths.
- Assumptions/dependencies: endpoints must be truly CPU-bound in Python; ensure libraries used are compatible with free-threading; consider process-per-core plus threads for isolation.
- Simulation and scenario sweeps with independent trials
- Sectors: finance (VaR/Monte Carlo), engineering/science (parameter sweeps), energy (grid scenarios)
- What to do: map trials to threads; avoid shared state; gather results in thread-local structures and reduce at the end.
- Tools/workflows: concurrent.futures thread pools; simple chunk scheduling; Energy/time A/B in CI.
- Expected impact: ~3–4× speed and energy gains until physical core count; diminishing returns beyond that.
- Assumptions/dependencies: independence of trials; careful random seeding per thread for reproducibility.
- Keep using the GIL-enabled build for sequential or NumPy-dominated pipelines
- Sectors: AI/ML (NumPy/BLAS/FFTs), analytics
- What to do: pin the standard CPython for scripts dominated by NumPy/BLAS/FFT or inherently sequential logic; avoid the free-threaded build in these cases to prevent 13–43% energy/time penalties.
- Tools/workflows: pyenv/virtualenv matrix providing both builds; CI that selects build per job type; rules of thumb (if >80% in native libs, prefer GIL).
- Expected impact: avoids measurable slowdowns/energy increases on sequential and NumPy-heavy tasks.
- Assumptions/dependencies: basic profiling to confirm native-extension dominance.
- Energy-aware benchmarking baked into CI/CD and performance gates
- Sectors: software/platform teams, DevEx
- What to do: integrate the paper’s sampling profiler and RAPL-based energy tracking into CI; run representative jobs under both builds; fail builds if “fixes” raise energy/time beyond thresholds.
- Tools/workflows: “EnergyCI” job that records time, CPU%, energy, VMS/RSS; geometric mean ratio reporting; GitHub Action/GitLab job templates.
- Expected impact: systematic prevention of regressions; continuous validation of no-GIL benefits.
- Assumptions/dependencies: Intel RAPL (Linux). On macOS/ARM, use powermetrics/PMU alternatives; stable, repeatable inputs.
- Memory planning for containers and VMs running no-GIL Python
- Sectors: cloud ops, platform engineering
- What to do: budget for larger VMS (often ~+1 GB) and modest RSS increases; stress-test under production-like thread counts; tune mimalloc if needed.
- Tools/workflows: cgroup-aware monitoring; mimalloc environment knobs (e.g., MIMALLOC_ARENA_EAGER_COMMIT) where acceptable; memory dashboards by build.
- Expected impact: avoids surprise OOM/commit issues; predictable infra costs.
- Assumptions/dependencies: container kernel/memory accounting behavior; tradeoffs when reducing eager commit.
- Teaching labs and seminars on energy-time proportionality and parallelism trade-offs
- Sectors: education, research computing
- What to do: replicate the study’s methodology; have students implement “shared mutation” vs “slice-copy” patterns to observe contention penalties; measure energy proportional to time.
- Tools/workflows: sampler + RAPL; controlled worker-count experiments.
- Expected impact: improves practical understanding of energy-aware programming.
- Assumptions/dependencies: lab machines with accessible energy counters; calibrated datasets.
- Internal sustainability guidance grounded in measurement
- Sectors: policy within organizations (Green IT, ESG teams)
- What to do: codify a guideline: “Parallelize or stick with GIL”; mandate energy/time measurement for CPU-bound services; report execution time as a reliable energy proxy when power is stable.
- Tools/workflows: internal standards, playbooks, review checklists.
- Expected impact: targeted energy savings without blanket language bans.
- Assumptions/dependencies: cross-team adoption; access to metrics; acceptance that energy ≈ time for controlled setups.
Long-Term Applications
These opportunities require further research, scaling, ecosystem evolution, or runtime improvements before widespread deployment.
- Thread-safety certification and ecosystem readiness for free-threaded CPython
- Sectors: software, open-source ecosystem
- What: certify C-extensions and popular libraries for no-GIL thread safety; publish compatibility matrices.
- Potential tools/products: “No-GIL Ready” badges; automated concurrency test harnesses.
- Dependencies: maintainer effort; upstream CPython API stability; funding/support.
- Static analyzers and linters that flag contention-prone patterns
- Sectors: developer tools
- What: detect shared mutable state across threads, in-place mutations of shared containers, fine-grained locking hotspots; suggest slice-copy/thread-local rewrites.
- Potential products: IDE plugins; CI lint steps with “contention risk score.”
- Dependencies: sound heuristics; minimal false positives; education materials.
- Autotuning runtimes/schedulers that minimize energy for a workload
- Sectors: cloud/data platforms
- What: automatically pick thread vs process parallelism, worker counts, and chunk sizes to minimize energy and latency given node topology and live telemetry.
- Potential tools: orchestration plugins for Dask/Ray/Airflow; Kubernetes operators that co-schedule CPU-bound no-GIL jobs.
- Dependencies: cross-platform energy telemetry; model calibration per hardware.
- Framework modes optimized for no-GIL (Dask/Ray/Joblib/Airflow)
- Sectors: data engineering, ML platforms
- What: “no-GIL threads-first” executors for independent Python tasks with energy-aware scheduling.
- Potential benefits: higher throughput per node, reduced energy-per-task.
- Dependencies: workload classification; backpressure and fairness controls.
- Data center consolidation strategies leveraging no-GIL processes
- Sectors: cloud providers, large enterprises
- What: reduce process counts, increase per-process thread-level parallelism, improve CPU cache locality; quantify server-level energy effects at scale.
- Potential workflows: capacity planning that considers per-process multi-core gains vs memory overheads.
- Dependencies: rigorous A/B at fleet scale; observability of energy/time/cost; maturity of no-GIL stability.
- OS/firmware-level integration for energy caps with parallel Python
- Sectors: energy/IT operations
- What: coordinate DVFS and per-core power limits with thread-level parallelism to sit at an energy-optimal point (not just time-optimal).
- Potential tools: power-aware schedulers interfacing with Python executors.
- Dependencies: hardware support; cross-layer APIs; policy controls.
- Developer-facing energy profilers embedded in IDEs and cloud consoles
- Sectors: education, software engineering
- What: unify RAPL/powermetrics into a common API; show “energy per function” and “contention hotspots”; compare GIL vs no-GIL within the same tool.
- Potential products: VS Code/JetBrains extensions; cloud APM modules.
- Dependencies: standardized energy telemetry APIs; low overhead sampling.
- Standards for energy reporting and compliance that leverage execution time as a proxy
- Sectors: policy, finance (ESG)
- What: formalize when and how execution time can stand in for energy; prescribe measurement controls (frequency caps, core counts).
- Potential outputs: guidance akin to “Energy ≈ Time under controlled power,” with validation protocols.
- Dependencies: consensus bodies; cross-vendor hardware validation.
- Robotics/embedded Python on SBCs with safe parallel sensing/processing
- Sectors: robotics, IoT
- What: move CPU-bound pre/post-processing of sensor streams into threads with no-GIL; preserve real-time constraints via careful isolation and bounded contention.
- Potential tools: robotics frameworks offering “no-shared-state threading” primitives.
- Dependencies: platform support (ARM, RT Linux), deterministic timing analysis, library readiness.
- Runtime and allocator advancements to reduce free-threaded overheads
- Sectors: language/runtime research
- What: lower per-object locking costs, reduce one-thread overhead, tune mimalloc arena strategies for containers.
- Potential benefits: shrink the current 13–43% penalty on sequential code and reduce VMS/RSS inflation.
- Dependencies: sustained CPython/mimalloc development; broad benchmarking across architectures.
Cross-cutting assumptions and dependencies (affect feasibility)
- Hardware and OS: results measured on Intel x86_64 Linux with RAPL; behavior may vary on ARM/macOS/AMD and with different kernels and power governors.
- Python versioning: free-threaded CPython is experimental (3.14); stability and API changes may occur; library compatibility varies.
- Workload fit: benefits require CPU-bound Python bytecode with minimal shared mutable state; NumPy/BLAS/GPU-bound pipelines gain little from no-GIL.
- Memory headroom: expect increased VMS and some RSS growth due to mimalloc and thread-safety mechanisms; test under realistic thread counts and container limits.
- Measurement discipline: energy closely tracks time when power is controlled; validate with on-box telemetry and stable configurations before generalizing.
Glossary
- cache locality: The tendency of a program to access the same memory locations repeatedly so data stays in fast CPU caches, reducing latency and energy. "a well-optimized program can have a large memory in use but excellent cache locality, keeping memory activity and execution time low."
- CPython: The reference implementation of the Python language, written in C, which defines Python’s runtime behavior. "In the standard CPython build, the GIL blocks multiple OS threads from executing Python bytecode at the same time within a single process, preventing multi-threaded programs to use the cores available in the CPU."
- cyclic garbage collection: A garbage collection technique that detects and reclaims groups of objects that reference each other, forming cycles. "it also requires additional coordination for cyclic garbage collection \cite{GIL_REMOVAL}."
- dataclass: A Python feature that generates boilerplate code for classes (e.g., init, repr) based on annotated fields. "object_lists: dataclass-based object/list transformations with 8{,000{,}000} records."
- dynamic voltage or frequency scaling: Hardware mechanisms that adjust a processor’s voltage and/or frequency to manage power and thermals, affecting performance and energy. "mechanisms such as dynamic voltage or frequency scaling may be triggered, negatively affecting execution time and potentially increasing total energy consumption."
- eager arena reservation and commit: An allocator strategy that reserves and commits large chunks (“arenas”) of virtual memory up front to improve multi-threaded allocation performance. "On Linux, the free-threaded build enables eager arena reservation and commit."
- FFT: The Fast Fourier Transform; an efficient algorithm to compute the discrete Fourier transform. "numpy_fft: FFT followed by magnitude reduction on signals."
- free-threaded build: A CPython build variant that disables the GIL so multiple Python threads can execute bytecode in parallel. "An important change in the free-threaded build is the use of mimalloc as the default memory allocator \cite{MIMALLOC_DOCS}, designed to scaling to many concurrent threads."
- geometric mean: A multiplicative average used to aggregate ratios, computed as the nth root of the product of n values. "Because ratios represent multiplicative effects, they are aggregated using log transformation and the geometric mean."
- Global Interpreter Lock (GIL): A global mutex in CPython that permits only one thread to execute Python bytecode at a time, limiting parallelism. "Python's Global Interpreter Lock (GIL) prevents Python bytecode from executing on more than one CPU core at the same time, even when multiple threads are used."
- hyperthreading: Intel’s simultaneous multithreading that lets each physical core present multiple hardware threads to the OS. "(6 physical cores, 12 hardware threads via hyperthreading, up to 4.1\,GHz)"
- Intel RAPL: Running Average Power Limit; a set of hardware counters for estimating energy usage on Intel CPUs. "Energy consumption: Measured using Intel RAPL via the Linux sysfs interface (\path{/sys/class/powercap/intel-rapl:*/energy_uj}), therefore it is a system-wide stat."
- leakage currents: Unavoidable static power dissipation in transistors even when idle, contributing to energy use. "idle cores are not energy-free, as leakage currents and power dissipation persist even at zero computational load \cite{PARALLEL}."
- Linux sysfs: A virtual filesystem that exposes kernel and device information to user space as files. "via the Linux sysfs interface (\path{/sys/class/powercap/intel-rapl:*/energy_uj})"
- lock contention: Performance degradation when multiple threads compete for the same lock, causing waiting and reduced parallel efficiency. "workloads where threads frequently access and modify the same objects show reduced improvements or even degradation due to lock contention."
- log transformation: Applying a logarithm to data, often to stabilize variance and convert multiplicative relationships into additive ones. "Because ratios represent multiplicative effects, they are aggregated using log transformation and the geometric mean."
- mimalloc: A high-performance, thread-scalable general-purpose memory allocator designed for low latency and small allocations. "An important change in the free-threaded build is the use of mimalloc as the default memory allocator \cite{MIMALLOC_DOCS}, designed to scaling to many concurrent threads."
- N-body simulation: A numerical method for simulating the motion of multiple interacting bodies (e.g., gravitational systems). "nbody: N-body simulation, num_particles=2000 and num_steps=10."
- per-object locks: Fine-grained synchronization where individual objects (e.g., containers) have their own locks to enable concurrent access with reduced interference. "such as per-object locks for shared containers, so that unrelated operations can proceed on different CPU cores while concurrent modifications to the same object remain safe \cite{GIL_REMOVAL}."
- psutil: A Python library for retrieving information on running processes and system utilization. "the library psutil (version 7.1.3 \cite{PSUTIL_7_1_3}) is used to collect statistics associated exclusively with that process."
- reference counting: A memory management scheme where objects track how many references point to them and are deallocated when the count drops to zero. "PEP~703 describes changes to reference counting and memory management so that object lifetime and allocation remain correct when multiple threads run simultaneously;"
- Resident Set Size (RSS): The amount of physical RAM currently used by a process. "Resident Set Size (RSS): Peak amount of physical memory (RAM) currently used by the process."
- Sieve of Eratosthenes: A classic algorithm for finding all prime numbers up to a given limit. "prime_sieve: Sieve of Eratosthenes up to varying limits."
- Student’s t distribution: A probability distribution used in statistical inference (e.g., confidence intervals) when sample sizes are small and variance is estimated. "A two-sided 95\% confidence interval for the mean log-ratio is constructed using Studentâs distribution with degrees of freedom:"
- thread-local: Data structures or storage that are private to a single thread, avoiding synchronization with others. "accumulate results in thread-local structures."
- ThreadPoolExecutor: A high-level Python concurrency API that manages a pool of worker threads for parallel execution. "These scenarios use ThreadPoolExecutor and vary the number of workers."
- Virtual Memory Size (VMS): The total amount of virtual address space reserved by a process, including memory not resident in RAM. "Virtual Memory Size (VMS): Peak amount of virtual memory reserved by the process."
