Colección de citas famosas - Consulta de diccionarios - Un artículo que le brindará una comprensión profunda de los subprocesos y procesos de Python.

Un artículo que le brindará una comprensión profunda de los subprocesos y procesos de Python.

El uso del módulo de subprocesos en Python le permite ejecutar diferentes partes de su programa simultáneamente y simplificar su diseño. Si ha comenzado a usar Python y desea utilizar subprocesos para acelerar sus programas, espero que este tutorial le resulte útil.

Hilos y procesos

¿Qué es un proceso?

Un proceso es una unidad independiente en el sistema que se utiliza para la asignación y programación de recursos. Un proceso es una actividad de programa con alguna funcionalidad independiente que se ejecuta en un conjunto de datos. Un proceso es una unidad independiente en el sistema que se utiliza para la asignación y programación de recursos. Cada proceso tiene su propio espacio de memoria independiente y diferentes procesos se comunican a través de la comunicación entre procesos. Debido a que los procesos son relativamente pesados ​​y ocupan memoria independiente, la sobrecarga de conmutación (pila, registros, memoria virtual, identificadores de archivos, etc.) es relativamente pequeña. ) es relativamente grande, pero relativamente estable y seguro.

¿Qué es un hilo?

La unidad básica de programación y envío de CPU. Un hilo es la entidad de un proceso, y un proceso es la unidad básica de programación y envío de CPU. Es una unidad básica que es más pequeña que un proceso y puede ejecutarse de forma independiente. El subproceso en sí básicamente no tiene recursos del sistema, excepto algunos recursos necesarios (como un contador de programa, un conjunto de registros y una pila) para ejecutarse, pero puede compartir todos los recursos que posee el proceso con otros subprocesos que pertenecen al mismo. mismo proceso. La comunicación entre subprocesos disfruta principalmente de la memoria a través de * * * *, con un cambio de contexto rápido y una baja sobrecarga de recursos, pero no es lo suficientemente estable en comparación con los procesos y es fácil perder datos.

Diagrama de proceso y hilo

La diferencia entre hilo y proceso:

Proceso

En la vida real, muchas cosas suceden al mismo tiempo escena del tiempo. Por ejemplo, conducir con las manos y los pies juntos mientras conduce, cantar y bailar y hablar por teléfono mientras come. Imagínese si un líder nos llamara mientras estábamos comiendo, definitivamente responderíamos de inmediato. Pero si contestas el teléfono o devuelves una llamada después de cenar, probablemente te despidan.

Nota:

El concepto de multitarea

¿Qué quieres decir con multitarea? En pocas palabras, un sistema operativo puede ejecutar múltiples tareas al mismo tiempo. Por ejemplo, utiliza un navegador para navegar por Internet, escuchar MP3 y utilizar Word para ponerse al día con la tarea. Se trata de multitarea, es decir, tener al menos tres tareas ejecutándose simultáneamente. Hay muchas tareas que se ejecutan silenciosamente en segundo plano al mismo tiempo, pero no aparecen en el escritorio.

Las CPU multinúcleo son muy comunes hoy en día, pero en el pasado incluso las CPU de un solo núcleo podían realizar múltiples tareas. Dado que la CPU ejecuta código de forma secuencial, ¿cómo realiza una CPU de un solo núcleo la multitarea?

La respuesta es que el sistema operativo ejecuta cada tarea alternativamente: la tarea 1 se ejecuta durante 0,01 segundos, cambia a la tarea 2 durante 0,01 segundos, luego cambia a la tarea 3 durante 0,01 segundos, y así sucesivamente. En la superficie, cada tarea se ejecuta alternativamente, pero debido a que la CPU es tan rápida, sentimos como si todas las tareas se ejecutaran al mismo tiempo.

La verdadera ejecución paralela de múltiples tareas solo se puede lograr en CPU de múltiples núcleos, pero dado que la cantidad de tareas excede con creces la cantidad de núcleos de CPU, el sistema operativo programará automáticamente muchas tareas para cada núcleo en secuencia. . De hecho, ¡la CPU se ejecuta demasiado rápido! De esa manera no sentimos que estamos haciendo turnos.

Paralelismo y Concurrencia

Paralelismo

Paralelismo: se refiere a dos o más eventos (o subprocesos) que ocurren al mismo tiempo, lo que significa que se ejecutan diferentes eventos o subprocesos. simultáneamente en diferentes recursos de CPU (múltiples núcleos).

Características

Concurrencia (concurrencia)

Se refiere a la multiplexación de una CPU física (o varias CPU) entre varios programas (o subprocesos de CPU física). La concurrencia obliga a varios usuarios a utilizar recursos físicos limitados para aumentar la eficiencia.

Características

Procesamiento múltiple. Módulo de proceso

El módulo de proceso es un módulo que crea procesos. Utilice este módulo para crear procesos.

Sintaxis: proceso ([grupo[, destino[, nombre[, args[, kwargs]]])

Los objetos instanciados por esta clase representan tareas en el subproceso (no comenzado todavía).

Nota: 1. Los parámetros deben especificarse mediante palabras clave; 2. El parámetro de posición especificado por args se pasa a la función de destino en forma de ancestro y debe tener una coma.

Introducción del parámetro:

No utilice el parámetro Grupo:, el valor predeterminado es Ninguno.

Destino: Indica el objeto que llama, es decir, la tarea que realizará el proceso hijo.

Args: Indica el parámetro posicional antecesor de la llamada.

Kwargs: Diccionario que representa el objeto que llama. Por ejemplo, kwargs = {'nombre':jack, 'edad':18}.

Nombre: El nombre del subproceso.

Código:

Además del método anterior para iniciar el proceso, existe otro método para iniciar el proceso heredando el proceso:

A través de lo anterior investigación, Hacemos todo lo posible para implementar la naturaleza asincrónica del programa para que se puedan procesar múltiples tareas al mismo tiempo en varios procesos al mismo tiempo. Una vez activados, se salen de control. Aunque la programación concurrente nos permite aprovechar al máximo los recursos IO, también nos trae nuevos problemas.

Cuando varios procesos utilizan el mismo recurso de datos, puede producirse seguridad o desorden en los datos. Podemos considerar el bloqueo. Tomemos como ejemplo la captura de tickets simulada para ver la importancia de la seguridad de los datos.

El bloqueo puede garantizar que cuando varios procesos modifican los mismos datos, solo se pueda modificar una tarea al mismo tiempo, es decir, modificación en serie. El bloqueo sacrifica la velocidad pero garantiza la seguridad de los datos.

Así que será mejor que encontremos una solución que pueda encargarse de ambos: 1. alta eficiencia (múltiples procesos * * * comparten datos en una memoria) 2. y nos ayude a lidiar con los problemas de bloqueo.

Mecanismo de comunicación IPC basado en mensajes proporcionado por el módulo multiprocesamiento: cola y canalización. Tanto las colas como las canalizaciones almacenan datos en la memoria y se basan en (tubería + bloqueo), lo que puede liberarnos de problemas complejos de bloqueo. Deberíamos tratar de evitar el uso de * * * para disfrutar de los datos, usar el paso de mensajes y las colas tanto como sea posible para evitar lidiar con problemas complejos de sincronización y bloqueo; cuando aumenta la cantidad de procesos, generalmente podemos obtener una mejor escalabilidad (ampliar el contenido más adelante). .

Subprocesos

Módulo de subprocesos de Python

Python proporciona varios módulos para la programación multiproceso, incluidos subprocesos, subprocesos y colas. Los subprocesos y el módulo de subprocesos permiten a los programadores crear y administrar subprocesos. El módulo de subprocesos proporciona soporte básico para subprocesos y bloqueos, mientras que los subprocesos proporcionan capacidades de gestión de subprocesos más avanzadas y potentes. El módulo de cola permite a los usuarios crear una estructura de datos de cola para compartir datos entre múltiples subprocesos.

Python crea y ejecuta subprocesos

Creación de código de subproceso

1. Método 1:

2.

Los procesos y los subprocesos son formas de lograr la multitarea. Por ejemplo, se pueden ejecutar múltiples QQ (procesos) en la misma computadora al mismo tiempo, y un QQ puede abrir múltiples ventanas de chat (hilos). Compartir recursos * * *: Un proceso no puede * * compartir recursos, mientras que un hilo * * * disfruta del espacio de direcciones y otros recursos del proceso al que pertenece. Al mismo tiempo, el hilo tiene su propia pila y puntero de pila. Por lo tanto, todos los subprocesos de un proceso comparten variables globales, pero los cambios en las variables globales realizados por varios subprocesos pueden causar confusión en las variables.

Demostración de código:

Los resultados son los siguientes:

Lo primero que hay que dejar claro es que GIL no es una característica de Python, sino que implementa la funcionalidad de Python. analizador (CPython) un concepto introducido en ese momento. Al igual que C++ es un conjunto de estándares de lenguaje (gramática), pero diferentes compiladores pueden compilarlo en código ejecutable. El mismo fragmento de código se puede ejecutar en diferentes entornos de ejecución de Python, como CPython, PyPy y Psyco (JPython no tiene un GIL).

Entonces, ¿qué es el GIL en la implementación de CPython? El nombre completo de GIL es Global Interpreter Lock. Para evitar engaños, echemos un vistazo a la explicación oficial:

El significado principal es:

Por lo tanto, el intérprete es en realidad. protegido por el bloqueo global del intérprete. Esto garantiza que solo se esté ejecutando un subproceso de Python en cualquier momento. En un entorno de subprocesos múltiples, la máquina virtual Python se ejecuta de la siguiente manera:

Debido a la existencia de GIL, el subproceso múltiple de Python no puede denominarse subproceso múltiple estricto. Porque en subprocesos múltiples, cada subproceso debe obtener el GIL primero durante la ejecución para garantizar que solo se ejecute un subproceso al mismo tiempo.

Debido a la existencia de GIL, incluso los subprocesos múltiples en realidad solo pueden garantizar que un subproceso pueda ejecutarse al mismo tiempo. Dado que la eficiencia de subprocesos múltiples y de subproceso único es diferente, ¿por qué utilizar subprocesos múltiples?

Debido a que las computadoras anteriores eran básicamente CPU de un solo núcleo, casi no había diferencia entre subprocesos múltiples y subprocesos únicos. Sin embargo, debido al rápido desarrollo de las computadoras, las computadoras actuales son casi todas CPU de múltiples núcleos, con al menos dos núcleos. En este momento surge la diferencia: a través de los casos anteriores, ya sabemos que incluso en una CPU multinúcleo, solo se ejecuta un hilo al mismo tiempo. Esto no solo deja de aprovechar las ventajas del multinúcleo. CPU, pero también cada subproceso se alternará en la ejecución de múltiples CPU, lo que dará como resultado diferentes CPU. En otras palabras, la razón es que solo hay un bloqueo GIL en un proceso. Cuando se ejecutan varios subprocesos, habrá competencia interna por el bloqueo GIL. Esto hará que la CPU espere cuando un subproceso no capture el bloqueo. entonces los recursos de la CPU de múltiples núcleos no se pueden utilizar razonablemente.

Sin embargo, cuando se utilizan subprocesos múltiples para rastrear el contenido de una página web, cuando se encuentra un bloqueo de IO, el subproceso de ejecución liberará temporalmente el bloqueo GIL y luego otros subprocesos utilizarán este tiempo de intervalo para ejecutar su propio código. por lo que el subproceso múltiple es mejor que el rastreo de un solo subproceso, por lo que aún necesitamos usar subprocesos múltiples.

El impacto de GIL en programas Python multiproceso

El rendimiento del programa se ve afectado por las limitaciones de la CPU y los programas intensivos de E/S, entonces, ¿qué son la CPU y la E/S? ¿O programas intensivos?

Computación intensiva: requiere una gran cantidad de cálculos numéricos, como cientos de millones de cálculos digitales, cálculo de pi, decodificación de videos de alta definición, etc. Aunque este tipo de tarea computacionalmente intensiva también se puede completar mediante multitarea, el tiempo principal invertido es durante el tiempo de cambio de tarea, cuando la eficiencia de la CPU en la ejecución de tareas es relativamente baja.

IO-intensivo: Las tareas que involucran solicitudes de red (time.sleep()) y IO de disco son tareas intensivas en IO, que se caracterizan por consumir poca CPU y pasar la mayor parte del tiempo esperando a que se completen las operaciones de IO (Porque la velocidad de IO es mucho menor que la velocidad de la CPU y la memoria). Para tareas intensivas de IO, cuantas más tareas, mayor será la eficiencia de la CPU, pero existen limitaciones.

Por supuesto, para evitar el impacto de GIL en nuestro programa, también podemos usar bloqueos de subprocesos.

Cerraduras y candados. Bloquear

Mecanismos de bloqueo de recursos de uso común * * *: Bloqueo, RLock, Semphore, Condición, etc. Compartamos brevemente Lock y RLock.

Bloqueo

Se caracteriza por una velocidad de ejecución lenta, pero garantiza la seguridad de los datos.

Locke

El uso inadecuado de los códigos de bloqueo puede provocar un punto muerto.

¿Qué es un punto muerto?

Punto muerto: cuando el hilo A tiene el bloqueo exclusivo A e intenta adquirir el bloqueo exclusivo B, cuando el hilo B tiene el bloqueo exclusivo B e intenta adquirir el bloqueo exclusivo A, cuando dos hilos AB se retienen entre sí Cuando se alcanza el bloqueo requerido se alcanza, se produce un bloqueo, lo que se denomina interbloqueo. Un punto muerto se refiere a un punto muerto causado por múltiples procesos que compiten por los recursos. Sin fuerzas externas, estos procesos no podrán avanzar.

Por lo tanto, en términos de diseño del sistema y programación de procesos, se debe prestar atención a cómo evitar que se establezcan estas cuatro condiciones necesarias y cómo determinar un algoritmo de asignación de recursos razonable para evitar que los procesos ocupen permanentemente los recursos del sistema.

Código de interbloqueo

Comunicación entre subprocesos de Python

Si cada subproceso hace lo suyo, entonces realmente no necesita comunicarse y el código es muy simple . Pero esto generalmente no es posible, al menos el hilo debe comunicarse con el hilo principal; de lo contrario, no se podrán recuperar los resultados del cálculo y otro contenido. En realidad, es mucho más complicado, ya que varios subprocesos necesitan intercambiar datos para obtener los resultados de ejecución correctos.

La cola en Python es una cola de mensajes que proporciona un mecanismo de comunicación entre subprocesos. Se le cambió el nombre a Cola en python3. Se proporcionan varias colas de bloqueo debajo del bloque del módulo de cola, que se utilizan principalmente para implementar la comunicación de subprocesos.

En el módulo de colas, hay tres categorías principales, que representan tres tipos de colas. Su principal diferencia es la diferencia entre entrar y salir de la cola.

Demostración de código simple

En este punto, el código se bloqueará porque la cola está llena.

En este momento, puede agregar tiempo de espera después de la cuarta cola. put('Apple'), y se convertirá en cola ('Apple', timeout=1). Si todavía está lleno después de esperar 1 segundo, se generará y detectará una excepción.

De manera similar, si la cola está vacía, la cola se bloqueará de forma predeterminada si no se puede obtener el contenido. Si no está bloqueado, puede usar queue.get_nowait().

Después de dominar las características de las colas de bloqueo de colas, puede utilizar las colas para implementar la comunicación de subprocesos en programas posteriores.

Demostremos un productor y un consumidor. Por supuesto, puede haber más de uno.

Al utilizar el módulo de cola, se puede llevar a cabo la comunicación entre subprocesos y garantizar la seguridad de los subprocesos.

Coroutines

Cornergy, también conocidos como microhilos, fibras. El nombre en inglés es Coroutine.

La condensación es otra forma de implementar la multitarea en Python, pero ocupa unidades de ejecución (entendidas como recursos necesarios) más pequeñas que los subprocesos. ¿Por qué es una unidad de ejecución? Porque viene con el contexto de la CPU. De esta manera, podremos pasar de un proceso a otro cuando sea el momento adecuado. Siempre que el contexto de la CPU se guarde o restaure durante el proceso, el programa aún puede ejecutarse.

Entendimiento popular: una función en un hilo puede guardar algunas variables temporales y otra información de la función actual en cualquier lugar, y luego cambiar a otra función para su ejecución. Tenga en cuenta que no se realiza llamando a una función; la cantidad de veces que se cambia y cuándo cambiar a la función original queda en manos del desarrollador.

Al implementar la multitarea, el cambio de subprocesos es mucho más sencillo que guardar y restaurar el contexto de la CPU desde el nivel del sistema. Para que el sistema operativo ejecute el programa de manera eficiente, cada subproceso tiene su propio caché y otros datos, y el sistema operativo también lo ayudará a restaurar estos datos. Por lo tanto, el cambio de subprocesos consume mucho rendimiento. Sin embargo, el proceso de conmutación sólo opera en el contexto de la CPU, por lo que el sistema puede soportar millones de cambios por segundo.

Greenlet y Gevent

Para utilizar mejor la corrutina para completar tareas múltiples, además de usar el rendimiento nativo para simular la corrutina, Python también tiene el módulo greenlet y el módulo gevent, lo que facilita la implementación. corrutinas más fáciles y más eficientes.

Aunque Greenlet implementa la coordinación, necesitamos cambiar manualmente, lo cual es demasiado problemático. gevent es un módulo más potente que greenlet y puede cambiar de tarea automáticamente.

El principio es que, por ejemplo, cuando un greenlet encuentra una operación IO (entrada y salida, como operaciones de red y archivos), cambiará automáticamente a otros greenlets y esperará hasta que se complete la operación IO. y luego, en el momento adecuado, retroceda y continúe la ejecución.

Simule operaciones que consumen mucho tiempo:

Si hay operaciones que consumen mucho tiempo, también puede reemplazarlas con sus propios módulos implementados en gevent, y luego deberá parchearlos.

¡Utilice Xiecheng para completar un sencillo código de rastreo de información sobre viviendas de segunda mano!

El siguiente artículo es de la columna Python escrita por Song Song.

Enlace del artículo:/s/2r3_ipU3HjdA5VnqSHjUnQ