Comment limiter le nombre de cœurs de processeur que chaque utilisateur peut utiliser?

18

Nous avons un ordinateur dont le processeur a 32 cœurs et il va être utilisé pour exécuter des programmes par quelques utilisateurs différents. Existe-t-il un moyen de restreindre le nombre de cœurs que chaque utilisateur peut utiliser à tout moment afin qu'un utilisateur ne monopolise pas toute la puissance du processeur?

Reza
la source
5
Pas une réponse, seulement une idée. Vous souhaiterez peut-être étudier la configuration de plusieurs machines virtuelles. Chacun ne pouvait avoir qu'une quantité limitée de CPU. Chaque utilisateur ne serait que sur l'une des machines virtuelles et les utilisateurs de cette machine virtuelle seraient limités dans l'utilisation du processeur. Il se peut que certains logiciels de virtualisation disposent d'outils pour prendre en charge cela.
ghellquist
1
@ghellquist vous devriez en faire une réponse
slebetman
@ghellquist: Vous voulez probablement quelque chose d'aussi léger que possible, comme des conteneurs Linux, si vous voulez simplement que différents utilisateurs ne voient que certains CPU. (Par exemple, quand ils démarrent un OpenMP ou un autre programme qui démarre autant de threads qu'il voit de cœurs, il démarre un nombre approprié pour la quantité de cœurs que vous laissez chaque utilisateur réellement utiliser). La virtualisation complète, comme KVM, a un coût de performance même avec une prise en charge matérielle comme VT-X ou AMD-V, à partir de niveaux supplémentaires de tables de pages, même lorsque les sorties de machine virtuelle sont évitées, dans un code qui élimine tout manquement TLB en touchant beaucoup de mémoire.
Peter Cordes
Je suis désolé, mais est-ce même nécessaire? En tant que système multi-utilisateur, Linux implémente déjà par défaut le multitâche préemptif, donc la situation où un seul utilisateur (non malveillant) monopolise tout le système pour lui-même ne devrait pas se présenter.
Cubic

Réponses:

16

Bien que cela soit possible , c'est compliqué et presque certainement une mauvaise idée. Si un seul utilisateur utilise la machine pour le moment, les limiter à N cœurs est un gaspillage de ressources. Une bien meilleure approche serait de tout faire avec 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).

Il s'agit d'un excellent outil qui définit la priorité d'un processus. Donc, si un seul utilisateur exécute quelque chose, il obtiendra autant de temps processeur qu'il en aura besoin, mais si quelqu'un d'autre lance son propre travail (également sympa), il sera gentil et partagera les uns avec les autres. De cette façon, si vos utilisateurs lancent tous des commandes avec nice 10 command, personne ne monopolisera les ressources (et personne ne mettra le serveur à genoux).

Notez qu'une valeur de Nice élevée signifie une faible priorité. C'est une mesure de la façon dont nous devrions être gentils et plus nous sommes gentils, plus nous partageons.

Notez également que cela n'aidera pas à gérer l'allocation de mémoire, cela n'affectera que la planification du processeur. Donc, si plusieurs utilisateurs lancent plusieurs processus gourmands en mémoire, vous aurez toujours un problème. Si c'est un problème, vous devriez examiner les systèmes de mise en file d'attente appropriés tels que le couple .

terdon
la source
Merci pour votre réponse. Il existe des "gestionnaires de charge de travail" tels que SLURM, mais ils sont destinés aux ordinateurs à plusieurs nœuds. Je suppose qu'il est logique que les gens n'aient pas développé d'applications similaires pour les ordinateurs à nœud unique car il n'y a pas autant de demande.
Reza
@Reza essayez nice, d'après ce que vous décrivez, c'est exactement ce dont vous avez besoin.
terdon le
3
@Reza: C'est parce que le système d'exploitation le fait déjà. Il partage automatiquement le temps entre les CPU disponibles et les threads / processus selon les besoins.
BlueRaja - Danny Pflughoeft
13

TL; DR : De brèves recherches, il semble qu'il soit possible de restreindre les commandes à un nombre spécifique de cœurs, mais dans tous les cas, vous devez utiliser une commande qui applique réellement la restriction.

groupes de contrôle

Linux a cgroupsqui est fréquemment utilisé exactement dans le but de restreindre les ressources disponibles pour les processus. À partir d'une très brève recherche, vous pouvez trouver un exemple dans Arch Wiki avec la configuration Matlab (un logiciel scientifique) définie dans /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;
    }
}

Pour qu'une telle configuration prenne effet, vous devez exécuter le processus via une cgexeccommande, par exemple à partir de la même page wiki:

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

ensemble de tâches

Une question connexe sur Ask Ubuntu et comment limiter un processus à un cœur de processeur sous Linux? [duplicate] sur le site Unix et Linux montre un exemple d'utilisation tasksetpour limiter les processeurs pour le processus. Dans la première question, il est réalisé en analysant tous les processus pour un utilisateur particulier

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

Dans l'autre question, un processus est lancé via tasksetlui-même:

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

Conclusion

Bien qu'il soit certainement possible de limiter les processus, il semble que ce ne soit pas si simple de le faire pour des utilisateurs particuliers. L'exemple dans le post Ask Ubuntu lié nécessiterait une analyse cohérente des processus appartenant à chaque utilisateur et utilisant tasksetchaque nouveau. Une approche beaucoup plus raisonnable consisterait à exécuter de manière sélective des applications gourmandes en ressources CPU, via cgexecou taskset; il est également inutile de restreindre tous les processus à un nombre spécifique de CPUS, en particulier pour ceux qui utilisent réellement le parallélisme et la concurrence pour exécuter leurs tâches plus rapidement - les limiter à un nombre spécifique de CPU peut avoir pour effet de ralentir le traitement. De plus, comme la réponse de Terdon l'a mentionné, c'est un gaspillage de ressources

L'exécution de certaines applications via tasksetou cgexecnécessite de communiquer avec vos utilisateurs pour leur faire savoir quelles applications ils peuvent exécuter, ou la création de scripts d'encapsulation qui lanceront certaines applications via taskselou cgexec.

En outre, envisagez de définir le nombre de processus qu'un utilisateur ou un groupe peut générer au lieu de définir une limite sur le nombre de processeurs. Cela peut être réalisé via un /etc/security/limits.conffichier .

Voir également

Sergiy Kolodyazhnyy
la source
1
bien, il y a cgrulesengd et cgrules.conf pour déplacer automatiquement les processus vers le groupe de contrôle approprié en fonction de l'utilisateur / groupe au lieu de compter sur les utilisateurs exécutant leurs processus avec cgexec. Mais il semble que la configuration de cela dans ubuntu soit quelque peu banale.
Hans-Jakob
@ Hans-Jakob Il semble quelque peu compliqué, et nécessite l'ajout de drapeaux de noyau dans GRUB. Probablement pour le niveau d'entreprise de la machine, où vous avez beaucoup d'utilisateurs et ne voulez pas qu'ils plantent le système, cela en vaut probablement la peine, mais pour le bureau - trop de travail. Merci d'avoir lié cela.
Sergiy Kolodyazhnyy
2
sched_setaffinity(2)dit que le masque d'affinité est conservé à travers execve(2), et qu'un enfant en hérite fork(2). Donc, si vous définissez le shell pour un utilisateur (ou leur shell graphique pour une session X), tout ce qu'ils commencent à partir de ce shell utilise par défaut le même masque d'affinité.
Peter Cordes
1
Un inconvénient possible est les programmes qui vérifient le nombre de processeurs de la machine lors du choix du nombre de threads à démarrer; ils auront trop de threads pour le nombre de cœurs sur lesquels ils seront réellement programmés. Avez-vous découvert si les groupes de contrôle pouvaient faire quelque chose à ce sujet?
Peter Cordes
@PeterCordes L'idée de la coquille d'apparition semble intéressante. Je vais devoir examiner cela. Merci ! Quant au deuxième commentaire, non, je n'ai pas suffisamment recherché les groupes de contrôle à ce stade.
Sergiy Kolodyazhnyy