CPU cores
Python processes
task scheduling
multi-threading
system monitoring

On what CPU cores are my Python processes running?

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

There are two different questions hidden inside this topic. One is "Which CPU core is the process running on right now?" The other is "Which CPU cores is the process allowed to run on?" Those are not the same thing. The operating system scheduler may move a Python process between cores unless affinity pins it down.

Check the Current Core on Linux

On Linux, the psr column shows the processor that last ran the process or thread.

bash
ps -o pid,psr,comm -p 12345

Example output:

text
  PID PSR COMMAND
12345   6 python

That tells you the process was recently scheduled on core 6. It does not guarantee the process will stay there.

For thread-level visibility:

bash
top -H -p 12345

This is useful when one Python program has multiple native threads and you want to see scheduler behavior in more detail.

Check Allowed CPU Affinity

If you care about which cores the process may use, inspect CPU affinity instead.

On Linux:

bash
taskset -cp 12345

Example output:

text
pid 12345's current affinity list: 0-3

That means the scheduler may place the process on any of cores 0 through 3. Affinity describes the allowed set, not the currently active core.

Inspect from Python with psutil

Inside Python, psutil is the easiest cross-process inspection tool.

python
1import os
2import psutil
3
4process = psutil.Process(os.getpid())
5
6print("pid:", process.pid)
7print("allowed cores:", process.cpu_affinity())
8print("current core:", process.cpu_num())

This is practical because it lets your application log or inspect scheduling information during runtime without external shell commands.

cpu_num() tells you which CPU the process is currently running on or most recently ran on, depending on platform support. cpu_affinity() tells you the allowed set.

Affinity Can Be Changed Too

If you need to restrict a process to specific cores, that is usually called setting affinity.

python
1import os
2import psutil
3
4process = psutil.Process(os.getpid())
5process.cpu_affinity([0, 1])
6
7print(process.cpu_affinity())

This can be useful for benchmarking, isolating workloads, or reducing interference. But it is a policy decision, not just a monitoring trick.

Python Threads Add a Twist

A Python process may have many threads, but CPU-bound Python code is still affected by the global interpreter lock in normal CPython. That means:

  • multiple Python threads do not automatically mean simultaneous multi-core CPU execution for pure Python bytecode
  • native extensions may still release the GIL and run across cores
  • multiprocessing creates separate processes, which the scheduler can place on different cores independently

So when checking "what cores my Python processes are running on," first clarify whether you mean:

  • one process
  • several processes
  • several threads inside one process

The monitoring tools differ slightly for each case.

Use the Right Tool for the Platform

On Linux, ps, top, and taskset are the usual answers. On Windows, tools such as Process Explorer or Task Manager plus affinity settings are more common. On macOS, scheduler details are less directly exposed in the same style.

That is why Python-level tools like psutil are useful: they give you one programmatic interface for many common questions even when the shell tooling differs.

Common Pitfalls

  • Confusing the current core with the allowed affinity mask.
  • Assuming a process stays on one core just because it was seen there once.
  • Expecting Python threads to show meaningful multi-core CPU scaling for pure Python code automatically.
  • Looking only at process-level data when the real question is thread-level scheduling.
  • Pinning affinity for benchmarking without documenting it, then comparing results unfairly later.

Summary

  • The current core and the allowed cores are different concepts.
  • On Linux, ps -o psr shows the recent CPU and taskset -cp shows affinity.
  • In Python, psutil exposes both cpu_num() and cpu_affinity().
  • Scheduler behavior can move a process across cores unless affinity restricts it.
  • For Python workloads, also distinguish between processes, threads, and GIL-limited execution.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.