Desativando dinamicamente os núcleos de maneira eficiente em termos de consumo de energia?

3

Estou procurando um mecanismo para desativar dinamicamente núcleos no Linux para minimizar o consumo de energia.

Infelizmente, desabilitar os núcleos usando a seguinte abordagem simples na verdade aumenta a potência, com base em leituras de um Watts Up? Pro medindo a potência total do sistema:

echo 0 > /sys/devices/system/cpu/cpu7/online

Minha experiência parece ser confirmada por outras pessoas (embora esse bug tenha sido marcado como "CLOSED PATCH_ALREADY_AVAILABLE"): link

Como a máquina está descarregada, eu quero que todos, exceto um dos núcleos (ou talvez dois "núcleos", desde que a CPU esteja hyper-threaded) estejam no estado de repouso mais profundo possível. Isso não parece estar acontecendo sozinho, com base na saída do acpitool:

Processor ID           : 7
Bus mastering control  : no
Power management       : yes
Throttling control     : no
Limit interface        : no
Active C-state         : C0
C-states (incl. C0)    : 3
Usage of state C1      : 899 (99.3 %)
Usage of state C2      : 6 (0.7 %)

BTW, um ponto de confusão para mim é que acpitool e / proc / acpi parecem discordar sobre os estados C disponíveis, ou talvez eles usem esquemas de nomenclatura diferentes.

$ cat /proc/acpi/processor/CPU7/power 
active state:            C0
max_cstate:              C8
maximum allowed latency: 2000000000 usec
states:
    C1:                  type[C1] promotion[--] demotion[--] latency[001] usage[00000000] duration[00000000000000000000]
    C2:                  type[C2] promotion[--] demotion[--] latency[017] usage[00001248] duration[00000000001877531423]
    C3:                  type[C3] promotion[--] demotion[--] latency[017] usage[00000006] duration[00000000000012580727]

Isto parece indicar que existem 4 estados C (C0-C3), mas o acpitool apenas reporta 3 estados C.

Realmente isso se resume a duas perguntas:

  1. Existe uma maneira (segura) de forçar núcleos individuais em um estado de suspensão específico (estado C) e forçá-los a permanecerem lá até que eu os acorde explicitamente?
  2. Como alternativa, como posso melhorar a capacidade do sistema operacional de colocar automaticamente os núcleos em estados de suspensão mais profundos?

Observe que a latência de acordar de estados de sono mais profundos não é uma preocupação. FWIW, estou executando o Ubuntu 10.04.3 (kernel 2.6.32-38) em um Intel i7 920.

    
por Michael Boyer 02.03.2012 / 01:58

1 resposta

-1

Os métodos para limitar os estados C acima serão todos permanentes (até que o sistema seja reinicializado). Se você quisesse gostaria de ter um sistema com latência extremamente baixa durante certas horas, mas quer mais economia de energia em outras vezes, existe um método para controlar dinamicamente quais estados-C são usados.

Para controlar dinamicamente os estados C, abra o arquivo / dev / cpu_dma_latency e grave a latência máxima permitida para ele. Isso impedirá que os estados C com latências de transição maiores do que o valor especificado sejam utilizados, desde que o arquivo / dev / cpu_dma_latency seja mantido aberto. A gravação de uma latência máxima permitida de 0 manterá os processadores em C0 (como o uso do parâmetro do kernel "idle = poll") e a gravação de um valor baixo (geralmente 5 ou inferior) deve forçar os processadores a C1 quando ociosos. O valor exato necessário para restringir os processadores ao estado C1 depende de vários fatores, como qual driver inativo você está usando, quais CPUs você está usando e, possivelmente, as tabelas ACPI em seu sistema. Valores mais altos também podem ser gravados para restringir o uso de estados C com latência maior que o valor gravado. O valor usado deve corresponder aos valores de latência em / sys / devices / system / cpu / cpuX / cpuidle / stateY / latency (onde X é o número da CPU e Y é o estado inativo) - estados inativos da CPU que têm uma latência maior que escrito para / dev / cpu_dma_latency não deve ser usado.

Uma maneira simples de fazer isso é compilar um programa simples que irá gravar nesse arquivo e permanecer aberto até ser eliminado. Um exemplo de tal programa está abaixo, e pode ser compilado cortando e colando o código em um arquivo chamado setcpulatency.c, e executando “make setcpulatency”. Portanto, para minimizar a latência durante certas horas, por exemplo, das 8h às 17h, um cron job pode ser configurado para ser executado às 8h. Esse cron job poderia executar setcpulatency em segundo plano com um argumento de 0, com uma entrada na tabela cron assim:

00 08 * * * /path/to/setcpulatency 0 &

Então, às 17h, outro trabalho do cron pode matar qualquer programa que mantenha o / dev / cpu_dma_latency aberto:

00 17 * * * kill -9 'lsof –t /dev/cpu_dma_latency'

Naturalmente, este é apenas um exemplo para mostrar como os estados C podem ser controlados dinamicamente ... o serviço crond geralmente é desativado em ambientes de baixa latência, mas essas etapas podem ser executadas manualmente ou executadas por outros meios.

#include <stdio.h>
#include <fcntl.h>

int main(int argc, char **argv) {
   int32_t l;
   int fd;

   if (argc != 2) {
      fprintf(stderr, "Usage: %s <latency in us>\n", argv[0]);
      return 2;
   }

   l = atoi(argv[1]);
   printf("setting latency to %d us\n", l);

   fd = open("/dev/cpu_dma_latency", O_WRONLY);

   if (fd < 0) {
      perror("open /dev/cpu_dma_latency");
      return 1;
   }

   if (write(fd, &l, sizeof(l)) != sizeof(l)) {
      perror("write to /dev/cpu_dma_latency");
      return 1;
   }
}
    
por 19.10.2016 / 18:00