.\" -*- coding: UTF-8 -*-
.\" Copyright (C) 2002 Robert Love
.\" and Copyright (C) 2006, 2015 Michael Kerrisk
.\"
.\" %%%LICENSE_START(GPLv2+_DOC_FULL)
.\" This is free documentation; you can redistribute it and/or
.\" modify it under the terms of the GNU General Public License as
.\" published by the Free Software Foundation; either version 2 of
.\" the License, or (at your option) any later version.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual is distributed in the hope that it will be useful,
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
.\" GNU General Public License for more details.
.\"
.\" You should have received a copy of the GNU General Public
.\" License along with this manual; if not, see
.\" .
.\" %%%LICENSE_END
.\"
.\" 2002-11-19 Robert Love - initial version
.\" 2004-04-20 mtk - fixed description of return value
.\" 2004-04-22 aeb - added glibc prototype history
.\" 2005-05-03 mtk - noted that sched_setaffinity may cause thread
.\" migration and that CPU affinity is a per-thread attribute.
.\" 2006-02-03 mtk -- Major rewrite
.\" 2008-11-12, mtk, removed CPU_*() macro descriptions to a
.\" separate CPU_SET(3) page.
.\"
.\"*******************************************************************
.\"
.\" This file was generated with po4a. Translate the source file.
.\"
.\"*******************************************************************
.TH SCHED_SETAFFINITY 2 "1 novembre 2020" Linux "Manuel du programmeur Linux"
.SH NOM
sched_setaffinity, sched_getaffinity \- Définir et récupérer le masque
d'affinité CPU d'un thread
.SH SYNOPSIS
.nf
\fB#define _GNU_SOURCE\fP /* Consultez feature_test_macros(7) */
\fB#include \fP
.PP
\fBint sched_setaffinity(pid_t \fP\fIpid\fP\fB, size_t \fP\fIcpusetsize\fP\fB,\fP
\fB const cpu_set_t *\fP\fImask\fP\fB);\fP
.PP
\fBint sched_getaffinity(pid_t \fP\fIpid\fP\fB, size_t \fP\fIcpusetsize\fP\fB,\fP
\fB cpu_set_t *\fP\fImask\fP\fB);\fP
.fi
.SH DESCRIPTION
Le masque d'affinité CPU d'un thread détermine l'ensemble des processeurs
sur lesquels il est susceptible de s'exécuter. Sur un système
multiprocesseur, définir le masque d'affinité CPU permet d'obtenir une
meilleure performance. Par exemple, en dédiant un CPU à un thread
particulier (c'est\-à\-dire définir le masque d'affinité de ce thread pour
indiquer un seul CPU, et définir le masque d'affinité de tous les autres
threads pour exclure ce CPU), il est possible d'assurer une vitesse
d'exécution maximale pour ce thread. Restreindre un processus pour qu'il ne
s'exécute que sur un seul CPU réduit le coût lié à l'invalidation du cache
qui se produit lorsqu'un thread cesse de s'exécuter sur un CPU puis est
relancé sur un autre CPU.
.PP
Un masque d'affinité CPU est représenté par la structure \fIcpu_set_t\fP, un
ensemble de CPU («\ CPU set\ »), pointé par \fImask\fP. Des macros pour manipuler
des ensembles de CPU sont décrites dans \fBCPU_SET\fP(3).
.PP
\fBsched_setaffinity\fP() définit le masque d'affinité CPU du thread dont
l'identifiant est \fIpid\fP à la valeur donnée par \fImask\fP. Si \fIpid\fP est 0, le
thread appelant est utilisé. L'argument \fIcpusetsize\fP est la taille (en
octets) de la structure pointée par \fImask\fP. Normalement, cet argument doit
être spécifié comme \fIsizeof(cpu_set_t)\fP.
.PP
Si le thread indiqué par \fIpid\fP n'est pas actuellement en cours d'exécution
sur l'un des CPU spécifiés dans \fImask\fP, alors ce thread est migré vers l'un
des CPU spécifiés dans \fImask\fP.
.PP
La fonction \fBsched_getaffinity\fP() écrit dans la structure \fIcpu_set_t\fP
pointée par \fImask\fP le masque de préférences du thread \fIpid\fP. L'argument
\fIcpusetsize\fP indique la taille (en octets) de \fImask\fP. Si \fIpid\fP vaut zéro,
le masque du thread en cours est renvoyé.
.SH "VALEUR RENVOYÉE"
\fBsched_setaffinity\fP() et \fBsched_getaffinity\fP() renvoient \fB0\fP s'ils
réussissent (mais voir «\ Différences entre la bibliothèque C et le noyau\ »
ci\-dessous, qui explique que le \fBsched_getaffinity\fP() sous\-jacent diffère
dans son code de retour). En cas d'échec, \fB\-1\fP est renvoyé et \fIerrno\fP est
positionné pour indiquer l'erreur.
.SH ERREURS
.TP
\fBEFAULT\fP
Une adresse mémoire fournie n'est pas correcte.
.TP
\fBEINVAL\fP
Le masque de bits d'affinité \fImask\fP ne contient pas de processeurs qui
soient actuellement physiquement sur le système et autorisés pour le thread
d'après les restrictions qui peuvent être imposées par les cgroups \fIcpuset\fP
ou le mécanisme «\ cpuset\ » décrit dans \fBcpuset\fP(7).
.TP
\fBEINVAL\fP
(\fBsched_getaffinity\fP() et, pour les noyaux antérieurs à 2.6.9,
\fBsched_setaffinity\fP()) \fIcpusetsize\fP est plus petit que la taille du masque
d'affinité utilisé par le noyau.
.TP
\fBEPERM\fP
(\fBsched_setaffinity\fP()) Le thread appelant n'a pas les privilèges
appropriés. L'appelant doit avoir un UID effectif égal à l'UID effectif ou
réel du thread identifié par \fIpid\fP, ou avoir la capacité \fBCAP_SYS_NICE\fP
dans l'espace de noms de l'utilisateur du thread désigné par \fIpid\fP.
.TP
\fBESRCH\fP
Le thread numéro \fIpid\fP n'existe pas.
.SH VERSIONS
Les appels système d'affinité ont été introduits dans Linux 2.5.8. Les
fonctions enveloppes pour ces appels système ont été introduites dans la
glibc\ 2.3. Au départ, les interfaces de la glibc avaient un paramètre
\fIcpusetsize\fP de type \fIunsigned int\fP. Dans glibc\ 2.3.3, ce paramètre a été
supprimé, mais il a été réintroduit dans glibc\ 2.3.4, avec pour type
\fIsize_t\fP.
.SH CONFORMITÉ
Ces appels système sont spécifiques à Linux.
.SH NOTES
Après un appel à \fBsched_setaffinity\fP(), l'ensemble des CPU sur lesquels le
thread s'exécutera est l'intersection de l'ensemble spécifié dans le
paramètre \fImask\fP et l'ensemble des CPU actuellement présents sur le
système. Le système peut restreindre encore plus l'ensemble des CPU sur
lesquels le thread peut tourner si le mécanisme «\ cpuset\ », décrit dans
\fBcpuset\fP(7), est utilisé. Ces restrictions sur le véritable ensemble de CPU
sur lesquels le thread peut tourner sont imposées sans avertissement par le
noyau.
.PP
Il existe plusieurs manières de déterminer le nombre de processeurs
disponibles sur le système, notamment l'inspection du contenu de
\fI/proc/cpuinfo\fP, l'utilisation de \fBsysconf\fP(3) pour avoir les valeurs des
paramètres \fB_SC_NPROCESSORS_CONF\fP et \fB_SC_NPROCESSORS_ONLN\fP, et
l'inspection de la liste des répertoires de processeur dans
\fI/sys/devices/system/cpu/\fP.
.PP
\fBsched\fP(7) décrit les politiques d'ordonnancement sous Linux.
.PP
Le masque d'affinité est un attribut de thread, qui peut être modifié
indépendamment pour chacun des threads d'un groupe de threads. La valeur
renvoyée par \fBgettid\fP(2) peut être passée dans l'argument \fIpid\fP. Spécifier
un \fIpid\fP de \fB0\fP définira l'attribut pour le thread appelant, et une valeur
égale à celle renvoyée par \fBgetpid\fP(2) définira l'attribut pour le thread
principal du groupe de threads. (Si vous utilisez l'API POSIX des threads,
alors utilisez \fBpthread_setaffinity_np\fP(3) au lieu de
\fBsched_setaffinity\fP().)
.PP
L'option d'amorçage \fIisolcpus\fP peut être utilisée pour isoler un ou
plusieurs processeurs au moment du démarrage, afin qu'aucun processus
n'utilise ces processeurs. Suite à l'utilisation de cette option, la seule
manière d'affecter des processus à un processeur isolé est d'utiliser
\fBsched_setaffinity\fP() ou le mécanisme \fBcpuset\fP(7). Pour plus
d'informations, voir le fichier
\fIDocumentation/admin\-guide/kernel\-parameters.txt\fP des sources du
noyau. Comme indiqué dans ce fichier, \fIisolcpus\fP est le mécanisme
privilégié d'isolation des processeurs (plutôt que de définir à la main
l'affinité processeur de tous les processus du système).
.PP
Un processus enfant créé par \fBfork\fP(2) hérite du masque d'affinité CPU de
son parent. Le masque d'affinité est conservé au travers d'un \fBexecve\fP(2).
.SS "différences entre bibliothèque C et noyau"
Cette page de manuel décrit l'interface de la glibc pour les appels liés à
l'affinité CPU. L'interface des appels système est légèrement différente,
\fImask\fP ayant le type \fIunsigned long\ *\fP, montrant le fait que
l'implémentation des ensembles de CPU est en réalité un simple masque de
bits.
.PP
En cas de succès, l'appel système \fBsched_getaffinity\fP() brut renvoie le
nombre d'octets copiés dans le tampon \fImask\fP\ ; il s'agira de la taille
minimale de \fIcpusetsize\fP et de la taille (en octets) du type de données
\fIcpumask_t\fP utilisée en interne par le noyau pour représenter le masque de
bits du jeu de processeurs.
.SS "Gestion des systèmes ayant de grands masques d'affinité de processeur"
.\" FIXME . See https://sourceware.org/bugzilla/show_bug.cgi?id=15630
.\" and https://sourceware.org/ml/libc-alpha/2013-07/msg00288.html
Les appels système sous\-jacents (qui représentent les masques de processeur
par des masques de bits de type \fIunsigned long\ *\fP) n'imposent aucune
restriction quant à la taille du masque de processeur. Toutefois, le type de
données \fIcpu_set_t\fP utilisé par la glibc a une taille fixe de 128\ octets,
si bien que le nombre maximal de processeurs qui peuvent être représentés
est de 1023. Si le masque d'affinité de processeur du noyau est plus grand
que 1024, les appels sous la forme\ :
.PP
sched_getaffinity(pid, sizeof(cpu_set_t), &mask);
.PP
échouent avec l'erreur \fBEINVAL\fP, celle produite par l'appel système
sous\-jacent si la taille \fImask\fP indiquée dans \fIcpusetsize\fP est inférieure
à celle du masque d'affinité utilisée par le noyau (selon la topologie des
processeurs du système, le masque d'affinité du noyau peut être beaucoup
plus grand que le nombre de processeurs actifs sur le système).
.PP
Si vous travaillez sur des systèmes ayant de grands masques d'affinité de
processeur, vous pouvez allouer de manière dynamique l'argument \fImask\fP
(voir \fBCPU_ALLOC\fP(3)). Actuellement, la seule manière de faire cela est de
sonder la taille de masque nécessaire en utilisant les appels
\fBsched_getaffinity\fP() avec des tailles de masque croissantes (jusqu'à ce
que l'appel n'échoue pas avec l'erreur \fBEINVAL\fP).
.PP
Gardez en tête qu'il se peut que \fBCPU_ALLOC\fP(3) alloue un peu plus de
processeurs que vous ne l'avez demandé (car les ensembles de processeurs
sont implémentés sous forme de masques de bits alloués par unités de
\fIsizeof(long)\fP). Par conséquent, \fBsched_getaffinity\fP() peut positionner
des bits au\-delà de la taille d'allocation demandée car le noyau voit
quelques bits supplémentaires. Donc, l'appelant doit revenir sur les bits de
l'ensemble renvoyé en comptant ceux qui sont positionnés et s'arrêter
lorsqu'il atteint la valeur renvoyée par \fBCPU_COUNT\fP(3) (et non pas revenir
sur les bits de l'ensemble dont une allocation a été demandée).
.SH EXEMPLES
Le programme ci\-dessous crée un processus enfant. Puis le parent et l'enfant
s'affectent mutuellement un processeur indiqué et exécutent des boucles
identiques qui consomment du temps de processeur. Avant de se terminer, le
parent attend que l'enfant s'achève. Le programme prend trois paramètres en
ligne de commande\ : le numéro de processeur du parent, celui de l'enfant et
le nombre de boucles que doivent effectuer les deux processus.
.PP
Comme le montre le modèle ci\-dessous, la quantité de temps processeur et de
temps réel consommé lors de l'exécution d'un programme dépendra des effets
de mise en cache à l'intérieur du processeur et de l'utilisation ou non du
même processeur par les processus.
.PP
On utilise d'abord \fBlscpu\fP(1) pour déterminer que ce système (x86) comporte
deux cœurs, chacun ayant deux processeurs\ :
.PP
.in +4n
.EX
$ \fBlscpu | egrep \-i \(aqcore.*:|socket\(aq\fP
Thread(s) par cœur\ : 2
Cœur(s) par socket\ : 2
Socket(s)\ : 1
.EE
.in
.PP
On chronomètre alors l'opération du programme exemple dans trois cas\ : les
deux processus en fonction sur le même processeur, sur des processeurs
différents du même cœur et sur des processeurs différents sur des cœurs
différents.
.PP
.in +4n
.EX
$ \fBtime \-p ./a.out 0 0 100000000\fP
réel 14.75
utilisateur 3.02
sys 11.73
$ \fBtime \-p ./a.out 0 1 100000000\fP
réel 11.52
utilisateur 3.98
sys 19.06
$ \fBtime \-p ./a.out 0 3 100000000\fP
réel 7.89
utilisateur 3.29
sys 12.07
.EE
.in
.SS "Source du programme"
\&
.EX
#define _GNU_SOURCE
#include
#include
#include
#include
#include
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \e
} while (0)
int
main(int argc, char *argv[])
{
cpu_set_t set;
int parentCPU, childCPU;
int nloops;
if (argc != 4) {
fprintf(stderr, "Usage : %s CPU_parent CPU_enfant nb_boucles\en",
argv[0]);
exit(EXIT_FAILURE);
}
parentCPU = atoi(argv[1]);
childCPU = atoi(argv[2]);
nloops = atoi(argv[3]);
CPU_ZERO(&set);
switch (fork()) {
case \-1: /* Erreur */
errExit("fork");
case 0: /* Enfant */
CPU_SET(childCPU, &set);
if (sched_setaffinity(getpid(), sizeof(set), &set) == \-1)
errExit("sched_setaffinity");
for (int j = 0; j < nloops; j++)
getppid();
exit(EXIT_SUCCESS);
default: /* Parent */
CPU_SET(parentCPU, &set);
if (sched_setaffinity(getpid(), sizeof(set), &set) == \-1)
errExit("sched_setaffinity");
for (int j = 0; j < nloops; j++)
getppid();
wait(NULL); /* Attendre que l'enfant se termine */
exit(EXIT_SUCCESS);
}
}
.EE
.SH "VOIR AUSSI"
.ad l
.nh
\fBlscpu\fP(1), \fBnproc\fP(1), \fBtaskset\fP(1), \fBclone\fP(2), \fBgetcpu\fP(2),
\fBgetpriority\fP(2), \fBgettid\fP(2), \fBnice\fP(2), \fBsched_get_priority_max\fP(2),
\fBsched_get_priority_min\fP(2), \fBsched_getscheduler\fP(2),
\fBsched_setscheduler\fP(2), \fBsetpriority\fP(2), \fBCPU_SET\fP(3),
\fBget_nprocs\fP(3), \fBpthread_setaffinity_np\fP(3), \fBsched_getcpu\fP(3),
\fBcapabilities\fP(7), \fBcpuset\fP(7), \fBsched\fP(7), \fBnumactl\fP(8)
.SH COLOPHON
Cette page fait partie de la publication\ 5.10 du projet \fIman\-pages\fP
Linux. Une description du projet et des instructions pour signaler des
anomalies et la dernière version de cette page peuvent être trouvées à
l'adresse \%https://www.kernel.org/doc/man\-pages/.
.SH TRADUCTION
La traduction française de cette page de manuel a été créée par
Christophe Blaess ,
Stéphan Rafin ,
Thierry Vignaud ,
François Micaux,
Alain Portal ,
Jean-Philippe Guérard ,
Jean-Luc Coulon (f5ibh) ,
Julien Cristau ,
Thomas Huriaux ,
Nicolas François ,
Florentin Duneau ,
Simon Paillard ,
Denis Barbier ,
David Prévot ,
Cédric Boutillier ,
Frédéric Hantrais
et
Jean-Philippe MENGUAL
.
Cette traduction est une documentation libre ; veuillez vous reporter à la
.UR https://www.gnu.org/licenses/gpl-3.0.html
GNU General Public License version 3
.UE
concernant les conditions de copie et
de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.
Si vous découvrez un bogue dans la traduction de cette page de manuel,
veuillez envoyer un message à
.MT
debian-l10n-french@lists.debian.org
.ME .