Maison > Article > Tutoriel système > Le tueur de processeur double cœur accélère l'exécution de vos processus Linux !
Lors de l'utilisation de systèmes Linux, nous rencontrons souvent des tâches gourmandes en CPU, telles que le traitement de données, la compilation de programmes, etc., qui nécessitent une grande quantité de ressources informatiques. Cependant, si la configuration matérielle de notre système est faible, cela entraînera une exécution lente des tâches et affectera sérieusement notre efficacité au travail. Pour résoudre ce problème, cet article présentera une technologie appelée « liaison CPU », qui peut lier un processus à un cœur de CPU spécifique, améliorant ainsi l'efficacité d'exécution du processus.
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 nécessite une efficacité opérationnelle plus élevée, il est nécessaire d'envisager de le lier à un cœur distinct afin de réduire la surcharge causée par la planification sur différents cœurs.
Après avoir lié un processus/thread à un cœur de processeur spécifique, le processus s'exécutera toujours sur ce cœur et ne sera pas planifié sur d'autres cœurs par le système d'exploitation. Mais le noyau lié peut toujours être programmé pour exécuter d'autres applications.
Planification des processeurs multicœurs par le système d'exploitation
Actuellement, Windows et Linux prennent en charge la planification et la gestion des processeurs multicœurs.
Le cœur du développement logiciel dans un environnement multicœur est le développement multithread. Ce multithreading représente non seulement le multithreading dans la mise en œuvre logicielle, mais nécessite également l'utilisation de la technologie multithreading dans le matériel.
Les systèmes d'exploitation multicœurs se concentrent sur l'allocation et la planification des processus. L'allocation de processus alloue les processus à des cœurs physiques raisonnables, car différents cœurs ont des conditions de partage et de fonctionnement historiques différentes. Certains cœurs physiques peuvent partager le cache de deuxième niveau, tandis que d'autres sont indépendants. Si un processus avec partage de données est alloué à un cœur avec un cache secondaire partagé, les performances seront grandement améliorées ; sinon, les performances pourraient être affectées.
La planification des processus impliquera des problèmes tels que les performances en temps réel et l'équilibrage de charge. Les questions brûlantes de recherche actuelles se concentrent principalement sur les aspects suivants :
La situation lorsque plusieurs processus et multithread s'exécutent sur le cœur du processeur est la suivante :
Lorsque chaque cœur de processeur exécute un processus, puisque 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 doivent parfois partager des ressources, ces ressources doivent donc être copiées d'un cœur du processeur à un autre, ce qui entraînera une surcharge supplémentaire
Lier le processus à exécuter sur le cœur du processeur
Vérifiez le nombre de cœurs du processeur
Utilisez cat /proc/cpuinfo pour afficher les informations sur le processeur, les deux informations suivantes :
processeur, précisez quel processeur CPU
cœurs de processeur, précisez le nombre de cœurs de chaque processeur
Vous pouvez également utiliser l'appel système sysconf pour obtenir le nombre de cœurs CPU :
#include int sysconf(_SC_NPROCESSORS_CONF);/* 返回系统可以使用的核数,但是其值会包括系统中禁用的核的数目,因 此该值并不代表当前系统中可用的核数 */ int sysconf(_SC_NPROCESSORS_ONLN);/* 返回值真正的代表了系统当前可用的核数 */ /* 以下两个函数与上述类似 */ #include int get_nprocs_conf (void);/* 可用核数 */ int get_nprocs (void);/* 真正的反映了当前可用核数 */
J'utilise une machine virtuelle avec 2 processeurs. Chaque processeur n'a qu'un seul cœur, ce qui équivaut à deux cœurs sur un processeur.
Utilisez la commande tasket
Obtenir le pid du processus
-> % 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
Vérifiez sur quel processeur le processus s'exécute actuellement
-> % taskset -p 2726 pid 2726's current affinity mask: 3
Le nombre décimal affiché 3 est converti en binaire et les deux plus bas sont 1. Chaque 1 correspond à un CPU, le processus s'exécute donc sur 2 CPU.
Le processus spécifié s'exécute sur cpu1
-> % taskset -pc 1 2726 pid 2726's current affinity list: 0,1 pid 2726's new affinity list: 1
Notez que l'étiquette du processeur commence à 0, donc cpu1 représente le deuxième processeur (la première étiquette du processeur est 0).
À ce stade, l'application est liée à cpu1 pour s'exécuter, comme indiqué ci-dessous :
-> % taskset -p 2726 pid 2726's current affinity mask: 2
Lier le processeur au démarrage du programme
#启动时绑定到第二个cpu -> % taskset -c 1 ./dgram_servr& [1] 3011 #查看确认绑定情况 -> % taskset -p 3011 pid 3011's current affinity mask: 2
Utilisez l'appel système sched_setaffinity
sched_setaffinity peut lier un processus à un processeur spécifique.
#define _GNU_SOURCE /* See feature_test_macros(7) */ #include /* 设置进程号为pid的进程运行在mask所设定的CPU上 * 第二个参数cpusetsize是mask所指定的数的长度 * 通常设定为sizeof(cpu_set_t) * 如果pid的值为0,则表示指定的是当前进程 */ 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);/* 获得pid所指示的进程的CPU位掩码,并将该掩码返回到mask所指向的结构中 */
Exemples
#include #include #include #include #include #define __USE_GNU #include #include #include #include #define THREAD_MAX_NUM 200 //1个CPU内的最多进程数 int num=0; //cpu中核数 void* threadFun(void* arg) //arg 传递线程标号(自己定义) { cpu_set_t mask; //CPU核的集合 cpu_set_t get; //获取在集合中的CPU int *a = (int *)arg; int i; printf("the thread is:%d\n",*a); //显示是第几个线程 CPU_ZERO(&mask); //置空 CPU_SET(*a,&mask); //设置亲和力值 if (sched_setaffinity(0, sizeof(mask), &mask) == -1)//设置线程CPU亲和力 { printf("warning: could not set CPU affinity, continuing...\n"); } CPU_ZERO(&get); if (sched_getaffinity(0, sizeof(get), &get) == -1)//获取线程CPU亲和力 { printf("warning: cound not get thread affinity, continuing...\n"); } for (i = 0; i if (CPU_ISSET(i, &get))//判断线程与哪个CPU有亲和力 { printf("this thread %d is running processor : %d\n", i,i); } } return NULL; } int main(int argc, char* argv[]) { int tid[THREAD_MAX_NUM]; int i; pthread_t thread[THREAD_MAX_NUM]; num = sysconf(_SC_NPROCESSORS_CONF); //获取核数 if (num > THREAD_MAX_NUM) { printf("num of cores[%d] is bigger than THREAD_MAX_NUM[%d]!\n", num, THREAD_MAX_NUM); return -1; } printf("system has %i processor(s). \n", num); for(i=0;ifor(i=0; ireturn 0; }
Exécuter les résultats
-> % ./a.out system has 2 processor(s). the thread is:0 the thread is:1 this thread 0 is running processor : 0 this thread 1 is running processor : 1
Lier les threads pour qu'ils s'exécutent sur le cœur du processeur
Liez les threads au cœur du processeur à l'aide de la fonction pthread_setaffinity_np. Son prototype est défini comme suit :
#define _GNU_SOURCE /* See feature_test_macros(7) */ #include int pthread_setaffinity_np(pthread_t thread, size_t cpusetsize, const cpu_set_t *cpuset); int pthread_getaffinity_np(pthread_t thread, size_t cpusetsize, cpu_set_t *cpuset); Compile and link with -pthread.
La signification de chaque paramètre est similaire à sched_setaffinity.
Exemples
#define _GNU_SOURCE #include #include #include #include #define handle_error_en(en, msg) \ do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0) int main(int argc, char *argv[]) { int s, j; cpu_set_t cpuset; pthread_t thread; thread = pthread_self(); /* Set affinity mask to include CPUs 0 to 7 */ CPU_ZERO(&cpuset); for (j = 0; j if (s != 0) handle_error_en(s, "pthread_setaffinity_np"); /* Check the actual affinity mask assigned to the thread */ s = pthread_getaffinity_np(thread, sizeof(cpu_set_t), &cpuset); if (s != 0) handle_error_en(s, "pthread_getaffinity_np"); printf("Set returned by pthread_getaffinity_np() contained:\n"); for (j = 0; j if (CPU_ISSET(j, &cpuset)) printf(" CPU %d\n", j); exit(EXIT_SUCCESS); }
Exécuter les résultats
-> % ./a.out Set returned by pthread_getaffinity_np() contained: CPU 0 CPU 1
Grâce à l'introduction de cet article, nous avons appris à utiliser la technologie de liaison de processeur pour lier un processus à un cœur de processeur spécifique, améliorant ainsi considérablement l'efficacité d'exécution du processus. Dans les applications réelles, nous pouvons choisir des solutions de liaison CPU appropriées en fonction de différents scénarios et besoins pour obtenir le meilleur effet d'amélioration des performances. J'espère que cet article pourra aider les lecteurs à mieux comprendre et appliquer la technologie de liaison CPU, et à atteindre une plus grande efficacité de travail dans l'utilisation des systèmes Linux.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!