Sobre el uso de procesos, hilos, corutinas en Python

Descripción

Recientemente, se desarrolló una plataforma de programación de inteligencia artificial en Python. Debido a que el lado de la computación usa python + tensorflow, el lado de la programación también eligió Python para la seguridad heterogénea del lenguaje, lo que implica un problema de rendimiento concurrente de programación. Debido a las necesidades comerciales, debe ser capaz de lograr La demanda de tráfico de más de 1000 qps tiene un gran desafío para el rendimiento del servicio de programación de Python.
La arquitectura específica se muestra a continuación:
Sobre el uso de procesos, hilos, corutinas en Python

Suplemento:
El python utilizado en la arquitectura es cpython, y el lenguaje para interpretar y ejecutar no es jpython ni pypython. El entorno comunitario de cpython es relativamente activo. Muchos kits de desarrollo se implementan bajo cpython, como tensorflow, numpy, etc. utilizados en el módulo de cálculo del proyecto. Etc.
La siguiente discusión es lenguaje cpython.

El problema

Los datos actualmente servicios de computación cada servicio es responsable de analizar los datos de tipo, y no han tenido problemas, y el cálculo ventana acoplable puede ser programado para la otra máquina, de manera temporal no constituye una actuación cuellos de botella
hay que hacer más de 1000 veces por segundo en un cliente de servidor de RPC de negocios programadas Una vez, el negocio incluye la programación de rpc una vez que los datos originales, y luego la programación de rpc al servicio de computación para el cálculo y la devolución de los resultados y luego el almacenamiento asíncrono, en este momento cuando se usa python para programar rpc io usando diferentes métodos tendrán un rendimiento diferente.

Implementación y transformación del proyecto de la siguiente manera

Ejecución secuencial

Se ejecutarán secuencialmente más de 1,000 servicios. Si el programa Python tiene solo un proceso y otros procesos en la máquina no se apoderarán de los recursos de la CPU con él (cualquier proceso en cualquier idioma solo puede usar un núcleo de CPU al mismo tiempo sin subprocesos). Incluso si un proceso abre un hilo, solo puede usar como máximo un núcleo de CPU al mismo tiempo, o usar 0, que está en un estado bloqueado), todos los bloques de código de negocios se ejecutan en secuencia, y el código interno solo se puede ejecutar en secuencia con un núcleo de CPU. Obviamente no es aconsejable, cualquier CPU donde necesite esperar está allí para esperar la ejecución, después de ejecutar una tarea para reciclar y ejecutar la próxima vez, el rendimiento es bajo y cada negocio es serial.

Ejecución multiproceso

with concurrent.futures.ThreadPoolExecutor(max_workers=MAX_WOKERS) as executor:
        for (classify, sensorLists) in classifySensors.items():
            print(f'\ncurrent classify: {classify},  current sensors list: {sensorLists}')
            try:
                executor.submit(worker,classify,sensorLists)
            except Exception as e:
                print(e)

Primero, permítanme hablar brevemente sobre cómo el núcleo de la CPU del sistema operativo programa multiproceso / multiproceso. La programación del trabajo multiproceso / multiproceso se programa en la capa del kernel del sistema operativo. El sistema operativo depende de la prioridad del hilo / proceso o Si el segmento de tiempo se usa o se bloquea para determinar si se debe cambiar el segmento de tiempo de la CPU a otros procesos / subprocesos, algunos procesos / subprocesos también pueden adelantarse a los recursos de la CPU de acuerdo con el mecanismo de bloqueo, etc. Si la CPU está inactiva, entonces el subproceso / proceso actual O bien, siempre puede ocupar un núcleo de CPU y luego analizar cómo el subproceso en el proceso actual de Python está programado para ejecutarse por la CPU. Si la máquina actual tiene múltiples núcleos y no hay otras tareas ocupadas, el proceso del servicio de programación actual usa múltiples subprocesos / El grupo de subprocesos programa un trabajo comercial de subprocesos múltiples. Debido al lenguaje interpretado por Python, la ejecución de cada subproceso en el proceso actual de Python es la siguiente:
1. Adquirir bloqueo GIL
2. Adquirir segmento de tiempo de CPU
3. Ejecutar código, esperar el bloqueo (suspensión o io bloqueo o tiempo de funcionamiento) o la otra porción de tiempo de preferencia roscan CPU de
interruptor de bloqueo 4. GIL de liberación a su ejecución del hilo, repita desde el paso 1.
Se puede ver que un hilo en Python quiere ejecutarse, primero debe obtener un bloqueo GIL, solo hay un bloqueo GIL en un proceso de Python.
Por lo tanto, en el caso de los subprocesos múltiples de Python, debido a las características del lenguaje que se interpreta, hay un bloqueo GIL adicional, y varios subprocesos de un proceso solo pueden ocupar como máximo un recurso de CPU al mismo tiempo, pero un subproceso puede cambiar a otro subproceso mientras espera. Para ejecutarse, no es necesario esperar a que el subproceso anterior io complete el serial y luego pasar al siguiente subproceso, por lo que el subproceso múltiple puede tener efectos concurrentes en este momento, pero no puede ocupar múltiples núcleos de CPU al mismo tiempo, y los subprocesos no se pueden ejecutar en paralelo, solo en una espera En el momento de otra ejecución concurrente, para lograr un efecto concurrente, qps es mejor que la ejecución en serie.

Ejecución de rutina

Para procesos y subprocesos, hay un núcleo para la programación, existe el concepto de segmentos de tiempo de CPU, programación preventiva (con múltiples algoritmos de programación), para las rutinas (subprocesos a nivel de usuario), esto es transparente para el núcleo, que es el sistema No sé si hay una rutina. Está completamente programada por el propio programa del usuario. Debido a que está controlada por el programa del usuario, es difícil obligar al control de la CPU a cambiar a otros procesos / subprocesos como la programación preventiva. En general, solo se puede realizar una programación colaborativa, y otras corutinas solo se pueden ejecutar después de que la rutina transfiera su control.
Python usa aysnc para definir el método de rutina, la operación que consume mucho tiempo en el método define la palabra clave de espera (esto es definido por el usuario), cuando la ejecución llega a esperar, puede cambiar a otras corridas para ejecutar, por lo que en este proceso de Python Si el método de rutina en este núcleo de CPU necesita llamarse varias veces, dará el intervalo de tiempo de CPU a otras corutinas cuando sea necesario a través del método Ctrip aysnc + esperar definido por el usuario, que también logra el efecto de concurrencia. La sobrecarga de conmutación es relativamente pequeña y no involucra el mantenimiento del núcleo del sistema y los hilos de mantenimiento, guarda la escena y otras operaciones, por lo que si la rutina utilizada en Python es buena, el efecto de concurrencia será mejor que el subprocesamiento múltiple. Puede consultar el código fuente de implementación del decorador de rutina gen.coroutine subyacente de tornado para comprender la implementación subyacente de la rutina:
Referencia:
https://note.youdao.com/ynoteshare1/index.html?id=e78ce975a872b2bdd37c7bae116790b8&type=note

El iterador y el siguiente del generador cambian la capa inferior de la rutina de Python, y el evento se realiza mediante el grupo de selección proporcionado por el sistema operativo. Sin embargo, la implementación de rutina de Python solo se puede cambiar en el proceso actual o en el subproceso actual. Al mismo tiempo, solo se puede usar un núcleo de CPU al mismo tiempo, y no puede lograr paralelismo. Solo puede lograr concurrencia. Si se usa bien, el efecto de concurrencia es mejor que el multiproceso de Python.

Ejecución multiproceso

En primer lugar, el método de programación del sistema operativo para los subprocesos / procesos mencionados anteriormente. Si un subproceso en Python desea ejecutarse, primero debe obtener un bloqueo GIL. Solo hay un bloqueo GIL en un proceso Python. Luego, en el lenguaje de ejecución de interpretación python, se puede llevar a cabo el diseño de modo multiproceso. Cuando el proceso se está ejecutando, una parte del espacio de memoria y el núcleo de CPU independiente se pueden aplicar por separado. El espacio de proceso tiene una cierta independencia, por lo que cada proceso tiene su propio bloqueo GIL independiente. , Python multiproceso puede lograr un efecto paralelo, el efecto de qps es mucho mejor que la rutina y el subprocesamiento múltiple.

Multiproceso + corutina

Los multiprocesos pueden hacer un uso completo de la cantidad de núcleos de CPU, las corutinas también pueden extraer la tasa de utilización de un solo núcleo y la depuración en modo multiproceso + corutina puede tener diferentes efectos. El método de rutina generalmente se usa en aplicaciones de uso intensivo de io, el método de multiproceso se usa en escenarios computacionalmente intensivos, y el método de multiproceso + corutina se usa en escenarios intensivos en IO y computacionalmente intensivo. En mi proyecto, cada tarea requiere dos io, un cálculo, aunque el cálculo ya está en el proceso de Python en una ventana acoplada separada, pero el tiempo de cálculo para cada tarea aún es serial, también afectará El efecto general de qps, por lo que es mejor usar multiproceso + corutina en este momento. El negocio de un tipo de dispositivo IOT se coloca en un proceso independiente, y el negocio de múltiples tipos de dispositivos IOT se puede ejecutar en paralelo. Múltiples dispositivos en este tipo de dispositivo iot Puede ser concurrencia a través de las rutinas, el efecto qps general será bueno.

vaya a Dafa Goroutine

Esencialmente, la goroutina es una corutina. La diferencia es que Golang encapsula y procesa la programación de la rutina en muchos aspectos, como el tiempo de ejecución y las llamadas al sistema. Cuando encuentra una ejecución larga o realiza una llamada al sistema, transferirá activamente la CPU (P) de la rutina actual para permitir que otra rutina Puede programarse y ejecutarse, es decir, Golang admite corutinas desde el nivel de idioma. Una característica importante de Golang es el soporte nativo para las corutinas desde el nivel del idioma. Agregar la palabra clave go delante de una función o método puede crear una corutina.
La definición de ir es más complicada: más que las corutinas de Python, permite programarlas en diferentes subprocesos del sistema operativo.
Entonces, si desea perseguir el rendimiento, el servidor de programación se refactoriza con golang.
ir material de referencia:
"Estudio de Golang observa dos"
modelo de programación de GMP de libro electrónico de Golang https://blog.csdn.net/qq_37858332/article/details/100689667
Explicación detallada de la rutina de Golang https://blog.csdn.net/weixin_30416497/ artículo / detalles / 96665770

Transformación distribuida

Todos los métodos anteriores se modifican a partir de la capacidad de concurrencia del nodo único del servidor de planificación, pero si los requisitos de rendimiento no se pueden cumplir bajo ninguna circunstancia y se mejora el rendimiento de un único servidor, entonces se debe llevar a cabo la transformación distribuida. La transformación distribuida del nodo informático es relativamente simple. Se envía directamente a la misma máquina en k8s. La dificultad radica en el servidor de despacho. El servidor de despacho es similar a la solicitud del cliente y la distribución de rpc io. El modo actual es: despachar cliente de servicio desde el cliente En la estructura del número de memoria, tome la información del nodo de servicio-> nodos conectados directamente para realizar solicitudes de servicio.Si desea llevar a cabo una transformación distribuida, debe dividir el negocio en múltiples clientes de servicios de programación para llevar a cabo la carga de solicitudes y distribución rpc io, o De acuerdo con la dimensión comercial, divida algunos tipos de dispositivos iot a través de un cliente de servicio de programación y otras partes de dispositivos iot a través de otros clientes de servicio de programación; o agilice el cliente de servicio de programación en un distribuidor de solicitud sin estado, Puede desplegar múltiples, siempre que la puerta de enlace esté predeterminada Defina las reglas de distribución de enrutamiento y envíe solicitudes rpc io al servidor correcto. Las dos diferencias son:
una es: múltiples clientes de servicios de programación (lógica de enrutamiento de distribución comercial en este cliente) -> múltiples servicios informáticos,
otra: múltiples distribuidores de solicitudes sin estado (sin estado, sin ninguna Lógica de enrutamiento de distribución comercial) -> Puerta de enlace de enrutamiento comercial-> Múltiples servicios informáticos El
primer cliente de servicio de programación posible carga diferentes configuraciones, es decir, la lógica de configuración de enrutamiento de distribución comercial cargada es diferente, la segunda no tiene estado El distribuidor de solicitudes es el mismo, pero debe mantener una puerta de enlace de enrutamiento (dependiendo de qué rpc se use, hay una puerta de enlace oficial como grpc y una puerta de enlace opcional Nginx, puede agregar dinámicamente la configuración de enrutamiento a la puerta de enlace, y luego reescribirla automáticamente Configuración, recarga) La
transformación distribuida se puede completar como se describe anteriormente, transformarse en múltiples clientes de servicios de programación o múltiples distribuidores de solicitudes sin estado + una puerta de enlace de enrutamiento empresarial, por supuesto, ambos modos requieren un zk o etcd para el registro del servicio y el servicio Se descubre que varios clientes o distribuidores obtienen directamente la información de recursos del servidor informático correspondiente de zk o etc. El modo de transformación específico es el siguiente:
El primero:
Sobre el uso de procesos, hilos, corutinas en Python

El segundo tipo:

Sobre el uso de procesos, hilos, corutinas en Python

Resumen

1. En Python, un proceso tiene múltiples subprocesos. A lo sumo, solo puede usar un núcleo al mismo tiempo. Cuando usa corutinas, solo puede usar un núcleo al mismo tiempo.
2. El multiproceso de Python puede usar múltiples núcleos de CPU, un pythonf Es mejor ejecutar procesos de procesamiento para ejecutar diferentes servicios en el sistema de servicio; de lo contrario, no se puede utilizar el rendimiento de la CPU multinúcleo y no se puede lograr la capacidad de concurrencia del sistema de servicio en sí.
3. Otros lenguajes como java, go Un proceso puede usar múltiples núcleos al mismo tiempo cuando se abren múltiples hilos o múltiples corutinas. El lenguaje de go está inherentemente provisto de atributos de rutina y puede programarse en diferentes hilos del sistema operativo. Corutina
4. La transformación del rendimiento del servicio mejora el rendimiento concurrente de un solo nodo. Cuando se mejora el rendimiento, se realizan pruebas de estrés en varias etapas para identificar cuellos de botella del rendimiento y se apunta a la mejora del rendimiento, o se realiza la transformación del sistema distribuido del sistema y se implementan varios servidores Varios nodos van a la carga para emprender negocios para mejorar la concurrencia, y la distribución a menudo agrega algunos componentes, lo que hace que algunos componentes tengan un solo punto de falla, o la consistencia del servicio, la consistencia de los datos y otros problemas deben considerarse.

Supongo que te gusta

Origin blog.51cto.com/7142665/2486598
Recomendado
Clasificación