-
Notifications
You must be signed in to change notification settings - Fork 186
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding CPU core pinning and parking capability #416
Conversation
Added common files for the cpu core parking/pinning functionality
added build info for common-cpu to meson
added the cpu core parking/pinning settings to gamemode-config.c
added cpu core parking/pinning settings to gamemode-config.h
call the cpu core parking/pinning from gamemode-context.c
Added gamemode-cpu.c which contains the functions for cpu core parking and pinning
added the cpu core parking/pinning definitions to gamemode.h
Added build info for gamemade-cpu.c to meson
added the polkit policy for the cpucorectl utility so we can call it without being root
added polkit rules so we can run the cpucorectl utility without being root
added some info about the new cpu core parking and pinning settings in gamemode.ini
Added a utility to enable and disable cpu cores (aka core parking) since this requires root privileges
added build info for the new cpucorectl utility to meson
Added detection for big.LITTLE aka cpu:s where not all cores have the same frequency like on Intel Alder Lake and newer. The current logic allows a 5% difference in the max frequency due to some reports that those cpu:s doesn't always give back the exact same value (possible due to boosting capability).
use defines instead of values for the park_or_pin variable
use a define instead of values for the park_or_pin variable
if cpu core parking/pinning was disabled by the logic then there would be a double free at exit
@HenrikHolst is there a good way to verify that the core pinning is working correctly while a game is running? |
@cfebs use ps or top to find the pid of the game once it is running and then you can use "taskset -ap pid-number" to see the cpu mask for the process and all it's threads, depending on the amount of cores your cpu have the default mask would be something like "ffff" if the process was allowed to run on all cores and something like "ff00" or "00ff" if it was masked out of 8 of the cores (each f here represents 4 cores) |
Thanks for the walk through! Here are my results with a 7950X3D and
Here's the result of Was also just using If you would like any help testing other patches LMK! |
that looks correct yes, most likely the game launched new threads some time after launch so looks like we would have to store the pids that we watch and apply the mask on a regular basis to catch cases like this. |
Did another test with a steam game (if just to provide more info for other testers!). Also tried to debug which procs gamemode considers registered:
The main proc that was taking most cpu time was different though: Here's the taskset results:
And here's my ps + cli args for those procs: https://gist.github.com/cfebs/50e8c6b4198cce20db713bbfad451734
Gotcha, I'll keep using this build for as long as it's stable - thank you for the branch and the quick responses. |
made core pinning optionally silent, used for when the reaper thread calls us repeatable so we don't create tons of unnecessary logs
Reapply the core pinning from the reaper thread to catch cases where the game launches threads after initial start
walk through /proc/pid/task to make sure that we set the thread affinity for every single thread in the process
I have added some patches now that reapplies the core pinning in the gamemode reaper thread (by default it runs once every 5 seconds) and I also make sure that we really hit every single thread of the process. |
Awesome, here's the first test with supertuxkart: pinning_tux_1.mp4Looks great so far! |
nice!, thanks for the confirmation! |
Here are some Steam tests! Each using
So both look like there are a few threads that stay default masked. In DS3 there's more mask variety :) In both cases using |
could be that gamemode for some reason couldn't find the process id or something. One thing to try is to run "gamemodelist" to see if the process is listed as being registered. Another is to edit /etc/xdg/systemd/user/gamemoded.service and change "ExecStart=/usr/bin/gamemoded" to "ExecStart=/usr/bin/gamemoded -l" and then do "systemctl --user daemon-reload && systemctl --user stop gamemoded.service" to let the change take effect (the -l makes gamemoded log more to the journal) and then run "journalctl --user /usr/bin/gamemoded -f" in a terminal and then run the game and see what gamemoded logs. |
Thanks for the logging tip.
So I guess that's just how gamemode works: Hope to see this merged! And LMK if need any more testing. |
thanks for the tests! Hopefully this will increase the fps for the games that do get registered. |
closes #412 |
Took it out for a spin with Starfield, can confirm that the affinity is correctly set for all child processes. Also, got a noticeable bump in FPS in crowded areas. @afayaz-feral any chance this could be merged? This is a major boon for asymmetric CPU owners. |
🎉 |
The original PR #416 failed the format check, but this wasn't apparent until after merging.
hard to say but could be that since the rest of the system, except just the game, can use the other CCD cores when the game is pinned instead of the entire CCD being disabled the game gets more cpu than it would otherwise. |
prob better to open a issue for that than to continue here on the MR but check the gamemode log, in order to park the cores an external utility have to be used which means that polkit is also used and if you are on say ubuntu < 23.04 or some version of debian then the included polkit rules are incomatible and have to be manually remade to work |
First attempt at merging this patch set that adds cpu core pinning and parking capability. There is automatic logic that will try to detect if running on a CPU with non-uniform L3 cache (say 7900x3D or 7950x3D) or on a CPU with non-uniform frequencies (say Intel Alder Lake, Raptor Lake and so on with E-cores and P-cores).
By default the code will pin all the threads of the game on the cores with the better L3 or frequency but can also be configured to completely park the less desired cores (akin to how the xbox gamebar works in Windows on the 7900x3D and 7950x3D). Parking requires the aid of an new helper utility, cpucorectl, under polkit since that requires root privileges.
If logic fails or is inadequate then it is also possible to manually set which cores to pin to or which cores to park in the config file. There is also a built in safety check to make sure that the user/logic does not disable all cores by making sure that at least 4 cores have to be available for the game.