É possível aumentar a duração das fatias de tempo para as quais o escalonador de CPU do Linux permite que um processo seja executado? Como eu poderia fazer isso?
Conhecimento prévio
Esta questão pergunta como reduzir a frequência com que o kernel forçará uma alternância entre diferentes processos executados na mesma CPU. Este é o recurso do kernel descrito como "multitarefa preventiva". Esse recurso geralmente é bom, porque interrompe um processo individual que sobrecarrega a CPU e torna o sistema completamente sem resposta. No entanto, alternar entre processos tem um custo , portanto, há uma compensação.
Se você tiver um processo que usa todo o tempo de CPU que pode obter e outro processo que interage com o usuário, alternar com mais frequência pode reduzir as respostas atrasadas.
Se você tiver dois processos que usam todo o tempo de CPU que podem obter, alternar com menos frequência pode permitir que eles realizem mais trabalho ao mesmo tempo.
Motivação
Estou postando isso com base na minha reação inicial à pergunta Como alterar a frequência de troca de contexto do Linux?
Eu pessoalmente não quero alterar o timelice. No entanto, lembro vagamente que isso é uma coisa, com a CONFIG_HZ
opção de tempo de construção. Então eu quero saber qual é a situação atual. A fatia de tempo do agendador de CPU ainda é baseada em CONFIG_HZ
?
Além disso, na prática, o ajuste em tempo de construção é muito limitante. Para distribuições Linux, é muito mais prático se elas puderem ter um único kernel por arquitetura de CPU e permitir configurá-lo em tempo de execução ou pelo menos em tempo de inicialização. Se o ajuste da fatia de tempo ainda for relevante, existe um novo método que não o bloqueie em tempo de compilação?
Para a maioria dos servidores RHEL7, a RedHat sugere aumentar
sched_min_granularity_ns
para 10ms esched_wakeup_granularity_ns
para 15ms. ( Fonte . Tecnicamente este link diz 10 μs, o que seria 1000 vezes menor. É um erro).Podemos tentar entender essa sugestão com mais detalhes.
Aumentando sched_min_granularity_ns
Nos kernels Linux atuais, as fatias de tempo da CPU são alocadas para tarefas pelo CFS, o Completely Fair Scheduler. O CFS pode ser ajustado usando algumas
sysctl
configurações.kernel.sched_min_granularity_ns
kernel.sched_latency_ns
kernel.sched_wakeup_granularity_ns
Você pode definir sysctl temporariamente até a próxima reinicialização ou permanentemente em um arquivo de configuração que é aplicado em cada inicialização. Para saber como aplicar esse tipo de configuração, procure "sysctl" ou leia a breve introdução aqui .
sched_min_granularity_ns
é a configuração mais proeminente. No sched-design-CFS.txt original, isso foi descrito como a única configuração "ajustável", "para ajustar o agendador de cargas de trabalho de 'desktop' (baixas latências) para 'servidor' (bom lote)".Em outras palavras, podemos alterar essa configuração para reduzir as sobrecargas da alternância de contexto e, portanto, melhorar a taxa de transferência ao custo da capacidade de resposta ("latência").
Acho que essa configuração do CFS imita a configuração de tempo de compilação anterior, CONFIG_HZ . Na primeira versão do código CFS, o valor padrão era 1 ms, equivalente a 1000 Hz para uso "desktop". Outros valores suportados de CONFIG_HZ foram 250 Hz (o padrão) e 100 Hz para a extremidade "servidor". 100 Hz também foi útil ao executar Linux em CPUs muito lentas, esse foi um dos motivos apresentados quando CONFIG_HZ foi adicionado pela primeira vez como uma configuração de compilação no X86 .
Parece razoável tentar alterar esse valor em até 10 ms (ou seja, 100 Hz) e medir os resultados. Lembre-se de que os sysctls são medidos em ns . 1 ms = 1.000.000 ns.
Podemos ver que esse ajuste antigo para 'servidor' ainda era muito relevante em 2011, para taxa de transferência em alguns testes de benchmark de alta carga: https://events.static.linuxfound.org/slides/2011/linuxcon/lcna2011_rajan.pdf
E talvez algumas outras configurações
Os valores padrão das três configurações acima parecem relativamente próximos uns dos outros. Isso me faz querer manter as coisas simples e multiplicá-las todas pelo mesmo fator :-). Mas tentei analisar isso e parece que alguns ajustes mais específicos também podem ser relevantes, já que você está ajustando a taxa de transferência.
sched_wakeup_granularity_ns
diz respeito à "preempção de despertar". Ou seja, ele controla quando uma tarefa despertada por um evento é capaz de antecipar imediatamente o processo em execução no momento. Os slides de 2011 também mostraram diferenças de desempenho para essa configuração.Consulte também "Desativar WAKEUP_PREEMPT" nesta referência de 2010 da IBM , que sugere que "para algumas cargas de trabalho" esse recurso padrão "pode custar uma pequena porcentagem da utilização da CPU".
O SUSE Linux tem um documento que sugere configurar isso para mais da metade de
sched_latency_ns
desativará efetivamente a preempção de ativação e, em seguida, "as tarefas de ciclo de trabalho curto não poderão competir com os porcos da CPU de maneira eficaz".O documento do SUSE também sugere algumas descrições mais detalhadas das outras configurações. Você deve definitivamente verificar quais são os valores padrão atuais em seus próprios sistemas. Por exemplo, os valores padrão no meu sistema parecem um pouco diferentes do que o documento do SUSE diz.
https://www.suse.com/documentation/opensuse121/book_tuning/data/sec_tuning_taskscheduler_cfs.html
Se você experimentar qualquer uma dessas variáveis de agendamento, acho que também deve estar ciente de que todas as três são dimensionadas (multiplicadas) por 1+log_2 do número de CPUs. Essa escala pode ser desabilitada usando
kernel.sched_tunable_scaling
. Eu poderia estar faltando alguma coisa, mas isso parece surpreendente, por exemplo, se você estiver considerando a capacidade de resposta de servidores que fornecem aplicativos interativos e rodam em/perto de carga total, e como essa capacidade de resposta varia com o número de CPUs por servidor.Sugestão se sua carga de trabalho tiver um grande número de threads/processos
Também encontrei uma sugestão de 2013, para algumas outras configurações, que podem obter uma taxa de transferência significativa se sua carga de trabalho tiver um grande número de threads. (Ou talvez mais precisamente, ele recupera a taxa de transferência que eles obtiveram em kernels pré-CFS).
Ignorar
CONFIG_HZ
Eu acho que você não precisa se preocupar com o que
CONFIG_HZ
está definido. Meu entendimento é que não é relevante nos kernels atuais, supondo que você tenha um hardware de temporizador razoável. Veja também commit 8f4d37ec073c, "sched: high-res preemption tick" , encontrado através deste comentário em um tópico sobre a mudança: https://lwn.net/Articles/549754/ .(Se você olhar para o commit, eu não me preocuparia que
SCHED_HRTICK
depende deX86
. Esse requisito parece ter sido descartado em algum commit mais recente).Parece que você precisa do programador de lotes: use
schedtool
para executar processos em diferentes programadores. por exemploschedtool -B «Command to be run in batch mode»
(deveria ser um comentário, mas é um pouco longo)
Somente se o kernel estiver antecipando tarefas e as colocando de volta na fila de execução.
Geralmente deve ser pouco frequente e de curta duração quando isso acontece. Normalmente, as tarefas irão produzir explicitamente esperando que algo aconteça. A única vez que você verá algum benefício é onde a carga é consistentemente maior que o número de CPUs. Mas você também correrá o risco de perder a capacidade de resposta.