Mientras investigaba los estados de potencia de la CPU Core 2 (" C "), logré implementar el soporte para la mayoría de los procesadores Intel Core / Core 2 heredados. Aquí se documenta la implementación completa (parche de Linux) con toda la información de fondo.
A medida que acumulé más información sobre estos procesadores, comenzó a hacerse evidente que los estados C admitidos en los modelos Core 2 son mucho más complejos que los procesadores anteriores y posteriores. Estos se conocen como estados C mejorados (o " CxE "), que involucran el paquete, los núcleos individuales y otros componentes en el conjunto de chips (p. Ej., Memoria). En el momento en intel_idle
que se lanzó el controlador, el código no era particularmente maduro y se habían lanzado varios procesadores Core 2 que tenían un soporte de estado C en conflicto.
En este artículo de 2006 se encontró información convincente sobre el soporte Core 2 Solo / Duo C-state . Esto está relacionado con el soporte en Windows, sin embargo, sí indica el soporte robusto del estado C del hardware en estos procesadores. La información sobre Kentsfield entra en conflicto con el número de modelo real, por lo que creo que en realidad se refieren a un Yorkfield a continuación:
... el procesador de cuatro núcleos Intel Core 2 Extreme (Kentsfield) admite las cinco tecnologías de rendimiento y ahorro de energía: Intel SpeedStep (EIST) mejorado, Monitor térmico 1 (TM1) y Monitor térmico 2 (TM2), antiguo reloj bajo demanda Modulación (ODCM), así como Estados C mejorados (CxE). En comparación con los procesadores Intel Pentium 4 y Pentium D 600, 800 y 900, que se caracterizan solo por el estado de detención mejorada (C1), esta función se ha ampliado en los procesadores Intel Core 2 (así como en los procesadores Intel Core Solo / Duo) para todos los posibles estados inactivos de un procesador, incluidos Stop Grant (C2), Deep Sleep (C3) y Deeper Sleep (C4).
Este artículo de 2008 describe el soporte para estados C por núcleo en procesadores Intel de múltiples núcleos, incluidos Core 2 Duo y Core 2 Quad (se encontró una lectura de fondo útil adicional en este documento de Dell ):
Un estado C central es un estado C de hardware. Hay varios estados inactivos centrales, por ejemplo, CC1 y CC3. Como sabemos, un procesador moderno de última generación tiene múltiples núcleos, como los procesadores móviles Core Duo T5000 / T7000 recientemente lanzados, conocidos como Penryn en algunos círculos. Lo que solíamos pensar como una CPU / procesador, en realidad tiene múltiples CPU de propósito general a su lado. El Intel Core Duo tiene 2 núcleos en el chip del procesador. El Intel Core-2 Quad tiene 4 de estos núcleos por chip de procesador. Cada uno de estos núcleos tiene su propio estado inactivo. Esto tiene sentido ya que un núcleo puede estar inactivo mientras otro está trabajando duro en un hilo. Entonces, un estado C central es el estado inactivo de uno de esos núcleos.
Encontré una presentación de 2010 de Intel que proporciona algunos antecedentes adicionales sobre el intel_idle
controlador, pero desafortunadamente no explica la falta de soporte para Core 2:
Este controlador EXPERIMENTAL sustituye a acpi_idle en los procesadores Intel Atom, los procesadores Intel Core i3 / i5 / i7 y los procesadores Intel Xeon asociados. No es compatible con el procesador Intel Core2 o anterior.
La presentación anterior indica que el intel_idle
controlador es una implementación del gobernador de CPU del "menú", que tiene un impacto en la configuración del kernel de Linux (es decir, CONFIG_CPU_IDLE_GOV_LADDER
vs. CONFIG_CPU_IDLE_GOV_MENU
). Las diferencias entre los gobernadores de escalera y de menú se describen sucintamente en esta respuesta .
Dell tiene un útil artículo que enumera la compatibilidad C-state C0 a C6:
Los modos C1 a C3 funcionan básicamente cortando las señales de reloj utilizadas dentro de la CPU, mientras que los modos C4 a C6 funcionan reduciendo el voltaje de la CPU. Los modos "mejorado" pueden hacer ambas cosas al mismo tiempo.
Mode Name CPUs
C0 Operating State All CPUs
C1 Halt 486DX4 and above
C1E Enhanced Halt All socket LGA775 CPUs
C1E — Turion 64, 65-nm Athlon X2 and Phenom CPUs
C2 Stop Grant 486DX4 and above
C2 Stop Clock Only 486DX4, Pentium, Pentium MMX, K5, K6, K6-2, K6-III
C2E Extended Stop Grant Core 2 Duo and above (Intel only)
C3 Sleep Pentium II, Athlon and above, but not on Core 2 Duo E4000 and E6000
C3 Deep Sleep Pentium II and above, but not on Core 2 Duo E4000 and E6000; Turion 64
C3 AltVID AMD Turion 64
C4 Deeper Sleep Pentium M and above, but not on Core 2 Duo E4000 and E6000 series; AMD Turion 64
C4E/C5 Enhanced Deeper Sleep Core Solo, Core Duo and 45-nm mobile Core 2 Duo only
C6 Deep Power Down 45-nm mobile Core 2 Duo only
De esta tabla (que luego descubrí que era incorrecta en algunos casos), parece que hubo una variedad de diferencias en el soporte de estado C con los procesadores Core 2 (tenga en cuenta que casi todos los procesadores Core 2 son Socket LGA775, excepto Core 2 Solo SU3500, que son procesadores Socket BGA956 y Merom / Penryn. Los procesadores "Intel Core" Solo / Duo son uno de los Socket PBGA479 o PPGA478).
Se encontró una excepción adicional a la tabla en este artículo :
El Core 2 Duo E8500 de Intel es compatible con los estados C C2 y C4, mientras que el Core 2 Extreme QX9650 no.
Curiosamente, el QX9650 es un procesador Yorkfield (Intel familia 6, modelo 23, paso 6). Como referencia, mi Q9550S es la familia Intel 6, modelo 23 (0x17), paso 10, que supuestamente admite C-state C4 (confirmado mediante experimentación). Además, el Core 2 Solo U3500 tiene un CPUID idéntico (familia, modelo, paso a paso) al Q9550S, pero está disponible en un zócalo no LGA775, lo que confunde la interpretación de la tabla anterior.
Claramente, el CPUID debe usarse al menos hasta el escalón para identificar el soporte de estado C para este modelo de procesador, y en algunos casos puede ser insuficiente (indeterminado en este momento).
La firma del método para asignar información inactiva de la CPU es:
#define ICPU(model, cpu) \
{ X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&cpu }
Donde model
se enumera en asm / intel-family.h . Al examinar este archivo de encabezado, veo que a las CPU Intel se les asignan identificadores de 8 bits que parecen coincidir con los números de modelo de la familia Intel 6:
#define INTEL_FAM6_CORE2_PENRYN 0x17
De lo anterior, tenemos Intel Family 6, Modelo 23 (0x17) definido como INTEL_FAM6_CORE2_PENRYN
. Esto debería ser suficiente para definir estados inactivos para la mayoría de los procesadores Modelo 23, pero podría causar problemas con QX9650 como se indicó anteriormente.
Por lo tanto, como mínimo, cada grupo de procesadores que tenga un conjunto de estados C distinto debería definirse en esta lista.
Zagacki y Ponnala, Intel Technology Journal 12 (3): 219-227, 2008 indican que los procesadores Yorkfield sí admiten C2 y C4. También parecen indicar que la especificación ACPI 3.0a admite transiciones solo entre los estados C C0, C1, C2 y C3, lo que supongo que también puede limitar el acpi_idle
controlador de Linux a las transiciones entre ese conjunto limitado de estados C. Sin embargo, este artículo indica que puede no ser siempre el caso:
Tenga en cuenta que es el estado ACPI C, no el procesador, por lo que ACPI C3 podría ser HW C6, etc.
También de nota:
Más allá del procesador en sí, dado que C4 es un esfuerzo sincronizado entre los principales componentes de silicio en la plataforma, el chipset Intel Q45 Express logra una mejora de energía del 28 por ciento.
El chipset que estoy usando es un chipset Intel Q45 Express.
La documentación de Intel sobre los estados MWAIT es breve pero confirma el comportamiento ACPI específico del BIOS:
Los estados C específicos del procesador definidos en las extensiones MWAIT pueden correlacionarse con los tipos de estado C definidos por ACPI (C0, C1, C2, C3). La relación de mapeo depende de la definición de un estado C por implementación del procesador y el BIOS la expone a OSPM utilizando la tabla _CST definida por ACPI.
Mi interpretación de la tabla anterior (combinada con una tabla de Wikipedia , asm / intel-family.h y los artículos anteriores) es:
Modelo 9 0x09 ( Pentium M y Celeron M ):
- Banias: C0, C1, C2, C3, C4
Modelo 13 0x0D ( Pentium M y Celeron M ):
- Dothan, Stealey: C0, C1, C2, C3, C4
Modelo 14 0x0E INTEL_FAM6_CORE_YONAH ( Pentium M mejorado , Celeron M mejorado o Intel Core ):
- Yonah ( Core Solo , Core Duo ): C0, C1, C2, C3, C4, C4E / C5
Modelo 15 0x0F INTEL_FAM6_CORE2_MEROM (algunos Core 2 y Pentium Dual-Core ):
- Kentsfield, Merom, Conroe, Allendale ( E2xxx / E4xxx y Core 2 Duo E6xxx, T7xxxx / T8xxxx , Core 2 Extreme QX6xxx , Core 2 Quad Q6xxx ): C0, C1, C1E, C2, C2E
Modelo 23 0x17 INTEL_FAM6_CORE2_PENRYN ( Core 2 ):
- Merom-L / Penryn-L:?
- Penryn ( Core 2 Duo 45-nm mobile ): C0, C1, C1E, C2, C2E, C3, C4, C4E / C5, C6
- Yorkfield ( Core 2 Extreme QX9650 ): C0, C1, C1E, C2E ?, C3
- Wolfdale / Yorkfield ( Core 2 Quad , C2Q Xeon , Core 2 Duo E5xxx / E7xxx / E8xxx , Pentium Dual-Core E6xxx , Celeron Dual-Core ): C0, C1, C1E, C2, C2E, C3, C4
Por la cantidad de diversidad en el soporte de estado C dentro de solo la línea de procesadores Core 2, parece que la falta de soporte consistente para los estados C puede haber sido la razón para no intentar apoyarlos completamente a través del intel_idle
controlador. Me gustaría completar completamente la lista anterior para toda la línea Core 2.
Esta no es realmente una respuesta satisfactoria, porque me hace preguntarme cuánta energía innecesaria se usa y se ha generado (y aún se genera) un exceso de calor al no utilizar completamente los robustos estados C MWAIT de ahorro de energía en estos procesadores.
Chattopadhyay y col. 2018, Procesadores energéticamente eficientes de alto rendimiento: enfoques recientes para el diseño de la informática ecológica de alto rendimiento vale la pena señalar el comportamiento específico que estoy buscando en el chipset Q45 Express:
Paquete C-estado (PC0-PC10): cuando los dominios de proceso, Core y Graphics (GPU) están inactivos, el procesador tiene la oportunidad de ahorrar energía adicional a niveles de núcleo y plataforma, por ejemplo, vaciar la LLC y activar el controlador de memoria y DRAM IO, y en algún estado, todo el procesador puede apagarse mientras su estado se mantiene en el dominio de energía siempre encendido.
Como prueba, inserté lo siguiente en linux / drivers / idle / intel_idle.c línea 127:
static struct cpuidle_state conroe_cstates[] = {
{
.name = "C1",
.desc = "MWAIT 0x00",
.flags = MWAIT2flg(0x00),
.exit_latency = 3,
.target_residency = 6,
.enter = &intel_idle,
.enter_s2idle = intel_idle_s2idle, },
{
.name = "C1E",
.desc = "MWAIT 0x01",
.flags = MWAIT2flg(0x01),
.exit_latency = 10,
.target_residency = 20,
.enter = &intel_idle,
.enter_s2idle = intel_idle_s2idle, },
// {
// .name = "C2",
// .desc = "MWAIT 0x10",
// .flags = MWAIT2flg(0x10),
// .exit_latency = 20,
// .target_residency = 40,
// .enter = &intel_idle,
// .enter_s2idle = intel_idle_s2idle, },
{
.name = "C2E",
.desc = "MWAIT 0x11",
.flags = MWAIT2flg(0x11),
.exit_latency = 40,
.target_residency = 100,
.enter = &intel_idle,
.enter_s2idle = intel_idle_s2idle, },
{
.enter = NULL }
};
static struct cpuidle_state core2_cstates[] = {
{
.name = "C1",
.desc = "MWAIT 0x00",
.flags = MWAIT2flg(0x00),
.exit_latency = 3,
.target_residency = 6,
.enter = &intel_idle,
.enter_s2idle = intel_idle_s2idle, },
{
.name = "C1E",
.desc = "MWAIT 0x01",
.flags = MWAIT2flg(0x01),
.exit_latency = 10,
.target_residency = 20,
.enter = &intel_idle,
.enter_s2idle = intel_idle_s2idle, },
{
.name = "C2",
.desc = "MWAIT 0x10",
.flags = MWAIT2flg(0x10),
.exit_latency = 20,
.target_residency = 40,
.enter = &intel_idle,
.enter_s2idle = intel_idle_s2idle, },
{
.name = "C2E",
.desc = "MWAIT 0x11",
.flags = MWAIT2flg(0x11),
.exit_latency = 40,
.target_residency = 100,
.enter = &intel_idle,
.enter_s2idle = intel_idle_s2idle, },
{
.name = "C3",
.desc = "MWAIT 0x20",
.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
.exit_latency = 85,
.target_residency = 200,
.enter = &intel_idle,
.enter_s2idle = intel_idle_s2idle, },
{
.name = "C4",
.desc = "MWAIT 0x30",
.flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED,
.exit_latency = 100,
.target_residency = 400,
.enter = &intel_idle,
.enter_s2idle = intel_idle_s2idle, },
{
.name = "C4E",
.desc = "MWAIT 0x31",
.flags = MWAIT2flg(0x31) | CPUIDLE_FLAG_TLB_FLUSHED,
.exit_latency = 100,
.target_residency = 400,
.enter = &intel_idle,
.enter_s2idle = intel_idle_s2idle, },
{
.name = "C6",
.desc = "MWAIT 0x40",
.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
.exit_latency = 200,
.target_residency = 800,
.enter = &intel_idle,
.enter_s2idle = intel_idle_s2idle, },
{
.enter = NULL }
};
en la intel_idle.c
línea 983:
static const struct idle_cpu idle_cpu_conroe = {
.state_table = conroe_cstates,
.disable_promotion_to_c1e = false,
};
static const struct idle_cpu idle_cpu_core2 = {
.state_table = core2_cstates,
.disable_promotion_to_c1e = false,
};
en la intel_idle.c
línea 1073:
ICPU(INTEL_FAM6_CORE2_MEROM, idle_cpu_conroe),
ICPU(INTEL_FAM6_CORE2_PENRYN, idle_cpu_core2),
Después de una rápida compilación y reinicio de mis nodos PXE, dmesg
ahora muestra:
[ 0.019845] cpuidle: using governor menu
[ 0.515785] clocksource: acpi_pm: mask: 0xffffff max_cycles: 0xffffff, max_idle_ns: 2085701024 ns
[ 0.543404] intel_idle: MWAIT substates: 0x22220
[ 0.543405] intel_idle: v0.4.1 model 0x17
[ 0.543413] tsc: Marking TSC unstable due to TSC halts in idle states deeper than C2
[ 0.543680] intel_idle: lapic_timer_reliable_states 0x2
Y ahora PowerTOP está mostrando:
Package | CPU 0
POLL 2.5% | POLL 0.0% 0.0 ms
C1E 2.9% | C1E 5.0% 22.4 ms
C2 0.4% | C2 0.2% 0.2 ms
C3 2.1% | C3 1.9% 0.5 ms
C4E 89.9% | C4E 92.6% 66.5 ms
| CPU 1
| POLL 10.0% 400.8 ms
| C1E 5.1% 6.4 ms
| C2 0.3% 0.1 ms
| C3 1.4% 0.6 ms
| C4E 76.8% 73.6 ms
| CPU 2
| POLL 0.0% 0.2 ms
| C1E 1.1% 3.7 ms
| C2 0.2% 0.2 ms
| C3 3.9% 1.3 ms
| C4E 93.1% 26.4 ms
| CPU 3
| POLL 0.0% 0.7 ms
| C1E 0.3% 0.3 ms
| C2 1.1% 0.4 ms
| C3 1.1% 0.5 ms
| C4E 97.0% 45.2 ms
Finalmente he accedido a los estados C mejorados de Core 2, y parece que hay una caída medible en el consumo de energía: mi medidor en 8 nodos parece estar promediando al menos un 5% menos (con un nodo que todavía ejecuta el núcleo antiguo) , pero intentaré cambiar los núcleos nuevamente como prueba.
Una nota interesante con respecto al soporte C4E: mi procesador Q9550S de Yorktown parece admitirlo (o algún otro subestado de C4), como se evidencia anteriormente. Esto me confunde, porque la hoja de datos de Intel en el procesador Core 2 Q9000 (sección 6.2) solo menciona los estados C Normal (C0), HALT (C1 = 0x00), Extended HALT (C1E = 0x01), Stop Grant (C2 = 0x10) , Grant Stop extendido (C2E = 0x11), Sleep / Deep Sleep (C3 = 0x20) y Deeper Sleep (C4 = 0x30). ¿Cuál es este estado adicional 0x31? Si habilito el estado C2, entonces se usa C4E en lugar de C4. Si desactivo el estado C2 (estado de fuerza C2E), entonces se usa C4 en lugar de C4E. Sospecho que esto puede tener algo que ver con las banderas MWAIT, pero todavía no he encontrado documentación para este comportamiento.
No estoy seguro de qué hacer con esto: el estado C1E parece usarse en lugar de C1, C2 se usa en lugar de C2E y C4E se usa en lugar de C4. No estoy seguro si C1 / C1E, C2 / C2E y C4 / C4E se pueden usar junto con intel_idle
o si son redundantes. Encontré una nota en esta presentación de 2010 de Intel Labs Pittsburgh que indica que las transiciones son C0 - C1 - C0 - C1E - C0, y otros estados:
C1E solo se usa cuando todos los núcleos están en C1E
Creo que debe interpretarse como el estado C1E se ingresa en otros componentes (por ejemplo, memoria) solo cuando todos los núcleos están en el estado C1E. También considero que esto se aplica de manera equivalente a los estados C2 / C2E y C4 / C4E (aunque C4E se conoce como "C4E / C5", así que no estoy seguro si C4E es un subestado de C4 o si C5 es un sub- estado de C4E. Las pruebas parecen indicar que C4 / C4E es correcto). Puedo forzar el uso de C2E comentando el estado de C2; sin embargo, esto hace que se use el estado de C4 en lugar de C4E (es posible que se requiera más trabajo aquí). Esperemos que no haya ningún procesador modelo 15 o modelo 23 que carezca del estado C2E, porque esos procesadores estarían limitados a C1 / C1E con el código anterior.
Además, los valores de las banderas, la latencia y la residencia probablemente podrían ajustarse, pero solo tomar conjeturas fundamentadas basadas en los valores inactivos de Nehalem parece funcionar bien. Se requerirá más lectura para hacer cualquier mejora.
Probé esto en un Core 2 Duo E2220 ( Allendale ), un Dual Core Pentium E5300 ( Wolfdale ), Core 2 Duo E7400 , Core 2 Duo E8400 ( Wolfdale ), Core 2 Quad Q9550S ( Yorkfield ) y Core 2 Extreme QX9650 , y yo No hemos encontrado problemas más allá de la preferencia mencionada anteriormente para el estado C2 / C2E y C4 / C4E.
No cubierto por esta modificación del controlador:
- Los Core Solo / Core Duo originales ( Yonah , no Core 2) son de la familia 6, modelo 14. Esto es bueno porque admitían los estados C C4E / C5 (sueño profundo mejorado) pero no los estados C1E / C2E y necesitarían su propia definición de inactividad.
Los únicos problemas que puedo pensar son:
- Core 2 Solo SU3300 / SU3500 (Penryn-L) son de la familia 6, modelo 23 y serán detectados por este controlador. Sin embargo, no son Socket LGA775, por lo que es posible que no admitan el estado C de detención mejorada de C1E. Del mismo modo para el Core 2 Solo ULV U2100 / U2200 ( Merom-L ). Sin embargo, el
intel_idle
controlador parece elegir el C1 / C1E apropiado en función del soporte de hardware de los subestados.
- Según se informa, Core 2 Extreme QX9650 (Yorkfield) no es compatible con C-state C2 o C4. He confirmado esto comprando un procesador Optiplex 780 y QX9650 Extreme usado en eBay. El procesador admite los estados C C1 y C1E. Con esta modificación del controlador, la CPU está inactiva en el estado C1E en lugar de C1, por lo que presumiblemente hay algunos ahorros de energía. Esperaba ver C-state C3, pero no está presente cuando uso este controlador, por lo que es posible que deba investigar esto más a fondo.
Logré encontrar una diapositiva de una presentación de Intel de 2009 sobre las transiciones entre estados C (es decir, Deep Power Down):
En conclusión, resulta que no había una razón real para la falta de compatibilidad con Core 2 en el intel_idle
controlador. Ahora está claro que el código auxiliar original para "Core 2 Duo" solo maneja los estados C C1 y C2, que habrían sido mucho menos eficientes que la acpi_idle
función que también maneja el estado C C3. Una vez que supe dónde buscar, implementar el soporte fue fácil. Los comentarios útiles y otras respuestas fueron muy apreciados, y si Amazon está escuchando, ya sabe dónde enviar el cheque.
Esta actualización se ha comprometido con github . Enviaré un parche por correo electrónico a LKML pronto.
Actualización : También logré desenterrar un Socket T / LGA775 Allendale ( Conroe ) Core 2 Duo E2220, que es la familia 6, modelo 15, por lo que también agregué soporte para eso. Este modelo carece de soporte para C-state C4, pero admite C1 / C1E y C2 / C2E. Esto también debería funcionar para otros chips basados en Conroe ( E4xxx / E6xxx ) y posiblemente para todos los procesadores Kentsfield y Merom (no Merom-L).
Actualización : finalmente encontré algunos recursos de ajuste de MWAIT. Esta redacción de Power vs. Performance y estos estados de C más profundos y la publicación de blog de latencia aumentada contienen información útil sobre la identificación de latencias inactivas de CPU. Desafortunadamente, esto solo informa las latencias de salida que se codificaron en el núcleo (pero, curiosamente, solo los estados de hardware admitidos por el procesador):
# cd /sys/devices/system/cpu/cpu0/cpuidle
# for state in `ls -d state*` ; do echo c-$state `cat $state/name` `cat $state/latency` ; done
c-state0/ POLL 0
c-state1/ C1 3
c-state2/ C1E 10
c-state3/ C2 20
c-state4/ C2E 40
c-state5/ C3 20
c-state6/ C4 60
c-state7/ C4E 100
acpi_idle
los diversos gobernadores de rendimiento. ¿Qué estados sepowertop
muestran en su sistema?