protonscr

Steam sets wrong CPU affinity on system with hyperthreading enabled - resulting in a single CPU core being used

steamopen Distro Family: Ubuntu
ValveSoftware/steam-for-linux#12948 · opened 2026-03-01 by PierreBeucher · updated 2026-04-19 · 3 comments · github
1 matching comments, n / p to jump
PPierreBeucher 2026-03-01 github

Your system information

  • Steam Runtime Version:
    Steam Beta Branch:  Stable Client
    Steam Version:  1769025840
    Steam Client Build Date:  Wed, Jan 21 5:12 PM UTC -08:00
    Steam Web Build Date:  Wed, Jan 21 7:41 PM UTC -08:00
    Steam API Version:  SteamClient023
    
  • Distribution: Ubuntu 24.04
  • Link to your full system information: Gist link
  • Have you checked for system updates?: Yes
  • What compatibility tool are you using?: Proton 10.0-4 and Proton 9.0-4
  • What versions are listed in steamapps/common/SteamLinuxRuntime/VERSIONS.txt? None, folder doesn't exist
  • What versions are listed in steamapps/common/SteamLinuxRuntime_soldier/VERSIONS.txt? None, folder doesn't exist
  • What versions are listed in steamapps/common/SteamLinuxRuntime_sniper/VERSIONS.txt?
    $ cat VERSIONS.txt 
      #Name   Version         Runtime Runtime_Version Comment
      depot   3.0.20260119.200241                     # Overall version number
      pressure-vessel 0.20260115.0    scout           # pressure-vessel-bin.tar.gz
      scripts 0.20260115.0                    # from steam-runtime-tools
      sniper  3.0.20260119.200241     sniper  3.0.20260119.200241     # sniper_platform_3.0.20260119.200241/
    

Please describe your issue in as much detail as possible:

Hello, I have an issue with Steam Linux runtime CPU affinity on hyperthreaded VMs (for instance an AWS 4gdn instance with 2 Core and 4 logical CPUs, also reproduce on similar GCP instance)

On startup Steam set its own CPU affinity to {0,2}, but on the machine this corresponds to both logical cores of the same physical core. Sibling topology on machine is actually:

  • Core 1: {0,2}
  • Core 2: {1,3}

So Steam runs on a single Core (runs on both thread of the same CPU core). Steam then launch games on a single CPU with huge impact performance. Games are running with the same CPU affinity as Steam.

Notes:

  • This CPU affinity does not come from parent process which has [0-3], strace shows Steam set its own affinity (see detailed strace logs in Gist below)
  • It does not affect similar setup on machine without hyperthreading (eg. Scaleway and Linode instances with similar specs do not have this problem)

I suspect Steam tried to avoid having multiple threads on the same CPU, but should have used {0,1} to use both CPU Cores instead of {0,2}.

Can we have Steam (and runned games) use proper CPU affinity, or force CPU affinity globally somehow ? Any workaround will be appreciated in the meantime :)


Technical details and context:

  • Technical environment:
    • OS: Linux Ubuntu 24.04
    • Machine: AWS g4dn.xlarge with NVIDIA T4 GPU (4 vCPUs, 2 Core)
    • Steam runs under an Ubuntu 24.04 Docker container (along with X server, etc.)

For context: this machine is deployed with Cloudy Pad (I'm the creator/maintainer). It's a bit specific:

  • Run an AWS instance (or any other Cloud VM) with Ubuntu 24.04
  • Run Steam in a Docker Container based on Ubuntu 24.04

Steps to reproduce:

  • Install Cloudy Pad
  • Create an AWS instance with: cloudypad create aws
  • Connect, run Steam, install a game
  • Connect on instance via SSH and in container, check CPU affinity:
    ssh ubuntu@<instance_ip>
    $ docker exec -it cloudy bash
    $ ps -ef | grep steam     # find Steam PID
    $ taskset -pc <steam-pid> # see CPU affinity
    

I understand this is not a standard setup nor easy to reproduce. However please consider this completely breaks Steam on our system used by a fair mount of people.

I can provide direct access to an AWS instance to help dig further if someone from the team provide a public SSH key.

System CPU cibling data

System CPU sibling as appearing both on host and in container:

$ cat /sys/devices/system/cpu/cpu*/topology/thread_siblings_list
0,2
1,3
0,2
1,3
$ cat /sys/devices/system/cpu/cpu*/topology/thread_siblings
5
a
5
a

strace analysis showing sched_setaffinity calls

  • strace analysis Gist showing Steam and Wineserver setting the game CPU affinity via sched_setaffinity() syscalls
    • Steam PID(s): 5563 > 5566 > 5685
    • Wineserver: 6842
    • Game thread (Expedition 33): 6988
    • Wineserver sets game CPU affinity: 6842 15:24:57.172008 sched_setaffinity(6988, 128, [0 2]) = 0
    • Steam set ts own CPU affinity: 5685 15:22:51.187160 sched_setaffinity(5685, 128, [0 2]) = 0

Steam and Proton logs

Runned Steam with:

STEAM_LINUX_RUNTIME_LOG=1 STEAM_LINUX_RUNTIME_VERBOSE=1 PRESSURE_VESSEL_VERBOSE=1 PROTON_LOG=1 PROTON_LOG_DIR=/tmp steam

Gist link with

  • Steam log
  • Proton logs

Workaround attempts

Using WINE_CPU_TOPOLOGY

I tried running Steam with WINE_CPU_TOPOLOGY such as:

  • export WINE_CPU_TOPOLOGY=4:0,1,2,3: no effect, CPU affinity remained {0,2}
  • export WINE_CPU_TOPOLOGY=2:0,1: resulted in CPU affinity {0} - it seems this further restrict CPU affinity: as "by default" we have {0,2}, trying to force use of {0,1} result in only {0} being used...

Launch option to use all CPU on start

Forcing game game to start with more CPU with custom launch option such as:

# Use all available CPU
taskset -c 0-$(($(nproc --all)-1)) %command%

# Or more specifically
taskset -c 0-3 %command%

This do help: our game ends-up using all available CPU and performance are drastically better. Though it does not seem to solve base issue and must be done for each game... Maybe there's a way to set this globally ?


Thanks in advance for your help ! Let me know if I can provide further details.

Ssirus20x6 2026-03-22 github

I've had this issue for over a year. I had to make a script to intercept it and set the cores to all

PPierreBeucher 2026-03-22 github

Good to know thanks ! That's probably the workaround I'm gonna implement as well...

KKreevoz 2026-04-19 github

It's worse on systems with very high core counts.
Tested, and 100% reproducable on Arch Linux (latest), and NixOS (latest), both with kernel 6.19.X as of writing this.
Both systems were installed fresh for testing, with a fresh (native, non-flatpak) steam install with no old configs or baggage from prior installs.

Hardware is an AMD Threadripper 7975WX with 32 cores/64 threads.

Steam will pin itself, and all spawned child processes to cores 0,2,4,6 and there is no convincing it to stop doing that.

This gets extremely problematic when it spawns fossilize_replay to compile shaders.
It then spawns up to 64 processes and pins them all to those same 4 cores, resulting in quite dramatic system instability and freezing as the overhead simply cripples everything.

All parent processes above steam are unrestricted, and can use threads 0-63.
Steam is crippling itself:

$ strace -f -e sched_setaffinity steam 2>&1 | grep -i affinity 
[pid 8515] sched_setaffinity(8515, 128, [0 2 4 6]) = 0 
[pid 8514] sched_setaffinity(8514, 128, [0 2 4 6]) = 0 
[pid 8514] sched_setaffinity(8514, 128, [0 2 4 6]) = 0 
[pid 8589] sched_setaffinity(8589, 128, [0 2]) = 0 
[pid 8589] sched_setaffinity(8589, 128, [0 2]) = 0 
[pid 8627] sched_setaffinity(8627, 128, [0 2]) = 0 
[pid 8627] sched_setaffinity(8627, 128, [0 2]) = 0 
[pid 8514] sched_setaffinity(8514, 128, [0 2 4 6]) = 0 
[pid 8777] --- SIGSYS {si_signo=SIGSYS, si_code=SYS_SECCOMP, si_errno=ENXIO, si_call_addr=0x7f222f8a6e00, si_syscall=__NR_sched_getaffinity, si_arch=AUDIT_ARCH_X86_64} --- 
[pid 8778] --- SIGSYS {si_signo=SIGSYS, si_code=SYS_SECCOMP, si_errno=ENXIO, si_call_addr=0x7f222f8a6e00, si_syscall=__NR_sched_getaffinity, si_arch=AUDIT_ARCH_X86_64} --- 
[pid 8699] sched_setaffinity(8699, 128, [0 2]) = 0 
[pid 8699] sched_setaffinity(8699, 128, [0 2]) = 0 
[pid 8699] sched_setaffinity(8699, 128, [0 2]) = 0 
[pid 8514] sched_setaffinity(8514, 128, [0 2 4 6]) = 0 
[pid 8514] sched_setaffinity(8514, 128, [0 2 4 6]) = 0 
[pid 8570] sched_setaffinity(8570, 128, [0 2 4 6]) = 0 
[pid 8784] --- SIGSYS {si_signo=SIGSYS, si_code=SYS_SECCOMP, si_errno=ENXIO, si_call_addr=0x7f222f8a6e00, si_syscall=__NR_sched_getaffinity, si_arch=AUDIT_ARCH_X86_64} --- 
[pid 8699] sched_setaffinity(8699, 128, [0 2]) = 0 
[pid 8699] sched_setaffinity(8699, 128, [0 2]) = 0 
[pid 8699] sched_setaffinity(8699, 128, [0 2]) = 0 
[pid 8699] sched_setaffinity(8699, 128, [0 2]) = 0 
[pid 8699] sched_setaffinity(8699, 128, [0 2]) = 0 
[pid 8699] sched_setaffinity(8699, 128, [0 2]) = 0 
[pid 8699] sched_setaffinity(8699, 128, [0 2]) = 0 
[pid 8699] sched_setaffinity(8699, 128, [0 2]) = 0 
[pid 8699] sched_setaffinity(8699, 128, [0 2]) = 0 
[pid 8699] sched_setaffinity(8699, 128, [0 2]) = 0 
[pid 8699] sched_setaffinity(8699, 128, [0 2]) = 0 
[pid 8990] --- SIGSYS {si_signo=SIGSYS, si_code=SYS_SECCOMP, si_errno=ENXIO, si_call_addr=0x7f222f8a6e00, si_syscall=__NR_sched_getaffinity, si_arch=AUDIT_ARCH_X86_64} --- 
[pid 9001] --- SIGSYS {si_signo=SIGSYS, si_code=SYS_SECCOMP, si_errno=ENXIO, si_call_addr=0x7f222f8a6e00, si_syscall=__NR_sched_getaffinity, si_arch=AUDIT_ARCH_X86_64} ---

The same behavior as reported by Pierre.

That seems to be steam's own runtime / pressure-vessel sandbox applying a seccomp profile.
Even though the child processes (games, etc) try to bind to more threads, that silly profile blocks them from even being able to get that information.

A fix by valve would be very welcome.

Proton versions

Launch options