Enquanto pesquisava os estados de energia da CPU Core 2 (" estados C "), consegui implementar o suporte para a maioria dos processadores Intel Core / Core 2 herdados. A implementação completa (patch do Linux) com todas as informações de segundo plano está documentada aqui.
À medida que acumulava mais informações sobre esses processadores, começou a ficar aparente que os estados C suportados no (s) modelo (s) Core 2 são muito mais complexos do que os dos processadores anteriores e posteriores. Eles são conhecidos como estados C aprimorados (ou " CxE "), que envolvem o pacote, núcleos individuais e outros componentes no chipset (por exemplo, memória). No momento em que o intel_idle
driver foi lançado, o código não estava particularmente maduro e vários processadores Core 2 foram lançados com suporte ao estado C conflitante.
Algumas informações interessantes sobre o suporte ao estado C do Core 2 Solo / Duo foram encontradas neste artigo em 2006 . Isso está relacionado ao suporte no Windows, mas indica o suporte robusto do estado C do hardware nesses processadores. As informações sobre Kentsfield entram em conflito com o número real do modelo, então acredito que elas estão se referindo a um Yorkfield abaixo:
... o processador Intel Core 2 Extreme de quatro núcleos (Kentsfield) suporta todas as cinco tecnologias de desempenho e economia de energia - Enhanced Intel SpeedStep (EIST), Thermal Monitor 1 (TM1) e Thermal Monitor 2 (TM2), antigo relógio sob demanda Modulação (ODCM), bem como Estados C Aprimorados (CxE). Comparada aos processadores Intel Pentium 4 e Pentium D 600, 800 e 900, que são caracterizados apenas pelo estado Enhanced Halt (C1), essa função foi expandida nos processadores Intel Core 2 (bem como nos processadores Intel Core Solo / Duo) para todos os estados ociosos possíveis de um processador, incluindo Stop Grant (C2), Deep Sleep (C3) e Deep Sleep (C4).
Este artigo de 2008 descreve o suporte a estados C por núcleo em processadores Intel com vários núcleos, incluindo Core 2 Duo e Core 2 Quad (foi encontrada uma leitura útil adicional em segundo plano neste white paper da Dell ):
Um estado C principal é um estado C de hardware. Existem vários estados ociosos principais, por exemplo, CC1 e CC3. Como sabemos, um processador de última geração moderno possui vários núcleos, como os processadores móveis Core Duo T5000 / T7000, lançados recentemente, conhecidos em alguns círculos como Penryn. O que costumávamos pensar como CPU / processador, na verdade tem várias CPUs de uso geral ao lado. O Intel Core Duo possui 2 núcleos no chip do processador. O Intel Core-2 Quad possui 4 desses núcleos por chip de processador. Cada um desses núcleos tem seu próprio estado ocioso. Isso faz sentido, pois um núcleo pode estar ocioso enquanto outro trabalha duro em um encadeamento. Portanto, um estado C central é o estado ocioso de um desses núcleos.
Encontrei uma apresentação de 2010 da Intel que fornece informações adicionais sobre o intel_idle
driver, mas infelizmente não explica a falta de suporte ao Core 2:
Esse driver EXPERIMENTAL substitui o acpi_idle nos processadores Intel Atom, nos processadores Intel Core i3 / i5 / i7 e nos processadores Intel Xeon associados. Ele não suporta o processador Intel Core2 ou anterior.
A apresentação acima indica que o intel_idle
driver é uma implementação do controlador da CPU "menu", que afeta a configuração do kernel do Linux (ou seja, CONFIG_CPU_IDLE_GOV_LADDER
vs. CONFIG_CPU_IDLE_GOV_MENU
). As diferenças entre os governadores da escada e do menu são descritas sucintamente nesta resposta .
A Dell possui um artigo útil que lista a compatibilidade C0 a C6 dos estados C:
Os modos C1 a C3 funcionam basicamente cortando os sinais de relógio usados dentro da CPU, enquanto os modos C4 a C6 funcionam reduzindo a tensão da CPU. Os modos "aprimorados" podem fazer as duas coisas ao mesmo tempo.
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
Nesta tabela (que mais tarde achei incorreta em alguns casos), parece haver uma variedade de diferenças no suporte ao estado C com os processadores Core 2 (observe que quase todos os processadores Core 2 são soquete LGA775, exceto o Core 2 Solo SU3500, que são os processadores Socket BGA956 e Merom / Penryn. Os processadores Solo / Duo "Intel Core" são um dos Socket PBGA479 ou PPGA478).
Uma exceção adicional à tabela foi encontrada neste artigo :
O Core 2 Duo E8500 da Intel suporta os estados C C2 e C4, enquanto o Core 2 Extreme QX9650 não.
Curiosamente, o QX9650 é um processador Yorkfield (família Intel 6, modelo 23, etapa 6). Para referência, meu Q9550S é a família Intel 6, modelo 23 (0x17), etapa 10, que supostamente suporta o estado C C4 (confirmado por meio de experimentação). Além disso, o Core 2 Solo U3500 possui um CPUID idêntico (família, modelo, escalonamento) ao Q9550S, mas está disponível em um soquete não-LGA775, o que confunde a interpretação da tabela acima.
Claramente, o CPUID deve ser usado pelo menos até a etapa para identificar o suporte do estado C para esse modelo de processador e, em alguns casos, pode ser insuficiente (indeterminado no momento).
A assinatura do método para atribuir informações ociosas da CPU é:
#define ICPU(model, cpu) \
{ X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&cpu }
Onde model
é enumerado em asm / intel-family.h . Examinando esse arquivo de cabeçalho, vejo que as CPUs Intel recebem identificadores de 8 bits que parecem corresponder aos números de modelo da família Intel 6:
#define INTEL_FAM6_CORE2_PENRYN 0x17
Pelo exposto, temos a Família Intel 6, Modelo 23 (0x17) definida como INTEL_FAM6_CORE2_PENRYN
. Isso deve ser suficiente para definir estados inativos para a maioria dos processadores Modelo 23, mas pode causar problemas com o QX9650, conforme observado acima.
Portanto, minimamente, cada grupo de processadores que possui um conjunto C-state distinto precisaria ser definido nesta lista.
Zagacki e Ponnala, Intel Technology Journal 12 (3): 219-227, 2008 indicam que os processadores Yorkfield realmente suportam C2 e C4. Eles também parecem indicar que a especificação ACPI 3.0a suporta transições apenas entre os estados C C0, C1, C2 e C3, que eu presumo que também podem limitar o acpi_idle
driver Linux às transições entre esse conjunto limitado de estados C. No entanto, este artigo indica que nem sempre é esse o caso:
Lembre-se de que é o estado da ACPI C, não o processador, portanto, a ACPI C3 pode ser HW C6 etc.
Também de nota:
Além do próprio processador, como o C4 é um esforço sincronizado entre os principais componentes de silício da plataforma, o chipset Intel Q45 Express alcança uma melhoria de energia de 28%.
O chipset que estou usando é realmente um chipset Intel Q45 Express.
A documentação da Intel nos estados do MWAIT é concisa, mas confirma o comportamento da ACPI específica do BIOS:
Os estados C específicos do processador definidos nas extensões MWAIT podem ser mapeados para os tipos de estado C definidos pela ACPI (C0, C1, C2, C3). O relacionamento de mapeamento depende da definição de um estado C pela implementação do processador e é exposto ao OSPM pelo BIOS usando a tabela _CST definida pela ACPI.
Minha interpretação da tabela acima (combinada com uma tabela da Wikipedia , asm / intel-family.he os artigos acima) é:
Modelo 9 0x09 ( Pentium M e Celeron M ):
- Banias: C0, C1, C2, C3, C4
Modelo 13 0x0D ( Pentium M e Celeron M ):
- Dothan, Stealey: C0, C1, C2, C3, C4
Modelo 14 0x0E INTEL_FAM6_CORE_YONAH ( Pentium M aprimorado , Celeron M aprimorado ou Intel Core ):
- Yonah ( Core Solo , Core Duo ): C0, C1, C2, C3, C4, C4E / C5
Modelo 15 0x0F INTEL_FAM6_CORE2_MEROM (alguns Core 2 e Pentium Dual-Core ):
- Kentsfield, Merom, Conroe, Allendale ( E2xxx / E4xxx e 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 móvel de 45 nm ): 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
Da quantidade de diversidade no suporte ao estado C dentro da linha de processadores Core 2, parece que a falta de suporte consistente para os estados C pode ter sido o motivo para não tentar apoiá-los completamente por meio do intel_idle
driver. Gostaria de completar completamente a lista acima para toda a linha Core 2.
Essa não é realmente uma resposta satisfatória, porque me faz pensar em quanta energia desnecessária é usada e o excesso de calor foi (e ainda é) gerado por não utilizar totalmente os robustos estados MWAIT C de economia de energia desses processadores.
Chattopadhyay et al. 2018, Processadores de alto desempenho com eficiência energética: abordagens recentes para projetar uma computação de alto desempenho verde vale a pena notar o comportamento específico que estou procurando no chipset Q45 Express:
Estado C do pacote (PC0-PC10) - Quando os domínios de computação, Núcleo e Gráficos (GPU) estão ociosos, o processador tem uma oportunidade de economia de energia adicional nos níveis não classificadas e da plataforma, por exemplo, liberando a LLC e ativando a energia. controlador de memória e DRAM IO e, em algum estado, todo o processador pode ser desligado enquanto seu estado é preservado no domínio de energia sempre ativado.
Como teste, inseri o seguinte na linha 127 do linux / drivers / idle / intel_idle.c :
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 }
};
na intel_idle.c
linha 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,
};
na intel_idle.c
linha 1073:
ICPU(INTEL_FAM6_CORE2_MEROM, idle_cpu_conroe),
ICPU(INTEL_FAM6_CORE2_PENRYN, idle_cpu_core2),
Após uma rápida compilação e reinicialização dos meus nós PXE, dmesg
agora mostra:
[ 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
E agora o 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, acessei os estados C do Enhanced Core 2, e parece que há uma queda mensurável no consumo de energia - meu medidor em 8 nós parece estar em média pelo menos 5% menor (com um nó ainda executando o kernel antigo) , mas tentarei trocar os kernels novamente como teste.
Uma observação interessante sobre o suporte ao C4E - o processador My Yorktown Q9550S parece suportá-lo (ou algum outro sub-estado do C4), como evidenciado acima! Isso me confunde, porque a folha de dados da Intel no processador Core 2 Q9000 (seção 6.2) menciona apenas os estados C Normal (C0), HALT (C1 = 0x00), HALT estendido (C1E = 0x01), Stop Grant (C2 = 0x10) , Concessão de parada estendida (C2E = 0x11), suspensão / suspensão profunda (C3 = 0x20) e suspensão mais profunda (C4 = 0x30). O que é esse estado 0x31 adicional? Se eu ativar o estado C2, o C4E será usado em vez do C4. Se eu desativar o estado C2 (estado de força C2E), o C4 será usado em vez do C4E. Eu suspeito que isso possa ter algo a ver com os sinalizadores MWAIT, mas ainda não encontrei a documentação para esse comportamento.
Não sei ao certo o que fazer: o estado C1E parece ser usado no lugar de C1, C2 é usado no lugar de C2E e C4E é usado no lugar de C4. Não tenho certeza se C1 / C1E, C2 / C2E e C4 / C4E podem ser usados juntos intel_idle
ou se são redundantes. Encontrei uma observação nesta apresentação de 2010 do Intel Labs Pittsburgh que indica que as transições são C0 - C1 - C0 - C1E - C0 e outros estados:
C1E é usado apenas quando todos os núcleos estão em C1E
Eu acredito que deve ser interpretado como o estado C1E é inserido em outros componentes (por exemplo, memória) somente quando todos os núcleos estiverem no estado C1E. Também considero que isso se aplica de forma equivalente aos estados C2 / C2E e C4 / C4E (Embora C4E seja referido como "C4E / C5", não tenho certeza se C4E é um subestado de C4 ou se C5 é um sub- estado de C4E. O teste parece indicar que C4 / C4E está correto). Eu posso forçar o C2E a ser usado comentando o estado C2 - no entanto, isso faz com que o estado C4 seja usado em vez do C4E (mais trabalho pode ser necessário aqui). Esperamos que não haja nenhum processador modelo 15 ou modelo 23 que não possua o estado C2E, porque esses processadores seriam limitados a C1 / C1E com o código acima.
Além disso, os sinalizadores, os valores de latência e residência provavelmente podem ser ajustados, mas apenas adivinhar sugestões baseadas nos valores ociosos de Nehalem parece funcionar bem. Mais leitura será necessária para fazer melhorias.
Testei isso em um Core 2 Duo E2220 ( Allendale ), um Dual Core Pentium E5300 ( Wolfdale ), Core 2 Duo E7400 , Core 2 Duo E8400 ( Wolfdale ), Core 2 Quad Q9550S ( Yorkfield ) e Core 2 Extreme QX9650 e I não encontraram problemas além da preferência mencionada anteriormente para os estados C2 / C2E e C4 / C4E.
Não coberto por esta modificação de driver:
- Os Core Solo / Core Duo originais ( Yonah , não Core 2) são da família 6, modelo 14. Isso é bom porque eles suportaram os estados C C4E / C5 (sono profundo aprimorado), mas não os estados C1E / C2E e precisariam de seus própria definição ociosa.
Os únicos problemas em que consigo pensar são:
- O Core 2 Solo SU3300 / SU3500 (Penryn-L) é da família 6, modelo 23 e será detectado por esse driver. No entanto, eles não são soquete LGA775 e, portanto, podem não suportar o estado C da parada avançada C1E. O mesmo vale para o Core 2 Solo ULV U2100 / U2200 ( Merom-L ). No entanto, o
intel_idle
driver parece escolher o C1 / C1E apropriado com base no suporte de hardware dos sub-estados.
- O Core 2 Extreme QX9650 (Yorkfield) supostamente não suporta o estado C2 ou C4. Confirmei isso comprando um processador Optiplex 780 e QX9650 Extreme usado no eBay. O processador suporta os estados C C1 e C1E. Com essa modificação do driver, a CPU fica ociosa no estado C1E, em vez de C1, portanto, presumivelmente há economia de energia. Eu esperava ver o estado C3 C3, mas ele não está presente ao usar esse driver, portanto, talvez seja necessário analisar mais detalhadamente.
Consegui encontrar um slide de uma apresentação da Intel em 2009 sobre as transições entre estados C (ou seja, Deep Power Down):
Em conclusão, verifica-se que não havia motivo real para a falta de suporte ao Core 2 no intel_idle
driver. Agora está claro que o código de stub original do "Core 2 Duo" tratava apenas dos estados C C1 e C2, o que seria muito menos eficiente do que a acpi_idle
função que também lida com o estado C3 C3. Depois que soube onde procurar, implementar o suporte foi fácil. Os comentários úteis e outras respostas foram muito apreciados e, se a Amazon estiver ouvindo, você sabe para onde enviar o cheque.
Esta atualização foi confirmada no github . Em breve, enviarei um patch para o LKML.
Atualização : Eu também consegui desenterrar um Soquete T / LGA775 Allendale ( Conroe ) Core 2 Duo E2220, que é a família 6, modelo 15, então adicionei suporte para isso também. Este modelo carece de suporte para o estado C C4, mas suporta C1 / C1E e C2 / C2E. Isso também deve funcionar para outros chips baseados em Conroe ( E4xxx / E6xxx ) e possivelmente todos os processadores Kentsfield e Merom (não Merom-L).
Atualização : Finalmente encontrei alguns recursos de ajuste do MWAIT. Esse artigo sobre Power vs. Performance e esse Deeper C afirmam e uma postagem no blog de latência aumentada contém algumas informações úteis sobre a identificação de latências ociosas da CPU. Infelizmente, isso apenas relata as latências de saída que foram codificadas no kernel (mas, curiosamente, apenas os estados de hardware suportados pelo processador):
# 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
e dos vários reguladores de desempenho. Quais estados sãopowertop
exibidos no seu sistema?