Como se pode restringir o número de núcleos de CPU que cada usuário pode usar?

17

Temos um computador cuja CPU possui 32 núcleos e será usada para executar programas por alguns usuários diferentes. Existe alguma maneira de restringir o número de núcleos que cada usuário pode usar a qualquer momento para que um usuário não monopolize toda a energia da CPU?

Reza
fonte
5
Não é uma resposta, apenas uma ideia. Você pode querer configurar várias máquinas virtuais. Cada um pode ter apenas uma quantidade limitada de CPU-s. Cada usuário estaria apenas em uma das máquinas virtuais e os usuários nessa VM seriam limitados no uso da CPU. Pode ser que alguns dos softwares de virtualização possuam ferramentas para dar suporte a isso.
precisa saber é o seguinte
11
@ghellquist você deve fazer que uma resposta
slebetman
@ghellquist: Você provavelmente quer algo o mais leve possível, como contêineres Linux, se quiser que usuários diferentes vejam apenas algumas das CPUs. (por exemplo, quando eles iniciam um OpenMP ou outro programa que inicia o número de threads que vê núcleos, ele inicia um número apropriado para a quantidade de núcleos que você está deixando que cada usuário realmente use). A virtualização completa, como o KVM, tem um custo de desempenho, mesmo com suporte de hardware como o VT-X ou o AMD-V, a partir de níveis extras de tabelas de páginas, mesmo quando as saídas da VM são evitadas, em código que causa falta de TLB ao tocar em muita memória.
Peter Cordes
Sinto muito, mas há alguma necessidade disso? Como um sistema multiusuário, por padrão, o Linux já implementa multitarefas preemptivas, portanto a situação em que um único usuário (não malicioso) apenas monopoliza todo o sistema por si só não deve aparecer.
cúbico

Respostas:

16

Embora isso seja possível , é complicado e quase certamente uma má ideia. Se apenas um usuário estiver usando a máquina no momento, restringi-los a N núcleos é um desperdício de recursos. Uma abordagem muito melhor seria executar tudo com nice:

NAME
       nice - run a program with modified scheduling priority

SYNOPSIS
       nice [OPTION] [COMMAND [ARG]...]

DESCRIPTION
       Run  COMMAND  with an adjusted niceness, which affects process scheduling.  With
       no COMMAND, print the current niceness.  Niceness values range  from  -20  (most
       favorable to the process) to 19 (least favorable to the process).

Essa é uma ótima ferramenta que define a prioridade de um processo. Portanto, se apenas um usuário estiver executando alguma coisa, eles terão o tempo de CPU necessário, mas se outra pessoa iniciar seu próprio trabalho (também é necessário), eles serão agradáveis ​​e compartilharão um com o outro. Dessa forma, se todos os seus usuários iniciarem comandos nice 10 command, ninguém estará consumindo recursos (e ninguém trará o servidor de joelhos).

Observe que um valor alto e agradável significa baixa prioridade. Essa é uma medida de quão legais devemos ser e quanto mais agradáveis ​​somos, mais compartilhamos.

Observe também que isso não ajudará a gerenciar a alocação de memória, mas afeta apenas o agendamento da CPU. Portanto, se vários usuários iniciarem vários processos com muita memória, você ainda terá um problema. Se isso é um problema, você deve procurar sistemas de filas adequados, como torque .

Terdon
fonte
Obrigado pela sua resposta. Existem alguns "gerenciadores de carga de trabalho", como o SLURM, mas são para computadores com vários nós. Acho que faz sentido que as pessoas não tenham desenvolvido aplicativos semelhantes para computadores de nó único, pois não há tanta demanda.
Reza
@Reza tente nice, pelo que você descreve, é exatamente o que você precisa.
terdon 9/01/19
3
@Reza: Isso porque o sistema operacional já faz isso. Ele compartilha automaticamente as CPUs disponíveis em threads / processos, conforme necessário.
BlueRaja - Danny Pflughoeft
13

TL; DR : a partir de uma breve pesquisa, parece que é possível restringir os comandos a um número específico de núcleos; no entanto, em todos os casos, é necessário usar um comando que realmente imponha a restrição.

cgroups

O Linux possui o cgroupsque é freqüentemente usado exatamente com a finalidade de restringir os recursos disponíveis para os processos. De uma pesquisa muito breve, você pode encontrar um exemplo no Arch Wiki com a configuração do Matlab (um software científico) definida em /etc/cgconfig.conf:

group matlab {
    perm {
        admin {
            uid = username;
        }
        task {
            uid = username;
        }
    }

    cpuset {
        cpuset.mems="0";
        cpuset.cpus="0-5";
    }
    memory {
        memory.limit_in_bytes = 5000000000;
    }
}

Para que essa configuração entre em vigor, você deve executar o processo via cgexeccomando, por exemplo, na mesma página da wiki:

$ cgexec -g memory,cpuset:matlab /opt/MATLAB/2012b/bin/matlab -desktop

conjunto de tarefas

Uma pergunta relacionada ao Ask Ubuntu e Como limitar um processo a um núcleo de CPU no Linux? [duplicado] no site Unix e Linux mostra um exemplo de uso tasksetpara limitar as CPUs do processo. Na primeira pergunta, isso é alcançado através da análise de todos os processos para um usuário específico

$ ps aux | awk '/^housezet/{print $2}' | xargs -l taskset -p 0x00000001

Na outra questão, um processo é iniciado via tasksetele mesmo:

$ taskset -c 0 mycommand --option  # start a command with the given affinity

Conclusão

Embora seja certamente possível limitar processos, parece que não é tão simples conseguir isso para usuários específicos. O exemplo na postagem Ask Ubuntu vinculada exigiria uma verificação consistente dos processos pertencentes a cada usuário e usados tasksetem cada novo. Uma abordagem muito mais razoável seria executar seletivamente aplicativos intensivos da CPU, via cgexecou taskset; também não faz sentido restringir todos os processos a um número específico de CPUS, especialmente para aqueles que realmente usam paralelismo e simultaneidade para executar suas tarefas mais rapidamente - limitá-los a um número específico de CPUs pode ter o efeito de retardar o processamento. Além disso, como a resposta de Terdon mencionou, é um desperdício de recursos

A execução de aplicativos selecionados via tasksetou cgexecrequer a comunicação com seus usuários para que eles saibam quais aplicativos eles podem executar ou a criação de scripts de wrapper que iniciarão aplicativos selecionados via taskselou cgexec.

Além disso, considere definir o número de processos que um usuário ou grupo pode gerar em vez de definir o limite do número de CPUs. Isso pode ser conseguido via /etc/security/limits.confarquivo .

Veja também

Sergiy Kolodyazhnyy
fonte
11
bem, existe o cgrulesengd e o cgrules.conf para mover automaticamente os processos para o cgroup apropriado com base no usuário / grupo, em vez de confiar nos usuários que executam seus processos com o cgexec. Mas parece que configurá-lo no ubuntu não é nada trivial.
Hans-Jakob
@ Hans-Jakob Parece um pouco complicado, além de exigir a adição de sinalizadores de kernel no GRUB. Provavelmente para máquinas de nível corporativo, onde você tem muitos usuários e não deseja que eles travem o sistema, isso provavelmente vale a pena, mas para desktop - muito trabalho. Obrigado por vincular isso.
Sergiy Kolodyazhnyy 9/01/19
2
sched_setaffinity(2)diz a máscara de afinidade é preservada em todo execve(2), e que uma criança herda on fork(2). Portanto, se você definir o shell para um usuário (ou o shell gráfico para uma sessão X), tudo o que iniciar nesse shell usará, por padrão, a mesma máscara de afinidade.
Peter Cordes
11
Uma desvantagem possível são os programas que verificam quantas CPUs a máquina possui ao decidir quantos threads iniciar; eles terão muitos threads para o número de núcleos nos quais serão agendados. Você descobriu se o cgroups pode fazer algo sobre isso?
Peter Cordes
@PeterCordes A ideia da concha desova parece interessante. Vou precisar investigar isso. Obrigado ! Quanto ao segundo comentário, não, eu não pesquisei cgroups o suficiente neste momento.
Sergiy Kolodyazhnyy 10/01/19