Bei der Verwendung von Linux-Systemen stoßen wir häufig auf CPU-intensive Aufgaben wie Datenverarbeitung, Programmkompilierung usw., deren Ausführung eine große Menge an Rechenressourcen erfordert. Wenn die Hardwarekonfiguration unseres Systems jedoch niedrig ist, führt dies zu einer langsamen Aufgabenausführung und beeinträchtigt unsere Arbeitseffizienz erheblich. Um dieses Problem anzugehen, wird in diesem Artikel eine Technologie namens „CPU-Bindung“ vorgestellt, mit der ein Prozess an einen bestimmten CPU-Kern gebunden werden kann, wodurch die Ausführungseffizienz des Prozesses verbessert wird.
Für normale Anwendungen ist der Standardplanungsmechanismus des Betriebssystems kein Problem. Wenn ein Prozess jedoch eine höhere Betriebseffizienz erfordert, muss darüber nachgedacht werden, ihn an einen separaten Kern zu binden, um den durch die Planung auf verschiedenen Kernen verursachten Overhead zu reduzieren.
Nachdem ein Prozess/Thread an einen bestimmten CPU-Kern gebunden wurde, wird der Prozess immer auf diesem Kern ausgeführt und vom Betriebssystem nicht für andere Kerne geplant. Der gebundene Kern kann jedoch weiterhin für die Ausführung anderer Anwendungen eingeplant sein.
Planung von Multi-Core-CPUs durch das Betriebssystem
Derzeit unterstützen sowohl Windows als auch Linux die Planung und Verwaltung von Multi-Core-CPUs.
Der Kern der Softwareentwicklung in einer Multicore-Umgebung ist die Multithread-Entwicklung. Dieses Multithreading stellt nicht nur Multithreading in der Softwareimplementierung dar, sondern erfordert auch den Einsatz von Multithreading-Technologie in der Hardware.
Der Fokus von Multicore-Betriebssystemen liegt auf der Prozesszuordnung und -planung. Bei der Prozesszuweisung werden Prozesse angemessenen physischen Kernen zugewiesen, da verschiedene Kerne unterschiedliche gemeinsame Nutzung und historische Betriebsbedingungen haben. Einige physische Kerne können den Second-Level-Cache gemeinsam nutzen, während andere unabhängig sind. Wenn ein Prozess mit Datenfreigabe einem Kern mit einem gemeinsam genutzten sekundären Cache zugewiesen wird, wird die Leistung erheblich verbessert, andernfalls kann die Leistung beeinträchtigt werden.
Die Prozessplanung umfasst Themen wie Echtzeitleistung und Lastausgleich. Aktuelle Forschungsthemen konzentrieren sich hauptsächlich auf die folgenden Aspekte:
Die Situation, wenn Multiprozess und Multithread auf dem CPU-Kern ausgeführt werden, ist wie folgt:
Wenn jeder CPU-Kern einen Prozess ausführt, besteht keine Notwendigkeit, den Kontext beim Wechseln zwischen CPU-Kernen zu berücksichtigen, da die Ressourcen jedes Prozesses unabhängig sind
Wenn jeder CPU-Kern einen Thread ausführt, müssen die Threads manchmal Ressourcen gemeinsam nutzen, sodass diese Ressourcen von einem Kern der CPU auf einen anderen kopiert werden müssen, was zusätzlichen Overhead verursacht
Binden Sie den Prozess so, dass er auf dem CPU-Kern ausgeführt wird
Überprüfen Sie, wie viele Kerne die CPU hat
Verwenden Sie cat /proc/cpuinfo, um CPU-Informationen anzuzeigen, die folgenden zwei Informationen:Prozessor, geben Sie an, welcher CPU-Prozessor
ist
CPU-Kerne, geben Sie die Anzahl der Kerne jedes Prozessors an
Sie können auch den Systemaufruf sysconf verwenden, um die Anzahl der CPU-Kerne zu ermitteln:
#include int sysconf(_SC_NPROCESSORS_CONF);/* 返回系统可以使用的核数,但是其值会包括系统中禁用的核的数目,因 此该值并不代表当前系统中可用的核数 */ int sysconf(_SC_NPROCESSORS_ONLN);/* 返回值真正的代表了系统当前可用的核数 */ /* 以下两个函数与上述类似 */ #include int get_nprocs_conf (void);/* 可用核数 */ int get_nprocs (void);/* 真正的反映了当前可用核数 */
Verwenden Sie den Taskset-Befehl
Prozess-PID abrufen
-> % 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
-> % taskset -p 2726 pid 2726's current affinity mask: 3
Der angegebene Prozess wird auf CPU1 ausgeführt
-> % taskset -pc 1 2726 pid 2726's current affinity list: 0,1 pid 2726's new affinity list: 1
Zu diesem Zeitpunkt ist die Anwendung zur Ausführung an cpu1 gebunden, wie unten gezeigt:
-> % taskset -p 2726 pid 2726's current affinity mask: 2
#启动时绑定到第二个cpu -> % taskset -c 1 ./dgram_servr& [1] 3011 #查看确认绑定情况 -> % taskset -p 3011 pid 3011's current affinity mask: 2
Verwenden Sie den Systemaufruf sched_setaffinity
sched_setaffinity kann einen Prozess an eine bestimmte CPU binden.
#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所指向的结构中 */
#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; }
-> % ./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
Binden Sie Threads zur Ausführung auf dem CPU-Kern
Binden Sie Threads mit der Funktion pthread_setaffinity_np an den CPU-Kern. Ihr Prototyp ist wie folgt definiert:
#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.
Beispiele
#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); }
-> % ./a.out Set returned by pthread_getaffinity_np() contained: CPU 0 CPU 1
Das obige ist der detaillierte Inhalt vonDer Dual-Core-CPU-Killer lässt Ihren Linux-Prozess schneller laufen!. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!