Lier le processus / thread à un cœur de processeur spécifique et l'exécuter sous Linux

Transfert depuis: https://blog.csdn.net/guotianqing/article/details/80958281

Présentation
Maintenant, tout le monde utilise essentiellement un processeur multicœur, généralement 4 cœurs. Généralement, les applications sont gérées par le système d'exploitation au moment de l'exécution. Le système d'exploitation planifie tour à tour les processus d'application sur différents cœurs.

Pour les applications ordinaires, le mécanisme de planification par défaut du système d'exploitation ne pose aucun problème. Cependant, lorsqu'un processus a besoin d'une efficacité opérationnelle plus élevée, il est nécessaire d'envisager de l'exécuter sur un cœur séparé pour réduire les frais généraux causés par la planification sur différents cœurs.

Une fois qu'un processus / thread est lié à un cœur de processeur spécifique, le processus s'exécutera toujours sur ce cœur et ne sera pas planifié par le système d'exploitation sur d'autres cœurs. Mais le noyau lié peut toujours être planifié pour exécuter d'autres applications.

Planification du système d'exploitation des processeurs multicœurs
Actuellement, Windows et Linux prennent en charge la gestion de la planification des processeurs multicœurs.

Le cœur du développement logiciel dans un environnement multicœur est le développement multithread. Ce multi-thread représente non seulement le multi-thread dans l'implémentation logicielle, mais nécessite également la technologie multi-thread dans le matériel.

Les systèmes d'exploitation multicœurs se concentrent sur l'allocation et l'ordonnancement des processus. L'allocation de processus alloue les processus à des cœurs physiques raisonnables, car les différents cœurs ont des conditions de partage et d'exploitation historiques différentes. Certains cœurs physiques peuvent partager le cache secondaire, tandis que d'autres sont indépendants. Si le processus de partage de données est alloué au cœur avec un cache secondaire partagé, les performances seront considérablement améliorées, sinon les performances pourraient être affectées.

L'ordonnancement des processus impliquera en temps réel, l'équilibrage de charge et d'autres problèmes.Les points chauds de recherche actuels se concentrent principalement sur les aspects suivants:

Le développement parallèle des tâches
dépendant du temps de la conception du programme d'
allocation multi-processus et de planification d'
erreur de partage de cache problème de
cohérence problème d'accès
communication inter-processus
multi-processeur core ressources internes concurrence
multi-processus et multi-thread s'exécutant sur le noyau du processeur sont les suivants:

Lorsque chaque cœur de processeur exécute un processus, étant donné que les ressources de chaque processus sont indépendantes, il n'est pas nécessaire de prendre en compte le contexte lors du basculement entre les cœurs de processeur. Lorsque
chaque cœur de processeur exécute un thread, les threads ont parfois besoin de partager des ressources. La ressource doit être copiée d'un cœur du CPU vers un autre cœur, ce qui entraînera une surcharge supplémentaire.
Lier le processus pour s'exécuter sur le cœur du processeur.
Afficher le processeur. Il existe plusieurs cœurs.
Utilisez cat / proc / cpuinfo pour afficher les informations du processeur.

processeur, indiquant le nombre de
cœurs de processeur de la CPU, indiquant le nombre de cœurs de chaque processeur.
Vous pouvez également utiliser l'appel système sysconf pour obtenir le nombre de cœurs de processeur:

#include <unistd.h>

int sysconf (_SC_NPROCESSORS_CONF); / * renvoie le nombre de cœurs qui peuvent être utilisés par le système, mais sa valeur inclura le nombre de cœurs désactivés dans le système, donc cette valeur ne représente pas le nombre de cœurs disponibles dans le système actuel * /
int sysconf (_SC_NPROCESSORS_ONLN); / * La valeur de retour représente vraiment le nombre de cœurs actuellement disponibles dans le système * /

/ * Les deux fonctions suivantes sont similaires aux
précédentes * / #include <sys / sysinfo.h>

int get_nprocs_conf (void); / *
Cœurs disponibles * / int get_nprocs (void); / * Reflète vraiment les cœurs actuellement disponibles * /

J'utilise une machine virtuelle, il y a 2 processeurs, chaque processeur n'en a qu'un Le cœur équivaut à un processeur avec deux cœurs.

Utilisez l'instruction de l'ensemble de tâches pour
obtenir le processus pid
->% ps
PID TTY TIME CMD
2683 pts / 1 00:00:00 zsh
2726 pts / 1 00:00:00 dgram_servr
2930 pts / 1 00:00:00 ps pour

voir où le processus s'exécute actuellement Sur le processeur
->% taskset -p 2726
pid 2726 masque d'affinité actuel: 3

montre le nombre décimal 3 converti en 2 hexadécimal est le plus bas deux est 1, chaque 1 correspond à un CPU, donc le processus s'exécute sur 2 CPU.

Le processus spécifié s'exécute sur cpu1
->% taskset -pc 1 2726
pid 2726 liste d'affinité actuelle: 0,1
pid 2726 nouvelle liste d'affinité: 1

Notez que le libellé du cpu commence à 0, donc cpu1 représente le deuxième cpu (le premier L'étiquette d'un processeur est 0).

Jusqu'à présent, l'application est destinée à fonctionner sur cpu1, voir comme suit:

->% tasket -p 2726
pid 2726 masque d'affinité actuel: 2

Lier le cpu au démarrage du programme
# Lier au second cpu au démarrage
->% tasket -c 1 ./dgram_servr&
[1] 3011


#Check pour confirmer l'état de la liaison ->% taskset -p 3011
masque d'affinité actuel du pid 3011: 2

Utilisez l'appel système
sched_setaffinity sched_setaffinity pour lier un processus à une CPU spécifique.

#define _GNU_SOURCE / * Voir feature_test_macros (7) * /
#include <sched.h>

/ * Définissez le processus avec l'ID de processus pid à exécuter sur le CPU défini par le masque
* Le deuxième paramètre cpusetsize est la longueur du nombre spécifié par le masque
* Habituellement défini sur sizeof (cpu_set_t)

* Si la valeur de pid est 0, cela signifie que le processus spécifié est le processus actuel
* /
int sched_setaffinity (pid_t pid, size_t cpusetsize, cpu_set_t * mask);

int sched_getaffinity (pid_t pid, size_t cpusetsize, cpu_set_t * mask); / * Obtenez le masque de bits CPU du processus indiqué par pid et renvoyez le masque à la structure pointée par mask * /

Instance
# include <stdlib.h >
#include <stdio.h>
#include <sys / types.h>
#include <sys / sysinfo.h>
#include <unistd.h>

#define __USE_GNU
#include <sched.h>
#include <ctype.h>
#include <string.h>
#include <pthread.h>
#define THREAD_MAX_NUM 200 // 1 个 CPU 内 的 最多 进程 数

int num = 0; // Le nombre de cœurs dans le CPU
void * threadFun (void * arg) // arg passe l'étiquette du thread (défini par vous-même)
{
cpu_set_t mask; // CPU core set
cpu_set_t get; // Get the CPU
int in the set * a = (int *) arg;
int i;

printf ("le thread est:% d \ n", * a); // Affiche le nombre de threads
CPU_ZERO (& mask); // Définit
CPU_SET (* a, & mask); // Définit la valeur d'affinité
si (sched_setaffinity (0, sizeof (mask), & mask) == -1) // Définir l'affinité CPU du thread
{
printf ("avertissement: impossible de définir l'affinité CPU, en continuant ... \ n");
}

CPU_ZERO (& get);
if (sched_getaffinity (0, sizeof (get), & get) == -1) // Get thread CPU affinity
{
printf ("warning: cound not get thread affinity, continue ... \ n");
}
for (i = 0; i <num; i ++)
{
if (CPU_ISSET (i, & get)) // déterminer avec quel processeur le thread a une affinité avec
{
printf ("ce thread% d exécute le processeur:% d \ n", i, i);
}
}

return NULL;
}

int main (int argc, char * argv [])
{
int tid [THREAD_MAX_NUM];
int i;
thread pthread_t [THREAD_MAX_NUM];

num = sysconf (_SC_NPROCESSORS_CONF); // 获取 核 数
if (num> THREAD_MAX_NUM) {
printf ("le nombre de cœurs [% d] est plus grand que THREAD_MAX_NUM [% d]! \ N", num, THREAD_MAX_NUM);
return -1;
}
printf ("le système a% i processeur (s). \ n", num);

for (i = 0; i <num; i ++)
{
tid [i] = i; // Chaque thread doit avoir un tid [i]
pthread_create (& thread [i], NULL, threadFun, (void *) & tid [i ]);
}
for (i = 0; i <num; i ++)
{
pthread_join (thread [i], NULL); // Attendre la fin de tous les threads, le thread est une boucle sans fin, CTRL + C se termine
}
return 0;
}

Run Résultat
->% ./a.out le
système a 2 processeur (s).
Le thread est: 0
le thread est: 1
ce thread 0 exécute le processeur: 0
ce thread 1 exécute le processeur: 1

lie le thread au noyau du CPU
Utilisez la fonction pthread_setaffinity_np pour exécuter le thread de liaison vers le cœur du processeur. Son prototype est défini comme suit:
#define _GNU_SOURCE / * Voir feature_test_macros (7) * /
#include <pthread.h>

int pthread_setaffinity_np (thread pthread_t, size_t cpusetsize, const cpu_set_t * cpuset);
int pthread_getaffinity_np (thread pthread_t, size_t cpusetsize, cpu_set_t * cpuset);

Compilez et liez avec -pthread.

La signification de chaque paramètre est similaire à sched_setaffinity.

Des exemples

#define _GNU_SOURCE
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

#define handle_error_en (en, msg) \
do {errno = en; perror (msg); exit (EXIT_FAILURE); } tandis que (0)

int
main (int argc, char * argv [])
{
int s, j;
cpu_set_t cpuset;
fil pthread_t;

thread = pthread_self ();

/ * Définissez le masque d'affinité pour inclure les processeurs 0 à 7 * /

CPU_ZERO (& cpuset);
pour (j = 0; j <8; j ++)
CPU_SET (j, & cpuset);

s = pthread_setaffinity_np (thread, sizeof (cpu_set_t), & cpuset);
if (s! = 0)
handle_error_en (s, "pthread_setaffinity_np");

/ * Vérifiez le masque d'affinité réel attribué au thread * /

s = pthread_getaffinity_np (thread, sizeof (cpu_set_t), & cpuset);
if (s! = 0)
handle_error_en (s, "pthread_getaffinity_np");

printf ("L'ensemble retourné par pthread_getaffinity_np () contient: \ n");
pour (j = 0; j <CPU_SETSIZE; j ++)
if (CPU_ISSET (j, & cpuset))
printf ("CPU% d \ n", j);

exit (EXIT_SUCCESS);
}

Résultat en cours d'exécution
->% ./a.out
Ensemble renvoyé par pthread_getaffinity_np () contenu:
CPU 0
CPU 1

Résumé
Il existe plusieurs façons d'affecter des processus / threads à des cœurs de processeur spécifiques pour le fonctionnement.

Dans une utilisation spécifique, il est nécessaire de décider quelle méthode utiliser en fonction du scénario d'utilisation et des exigences. Je pense personnellement que l'étape importante est de déterminer s'il faut utiliser la méthode de liaison des threads au noyau.

[Référence] L'
introduction de systèmes d'exploitation de la technologie multi-coeurs méthode prise en charge pour les processeurs multi-coeurs
noyau de fil lié CPU -sched_setaffinity
pthread_setaffinity_np (3) ManualPTHREAD_SETAFFINITY_NP du programmeur Linux
(3) ----------------
Déclaration de copyright: Cet article est un article original du blogueur CSDN "guotianqing", qui suit l'accord de copyright CC 4.0 BY-SA. Veuillez joindre le lien source d'origine et cette déclaration lors de la réimpression.
Lien d'origine: https://blog.csdn.net/guotianqing/java/article/details/80958281

Je suppose que tu aimes

Origine www.cnblogs.com/sky-heaven/p/12753284.html
conseillé
Classement