[Linux] Vincula el proceso / subproceso a un núcleo de CPU específico para ejecutar

Tabla de contenido

Primero, el propósito

Dos, enlace de comando

1. Compruebe la situación de la encuadernación.

2. Vinculación al inicio

3. Encuadernación después del inicio

Tres, enlace de código

Vincular el proceso para que se ejecute en el núcleo de la CPU

Enlazar subprocesos para que se ejecuten en el núcleo de la CPU

para resumir


Primero, el propósito

Cuando un proceso requiere una mayor eficiencia operativa, es necesario considerar vincularlo a un núcleo separado para su ejecución a fin de reducir la sobrecarga causada por la programación en diferentes núcleos.

Después de que un proceso / subproceso está vinculado a un núcleo de CPU específico, el proceso siempre se ejecutará en este núcleo y el sistema operativo no lo programará para otros núcleos. Pero el núcleo vinculado aún puede estar programado para ejecutar otras aplicaciones.

Dos, enlace de comando

1. Compruebe la situación de la encuadernación.

Ver el estado de enlace actual del pid del proceso

conjunto de tareas -p pid

Máscara de afinidad actual de pid 2726: 6

El número decimal mostrado 6 -> convertido a binario es 110, cada 1 corresponde a una CPU, por lo que el proceso se ejecuta en # 1, # 2cpu (la CPU comienza desde 0)

 

2. Vinculación al inicio

# Enlace a la segunda CPU al inicio

conjunto de tareas -c 1 ./dgram_servr&

# Enlace a la primera CPU, la tercera CPU al inicio

conjunto de tareas -c 0,2 ./dgram_servr&

(La CPU comienza desde 0)

3. Encuadernación después del inicio

2.1 Vincular núcleos directamente según la cantidad de CPU

taskset -cp 1,2,5,11 9865 Vincula el proceso 9864 a los núcleos # 1, # 2, # 5, # 11.

taskset -cp 1,2,5-11 9865 Vincula el proceso 9864 a los núcleos # 1, # 2, # 5 ~ # 11.

Tenga en cuenta que la etiqueta de cpu comienza desde 0, por lo que cpu1 significa la segunda cpu (la etiqueta de la primera cpu es 0).


taskset -cp cpu-list pid
donde cpu-list es una lista de cpu digitalizada, comenzando desde 1. Se pueden conectar varias CPU discretas mediante comas y se pueden utilizar conexiones continuas de corta duración, como 1, 2, 5-11, etc.

 

2.2 Núcleos de unión en forma de máscara

conjunto de tareas -p máscara pid


De acuerdo con la forma binaria, desde el bit más bajo al bit más alto, representa los núcleos # 1, # 2, ..., #n de la CPU física.
Por ejemplo: 0x00000001 representa el núcleo 0 de la CPU y 0x00000003 representa los núcleos 0 y 3 de la CPU.
Cabe señalar que el núcleo de la CPU que se indica en la máscara no existe necesariamente. Por ejemplo, 0x00000400 teóricamente representa el décimo núcleo de la CPU, pero este núcleo no existe necesariamente en una computadora real. Además, si intentamos vincular un núcleo que no existe físicamente a un proceso, se devolverá un error. El comando de enlace principal en forma de máscara es:
taskset -p mask pid
 

Tres, enlace de código

(Original: https://blog.csdn.net/guotianqing/article/details/80958281 )

Vincular el proceso para que se ejecute en el núcleo de la CPU

Compruebe cuántos núcleos tiene la CPU

Utilice para cat /proc/cpuinfover la información de la CPU, la siguiente información:

  • procesador, especifique el número de procesadores de cpu
  • núcleos de cpu, que indica la cantidad de núcleos por procesador

También puede usar la llamada al sistema sysconf para obtener el número de núcleos de CPU:

#include <unistd.h>

int sysconf(_SC_NPROCESSORS_CONF);/* 返回系统可以使用的核数,但是其值会包括系统中禁用的核的数目,因 此该值并不代表当前系统中可用的核数 */
int sysconf(_SC_NPROCESSORS_ONLN);/* 返回值真正的代表了系统当前可用的核数 */

/* 以下两个函数与上述类似 */
#include <sys/sysinfo.h>

int get_nprocs_conf (void);/* 可用核数 */
int get_nprocs (void);/* 真正的反映了当前可用核数 */

Estoy usando una máquina virtual con 2 procesadores, y cada procesador tiene solo un núcleo, lo que equivale a un procesador con dos núcleos.

 

Utilice la llamada al sistema sched_setaffinity

sched_setaffinity puede vincular un proceso a una CPU específica.

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

/* 设置进程号为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所指向的结构中 */
  • Ejemplo
#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;  //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 < num; 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;i<num;i++)
         {
                   tid[i] = i;  //每个线程必须有个tid[i]
                   pthread_create(&thread[i],NULL,threadFun,(void*)&tid[i]);
         }
         for(i=0; i< num; i++)
         {
                   pthread_join(thread[i],NULL);//等待所有的线程结束,线程为死循环所以CTRL+C结束
         }
         return 0;
}
  •  
  • resultado de la operación
-> % ./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

Enlazar subprocesos para que se ejecuten en el núcleo de la CPU

  • Enlaza el subproceso al núcleo de la CPU mediante la función pthread_setaffinity_np, y su prototipo se define de la siguiente manera:
#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include <pthread.h>

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.
  • El significado de cada parámetro es similar a sched_setaffinity.

  • Ejemplo

#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); } 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 < 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");

    /* 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 < CPU_SETSIZE; j++)
        if (CPU_ISSET(j, &cpuset))
            printf("    CPU %d\n", j);

    exit(EXIT_SUCCESS);
}
  • resultado de la operación
-> % ./a.out 
Set returned by pthread_getaffinity_np() contained:
    CPU 0
    CPU 1

para resumir

Hay muchas formas de asignar procesos / subprocesos a núcleos de CPU específicos para que se ejecuten.

En un uso específico, es necesario decidir qué método utilizar de acuerdo con el escenario de uso y los requisitos. En mi opinión, el paso importante es determinar primero si se debe utilizar el método de unión de hilos al núcleo.


[Material de referencia]
Introducción a la tecnología de múltiples núcleos al método de soporte del sistema operativo para procesadores de múltiples
núcleos Enlace de subprocesos CPU core-sched_setaffinity
PTHREAD_SETAFFINITY_NP (3) Manual del programador de Linux PTHREAD_SETAFFINITY_NP (3)

Supongo que te gusta

Origin blog.csdn.net/bandaoyu/article/details/113700713
Recomendado
Clasificación