Enlace el proceso / hilo a un núcleo de CPU específico y ejecútelo en Linux

Transferencia desde: https://blog.csdn.net/guotianqing/article/details/80958281

Descripción general
Ahora todo el mundo está utilizando básicamente CPU de múltiples núcleos, generalmente 4 núcleos. Por lo general, las aplicaciones son administradas por el sistema operativo en tiempo de ejecución. El sistema operativo programa procesos de aplicación para ejecutarse en diferentes núcleos a su vez.

Para aplicaciones ordinarias, el mecanismo de programación predeterminado del sistema operativo no es un problema. Sin embargo, cuando un proceso necesita una mayor eficiencia operativa, es necesario considerar ejecutarlo en un núcleo separado para 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 enlazado aún puede estar programado para ejecutar otras aplicaciones.

Programación del sistema operativo de CPU de varios núcleos
Actualmente, tanto Windows como Linux admiten la administración de programación de CPU de múltiples núcleos.

El núcleo del desarrollo de software en un entorno multinúcleo es el desarrollo multiproceso. Este subprocesamiento múltiple no solo representa subprocesos múltiples en la implementación de software, sino que también requiere tecnología de subprocesos múltiples en hardware.

El enfoque de los sistemas operativos multinúcleo está en la asignación y programación de procesos. La asignación de procesos asigna procesos a núcleos físicos razonables, porque los diferentes núcleos tienen diferentes condiciones de uso compartido e histórico. Algunos núcleos físicos pueden compartir el caché secundario, mientras que otros son independientes. Si el proceso con el intercambio de datos se asigna al núcleo con caché secundaria compartida, el rendimiento mejorará enormemente; de ​​lo contrario, puede afectar el rendimiento.

La programación del proceso implicará problemas de equilibrio de carga y otros problemas en tiempo real. Los puntos críticos de investigación actuales se centran principalmente en los siguientes aspectos:

El desarrollo paralelo de las tareas
dependientes del tiempo del diseño
del programa de asignación de múltiples procesos y programación de
errores de caché compartiendo el
problema de acceso de consistencia
comunicación entre procesos
núcleo de
multiprocesador competencia de recursos internos competencia multiproceso y multiproceso que se ejecuta en el núcleo de la CPU son los siguientes:

Cuando cada núcleo de la CPU ejecuta un proceso, dado que los recursos de cada proceso son independientes, no es necesario tener en cuenta el contexto al cambiar entre los núcleos de la CPU. Cuando
cada núcleo de la CPU ejecuta un subproceso, a veces los subprocesos necesitan compartir recursos, por lo que estos El recurso debe copiarse de un núcleo de la CPU a otro núcleo, lo que causará una sobrecarga adicional.
Vincula el proceso para que se ejecute en el núcleo de la CPU.
Visualiza la CPU. Hay varios núcleos.
Usa cat / proc / cpuinfo para ver la información de la CPU. La siguiente información:

procesador, que indica el número de
núcleos de CPU de la CPU, que indica el número de núcleos de cada procesador.
También puede utilizar la llamada al sistema sysconf para obtener el número de núcleos de CPU:

#include <unistd.h>

int sysconf (_SC_NPROCESSORS_CONF); / * devuelve el número de núcleos que puede utilizar el sistema, pero su valor incluirá el número de núcleos deshabilitados en el sistema, por lo que este valor no representa el número de núcleos disponibles en el sistema actual * /
int sysconf (_SC_NPROCESSORS_ONLN); / * El valor de retorno realmente representa el número de núcleos disponibles actualmente en el sistema * /

/ * Las siguientes dos funciones son similares a las anteriores * /
#include <sys / sysinfo.h>

int get_nprocs_conf (void); / * Núcleos disponibles * /
int get_nprocs (void); / * Realmente refleja los núcleos disponibles actuales * /

Uso una máquina virtual, hay 2 procesadores, cada procesador tiene solo uno El núcleo es equivalente a un procesador con dos núcleos.

Use la instrucción del conjunto de tareas para
obtener el proceso 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 para

ver dónde se está ejecutando actualmente el proceso En la CPU
->% taskset -p 2726
máscara de afinidad actual de pid 2726: 3

muestra que el número decimal 3 convertido a 2 hexadecimal es el más bajo dos es 1, cada 1 corresponde a una CPU, por lo que el proceso se ejecuta en 2 CPU.

El proceso especificado se ejecuta en cpu1
->% taskset -pc 1 2726
lista de afinidad actual de pid 2726: 0,1
nueva lista de afinidad de pid 2726: 1

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

Hasta ahora, la aplicación está destinada a ejecutarse en cpu1, ver de la siguiente manera:

->% taskset -p 2726
pid 2726 máscara de afinidad actual: 2

Vincular CPU al iniciar el programa
# Vincular a la segunda CPU al iniciar
->% taskset -c 1 ./dgram_servr&
[1] 3011


#Compruebe para confirmar el estado de enlace ->% taskset -p 3011
pid 3011 máscara de afinidad actual: 2

Utilice el sistema sched_setaffinity, llame a
sched_setaffinity para vincular un proceso a una CPU específica.

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

/ * Establezca el proceso con el ID de proceso de pid para que se ejecute en la CPU establecida por la máscara
* El segundo parámetro cpusetsize es la longitud del número especificado por la máscara
* Generalmente establecido en sizeof (cpu_set_t)

* Si el valor de pid es 0, significa que el proceso especificado es el proceso actual
* /
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); / * Obtenga la máscara de bits de CPU del proceso indicado por pid, y devuelva la máscara a la estructura apuntada por 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; // El número de núcleos en la CPU
void * threadFun (void * arg) // arg Pase la etiqueta del hilo (definida por usted mismo)
{
cpu_set_t mask; // La colección de núcleos de CPU
cpu_set_t get; // Obtenga la CPU
int en la colección * a = (int *) arg;
int i;

printf ("el subproceso es:% d \ n", * a); // Muestra el número de subprocesos
CPU_ZERO (& mask); // Establece
CPU_SET (* a, & mask); // Establece el valor de afinidad
if (sched_setaffinity (0, sizeof (mask), & mask) == -1) // Establecer la afinidad de la CPU del hilo
{
printf ("advertencia: no se pudo establecer la afinidad de la CPU, continuando ... \ n");
}

CPU_ZERO (& get);
if (sched_getaffinity (0, sizeof (get), & get) == -1) // Obtener afinidad de CPU de subproceso
{
printf ("advertencia: no puede obtener afinidad de subproceso, continuando ... \ n");
}
for (i = 0; i <num; i ++)
{
if (CPU_ISSET (i, & get)) // determina con qué CPU el hilo tiene afinidad con
{
printf ("este hilo% d está ejecutando el procesador:% d \ n", i, i);
}
}

devuelve 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 ("el número de núcleos [% d] es mayor que THREAD_MAX_NUM [% d]! \ N", num, THREAD_MAX_NUM);
volver -1;
}
printf ("el sistema tiene% i procesador (es). \ n", num);

for (i = 0; i <num; i ++)
{
tid [i] = i; // Cada hilo debe tener un tid [i]
pthread_create (& thread [i], NULL, threadFun, (void *) & tid [i ]);
}
for (i = 0; i <num; i ++)
{
pthread_join (thread [i], NULL); // Espera a que todos los hilos terminen, el hilo es un bucle sin fin para que CTRL + C termine
}
devuelva 0;
}

Ejecutar Resultado
->% ./a.out el
sistema tiene 2 procesadores.
El subproceso es: 0
el subproceso es: 1
este subproceso 0 está ejecutando el procesador: 0
este subproceso 1 está ejecutando el procesador: 1

une el subproceso al núcleo de la CPU
Use la función pthread_setaffinity_np para ejecutar el hilo de enlace al núcleo de la CPU. Su prototipo se define de la siguiente manera:
#define _GNU_SOURCE / * Vea 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 y vincule con -pthread.

El significado de cada parámetro es similar a sched_setaffinity.

Ejemplos

#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); salir (EXIT_FAILURE); } while (0)

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

hilo = pthread_self ();

/ * Establecer máscara de afinidad para incluir CPU de 0 a 7 * /

CPU_ZERO (& cpuset);
para (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");

/ * Compruebe la máscara de afinidad real asignada al hilo * /

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

printf ("Conjunto devuelto por pthread_getaffinity_np () contenido: \ n");
para (j = 0; j <CPU_SETSIZE; j ++)
if (CPU_ISSET (j, & cpuset))
printf ("CPU% d \ n", j);

exit (EXIT_SUCCESS);
}

Resultado de ejecución
->% ./a.out
Conjunto devuelto por pthread_getaffinity_np () contenido:
CPU 0
CPU 1

Resumen
Hay muchas formas de asignar procesos / subprocesos a núcleos de CPU específicos para la operación.

En uso específico, es necesario decidir qué método usar de acuerdo con el escenario de uso y los requisitos. Personalmente, creo que el paso importante es determinar si se debe usar el método de unir hilos al núcleo.

[Referencia]
Introducción de sistemas operativos tecnología multi-núcleo método para procesadores de múltiples núcleos apoyado
CPU núcleo -sched_setaffinity hilo-bound
pthread_setaffinity_np (3) del Programador de Linux ManualPTHREAD_SETAFFINITY_NP
(3) ----------------
Declaración de derechos de autor: Este artículo es un artículo original del blogger de CSDN "guotianqing", que sigue el acuerdo de derechos de autor CC 4.0 BY-SA. Adjunte el enlace de origen original y esta declaración al volver a imprimir.
Enlace original: https://blog.csdn.net/guotianqing/java/article/details/80958281

Supongo que te gusta

Origin www.cnblogs.com/sky-heaven/p/12753284.html
Recomendado
Clasificación