mirror of
https://github.com/RGBCube/Site
synced 2025-08-01 13:37:49 +00:00
blog: why-cores
This commit is contained in:
parent
031900c8c2
commit
4847abc8eb
1 changed files with 258 additions and 0 deletions
258
site/blog/why-cores.md
Normal file
258
site/blog/why-cores.md
Normal file
|
@ -0,0 +1,258 @@
|
|||
---
|
||||
title: "Why more `/sys/class/hwmon/*/temp*_label` than CPU cores?"
|
||||
|
||||
date: 2025-06-05
|
||||
|
||||
keywords:
|
||||
- hardware
|
||||
---
|
||||
|
||||
So, I am currently working on a Linux tool+daemon to replace
|
||||
[`auto-cpufreq`](https://github.com/AdnanHodzic/auto-cpufreq) with a more
|
||||
efficient, tunable and observable alternative.
|
||||
|
||||
And obviously, to tune a CPU well, knowing how hot it is is a requirement.
|
||||
|
||||
Then, how do you actually see how hot your CPU is in Linux? Using
|
||||
`/sys/class/hwmon` of course.
|
||||
|
||||
This path contains hardware monitoring devices. In the laptop I'm testing this
|
||||
on, `hwmon4` under this directory corresponds to the CPU.
|
||||
|
||||
Let's run a `tree`:
|
||||
|
||||
```text
|
||||
/sys/class/hwmon/hwmon4 -> ../../devices/platform/coretemp.0/hwmon/hwmon4
|
||||
├── device -> ../../../coretemp.0
|
||||
│ ├── driver_override
|
||||
│ ├── hwmon
|
||||
│ ├── modalias
|
||||
│ ├── power
|
||||
│ ├── subsystem -> ../../../bus/platform
|
||||
│ └── uevent
|
||||
├── name
|
||||
├── power
|
||||
│ ├── autosuspend_delay_ms
|
||||
│ ├── control
|
||||
│ ├── runtime_active_time
|
||||
│ ├── runtime_status
|
||||
│ └── runtime_suspended_time
|
||||
├── subsystem -> ../../../../../class/hwmon [recursive, not followed]
|
||||
├── temp10_crit
|
||||
├── temp10_crit_alarm
|
||||
├── temp10_input
|
||||
├── temp10_label
|
||||
├── temp10_max
|
||||
├── temp14_crit
|
||||
├── temp14_crit_alarm
|
||||
├── temp14_input
|
||||
├── temp14_label
|
||||
├── temp14_max
|
||||
├── temp18_crit
|
||||
├── temp18_crit_alarm
|
||||
├── temp18_input
|
||||
├── temp18_label
|
||||
├── temp18_max
|
||||
├── temp1_crit
|
||||
├── temp1_crit_alarm
|
||||
├── temp1_input
|
||||
├── temp1_label
|
||||
├── temp1_max
|
||||
├── temp22_crit
|
||||
├── temp22_crit_alarm
|
||||
├── temp22_input
|
||||
├── temp22_label
|
||||
├── temp22_max
|
||||
├── temp26_crit
|
||||
├── temp26_crit_alarm
|
||||
├── temp26_input
|
||||
├── temp26_label
|
||||
├── temp26_max
|
||||
├── temp2_crit
|
||||
├── temp2_crit_alarm
|
||||
├── temp2_input
|
||||
├── temp2_label
|
||||
├── temp2_max
|
||||
├── temp30_crit
|
||||
├── temp30_crit_alarm
|
||||
├── temp30_input
|
||||
├── temp30_label
|
||||
├── temp30_max
|
||||
├── temp34_crit
|
||||
├── temp34_crit_alarm
|
||||
├── temp34_input
|
||||
├── temp34_label
|
||||
├── temp34_max
|
||||
├── temp35_crit
|
||||
├── temp35_crit_alarm
|
||||
├── temp35_input
|
||||
├── temp35_label
|
||||
├── temp35_max
|
||||
├── temp36_crit
|
||||
├── temp36_crit_alarm
|
||||
├── temp36_input
|
||||
├── temp36_label
|
||||
├── temp36_max
|
||||
├── temp37_crit
|
||||
├── temp37_crit_alarm
|
||||
├── temp37_input
|
||||
├── temp37_label
|
||||
├── temp37_max
|
||||
├── temp38_crit
|
||||
├── temp38_crit_alarm
|
||||
├── temp38_input
|
||||
├── temp38_label
|
||||
├── temp38_max
|
||||
├── temp39_crit
|
||||
├── temp39_crit_alarm
|
||||
├── temp39_input
|
||||
├── temp39_label
|
||||
├── temp39_max
|
||||
├── temp40_crit
|
||||
├── temp40_crit_alarm
|
||||
├── temp40_input
|
||||
├── temp40_label
|
||||
├── temp40_max
|
||||
├── temp41_crit
|
||||
├── temp41_crit_alarm
|
||||
├── temp41_input
|
||||
├── temp41_label
|
||||
├── temp41_max
|
||||
├── temp42_crit
|
||||
├── temp42_crit_alarm
|
||||
├── temp42_input
|
||||
├── temp42_label
|
||||
├── temp42_max
|
||||
├── temp43_crit
|
||||
├── temp43_crit_alarm
|
||||
├── temp43_input
|
||||
├── temp43_label
|
||||
├── temp43_max
|
||||
├── temp44_crit
|
||||
├── temp44_crit_alarm
|
||||
├── temp44_input
|
||||
├── temp44_label
|
||||
├── temp44_max
|
||||
├── temp45_crit
|
||||
├── temp45_crit_alarm
|
||||
├── temp45_input
|
||||
├── temp45_label
|
||||
├── temp45_max
|
||||
├── temp46_crit
|
||||
├── temp46_crit_alarm
|
||||
├── temp46_input
|
||||
├── temp46_label
|
||||
├── temp46_max
|
||||
├── temp47_crit
|
||||
├── temp47_crit_alarm
|
||||
├── temp47_input
|
||||
├── temp47_label
|
||||
├── temp47_max
|
||||
├── temp48_crit
|
||||
├── temp48_crit_alarm
|
||||
├── temp48_input
|
||||
├── temp48_label
|
||||
├── temp48_max
|
||||
├── temp49_crit
|
||||
├── temp49_crit_alarm
|
||||
├── temp49_input
|
||||
├── temp49_label
|
||||
├── temp49_max
|
||||
├── temp6_crit
|
||||
├── temp6_crit_alarm
|
||||
├── temp6_input
|
||||
├── temp6_label
|
||||
├── temp6_max
|
||||
└── uevent
|
||||
```
|
||||
|
||||
Let's `cat` all the `_label` files:
|
||||
|
||||
```text
|
||||
/sys/class/hwmon/hwmon4/temp1_label:
|
||||
Package id 0
|
||||
/sys/class/hwmon/hwmon4/temp2_label:
|
||||
Core 0
|
||||
/sys/class/hwmon/hwmon4/temp6_label:
|
||||
Core 4
|
||||
/sys/class/hwmon/hwmon4/temp10_label:
|
||||
Core 8
|
||||
/sys/class/hwmon/hwmon4/temp14_label:
|
||||
Core 12
|
||||
/sys/class/hwmon/hwmon4/temp18_label:
|
||||
Core 16
|
||||
/sys/class/hwmon/hwmon4/temp22_label:
|
||||
Core 20
|
||||
/sys/class/hwmon/hwmon4/temp26_label:
|
||||
Core 24
|
||||
/sys/class/hwmon/hwmon4/temp30_label:
|
||||
Core 28
|
||||
/sys/class/hwmon/hwmon4/temp34_label:
|
||||
Core 32
|
||||
/sys/class/hwmon/hwmon4/temp35_label:
|
||||
Core 33
|
||||
/sys/class/hwmon/hwmon4/temp36_label:
|
||||
Core 34
|
||||
/sys/class/hwmon/hwmon4/temp37_label:
|
||||
Core 35
|
||||
/sys/class/hwmon/hwmon4/temp38_label:
|
||||
Core 36
|
||||
/sys/class/hwmon/hwmon4/temp39_label:
|
||||
Core 37
|
||||
/sys/class/hwmon/hwmon4/temp40_label:
|
||||
Core 38
|
||||
/sys/class/hwmon/hwmon4/temp41_label:
|
||||
Core 39
|
||||
/sys/class/hwmon/hwmon4/temp42_label:
|
||||
Core 40
|
||||
/sys/class/hwmon/hwmon4/temp43_label:
|
||||
Core 41
|
||||
/sys/class/hwmon/hwmon4/temp44_label:
|
||||
Core 42
|
||||
/sys/class/hwmon/hwmon4/temp45_label:
|
||||
Core 43
|
||||
/sys/class/hwmon/hwmon4/temp46_label:
|
||||
Core 44
|
||||
/sys/class/hwmon/hwmon4/temp47_label:
|
||||
Core 45
|
||||
/sys/class/hwmon/hwmon4/temp48_label:
|
||||
Core 46
|
||||
/sys/class/hwmon/hwmon4/temp49_label:
|
||||
Core 47
|
||||
```
|
||||
|
||||
Notice something? I do:
|
||||
|
||||
- `temp1_label` is `Package id 0` - what is that?
|
||||
- Other core numbers make no sense. This device only has 32 cores, there
|
||||
shouldn't be any gaps within numbers and the numbers shouldn't go that high.
|
||||
|
||||
The explanation for the first point is simple, looking at the kernel
|
||||
[`coretemp.c`](https://github.com/torvalds/linux/blob/ec7714e4947909190ffb3041a03311a975350fe0/drivers/hwmon/coretemp.c#L348)
|
||||
implementation, we can see that it is the temperature of the CPU as a whole:
|
||||
|
||||
```c
|
||||
static ssize_t show_label(
|
||||
struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
char *buf
|
||||
) {
|
||||
struct platform_data *pdata = dev_get_drvdata(dev);
|
||||
struct temp_data *tdata = container_of(devattr, struct temp_data, sd_attrs[ATTR_LABEL]);
|
||||
|
||||
if (is_pkg_temp_data(tdata))
|
||||
return sprintf(buf, "Package id %u\n", pdata->pkg_id);
|
||||
|
||||
return sprintf(buf, "Core %u\n", tdata->cpu_core_id);
|
||||
}
|
||||
```
|
||||
|
||||
That leaves us the second question. Why do we have CPUs 1, 2, 6, 10, 14, 18, 22,
|
||||
26, 30, 34-49, instead of the expected 0-31?
|
||||
|
||||
It turns out that CPU It's common for chip manufacturers to disable faulty or
|
||||
degraded cores before shipping. Or if a lower tier SKU[^Stock Keeping Unit] is
|
||||
selling more, cores of higher tier SKUs are disabled to match expectations.
|
||||
|
||||
Most likely the 32 core CPU I was testing this on was actually just the 64 core
|
||||
version with a bunch of the cores disabled.
|
Loading…
Add table
Add a link
Reference in a new issue