¿Cómo se puede restringir el número de núcleos de CPU que puede usar cada usuario?

18

Tenemos una computadora cuya CPU tiene 32 núcleos y será utilizada por algunos usuarios diferentes para ejecutar programas. ¿Hay alguna forma de restringir el número de núcleos que cada usuario puede usar en cualquier momento para que un usuario no monopolice toda la potencia de la CPU?

Reza
fuente
55
No es una respuesta, solo una idea. Es posible que desee considerar la configuración de varias máquinas virtuales. Cada uno podría tener solo una cantidad limitada de CPU-s. Cada usuario solo estaría en una de las máquinas virtuales, y los usuarios de esa VM estarían limitados en el uso de la CPU. Puede ser que algunos de los softwares de virtualización tengan herramientas para respaldar esto.
ghellquist
1
@ghellquist deberías responder
eso
@ghellquist: Probablemente desee algo lo más liviano posible, como los contenedores de Linux, si solo desea que diferentes usuarios solo vean algunas de las CPU. (por ejemplo, cuando inician un OpenMP u otro programa que inicia tantos subprocesos como ve núcleos, comenzará un número apropiado para la cantidad de núcleos que está permitiendo que cada usuario realmente use). La virtualización completa, como KVM, tiene un costo de rendimiento incluso con soporte de hardware como VT-X o AMD-V, desde niveles adicionales de tablas de páginas incluso cuando se evitan las salidas de VM, en el código que obtiene cualquier falla de TLB al tocar mucha memoria.
Peter Cordes
Lo siento, pero ¿hay alguna necesidad de esto? Como un sistema multiusuario, Linux por defecto ya implementa la multitarea preventiva, por lo que la situación en la que un solo usuario (no malicioso) acapara todo el sistema por sí mismo no debería surgir.
Cubic

Respuestas:

16

Si bien esto es posible , es complicado y casi seguro que es una mala idea. Si solo un usuario está usando la máquina en este momento, restringirlos a N núcleos es un desperdicio de recursos. Un enfoque mucho mejor sería ejecutar todo con 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).

Esta es una gran herramienta que establece la prioridad de un proceso. Entonces, si solo un usuario está ejecutando algo, obtendrán tanto tiempo de CPU como necesiten, pero si alguien más lanza su propio trabajo (también conocido), serán amables y se compartirán entre sí. De esa forma, si todos sus usuarios inician comandos nice 10 command, nadie estará acaparando recursos (y nadie pondrá al servidor de rodillas).

Tenga en cuenta que un valor agradable alto significa una prioridad baja. Esta es una medida de cuán agradables deberíamos ser y cuanto más agradables seamos, más compartiremos.

También tenga en cuenta que esto no ayudará a administrar la asignación de memoria, solo afecta la programación de la CPU. Por lo tanto, si varios usuarios inician múltiples procesos de uso intensivo de memoria, aún tendrá un problema. Si eso es un problema, debe buscar sistemas de colas adecuados, como el par .

terdon
fuente
Gracias por tu respuesta. Hay algunos "gestores de carga de trabajo" como SLURM, pero son para computadoras con múltiples nodos. Supongo que tiene sentido que las personas no hayan desarrollado aplicaciones similares para computadoras de un solo nodo ya que no hay tanta demanda.
Reza
@Reza intente nice, por lo que describe, eso es exactamente lo que necesita.
terdon el
3
@Reza: Eso es porque el sistema operativo ya lo hace. Automáticamente comparte el tiempo de las CPU disponibles con subprocesos / procesos según sea necesario.
BlueRaja - Danny Pflughoeft
13

TL; DR : De una breve investigación parece que es posible restringir los comandos a un número específico de núcleos, sin embargo, en todos los casos, debe usar un comando que realmente aplique la restricción.

cgroups

Linux tiene cgroupsque se utiliza con frecuencia exactamente con el fin de restringir los recursos disponibles para los procesos. A partir de una investigación muy breve, puede encontrar un ejemplo en Arch Wiki con la configuración de Matlab (un software científico) establecida en /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 dicha configuración surta efecto, debe ejecutar el proceso mediante un cgexeccomando, por ejemplo, desde la misma página wiki:

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

conjunto de tareas

¿Una pregunta relacionada sobre Ask Ubuntu y cómo limitar un proceso a un núcleo de CPU en Linux? [duplicado] en el sitio de Unix y Linux muestra un ejemplo de uso tasksetpara limitar las CPU para el proceso. En la primera pregunta, se logra mediante el análisis de todos los procesos para un usuario en particular

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

En la otra pregunta, un proceso se inicia por tasksetsí mismo:

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

Conclusión

Si bien es ciertamente posible limitar los procesos, parece que no es tan simple lograrlo para usuarios particulares. El ejemplo en la publicación de Ask Ubuntu vinculada requeriría un escaneo consistente para los procesos que pertenecen a cada usuario y se usan taskseten cada uno nuevo. Un enfoque mucho más razonable sería ejecutar selectivamente aplicaciones intensivas de CPU, ya sea a través de cgexeco taskset; Tampoco tiene sentido restringir todos los procesos a un número específico de CPUS, especialmente para aquellos que realmente utilizan el paralelismo y la concurrencia para ejecutar sus tareas más rápido; limitarlos a un número específico de CPU puede tener el efecto de ralentizar el procesamiento. Además, como la respuesta de terdon mencionó es un desperdicio de recursos

Ejecutar aplicaciones seleccionadas a través de taskseto cgexecrequiere comunicarse con sus usuarios para hacerles saber qué aplicaciones pueden ejecutar, o crear scripts de envoltura que inicien aplicaciones seleccionadas a través de taskselo cgexec.

Además, considere establecer el número de procesos que puede generar un usuario o grupo en lugar de establecer el límite en el número de CPU. Esto se puede lograr a través del /etc/security/limits.confarchivo .

Ver también

Sergiy Kolodyazhnyy
fuente
1
bueno, hay cgrulesengd y cgrules.conf para mover automáticamente los procesos al cgroup apropiado en función del usuario / grupo en lugar de depender de los usuarios que ejecutan sus procesos con cgexec. Pero parece que configurar esto en ubuntu es algo no trivial.
Hans-Jakob
@ Hans-Jakob Parece algo complicado, además requiere agregar banderas de kernel en GRUB. Probablemente para el nivel de máquina empresarial, donde tienes muchos usuarios y no quieres que bloqueen el sistema, probablemente valga la pena, pero para el escritorio, demasiado trabajo. Gracias por vincular eso.
Sergiy Kolodyazhnyy
2
sched_setaffinity(2)dice la máscara de afinidad se conserva en todo execve(2), y que un niño hereda el fork(2). Entonces, si configura el shell para un usuario (o su shell gráfico para una sesión X), todo lo que comiencen desde ese shell, por defecto, usará la misma máscara de afinidad.
Peter Cordes
1
Una posible desventaja son los programas que verifican cuántas CPU tiene la máquina al decidir cuántos subprocesos iniciar; tendrán demasiados hilos para la cantidad de núcleos en los que realmente se programarán. ¿Descubriste si cgroups podría hacer algo al respecto?
Peter Cordes
@PeterCordes La idea de shell de desove suena interesante. Tendré que investigar eso. Gracias ! En cuanto al segundo comentario, no, no he investigado lo suficiente cgroups en este momento.
Sergiy Kolodyazhnyy