[011] practicar pitón fuerza interna: piscinas de proceso Python y grupos de subprocesos Detallada

Yo, por el grupo de subprocesos \ piscinas de procesos

1.1 El concepto de la piscina

  • La piscina es una colección de recursos, este conjunto de recursos fue completamente creado e inicializado cuando se inicia el programa, que también se conoce como 静态资源分配.

  • llamadas de programa y asignar los recursos del sistema (memoria), incluso después de la liberación de los recursos tiene que gastar un montón de tiempo. Si el recurso correspondiente en el "pool", el programa recibe de la piscina y puesto en libertad sin asignación dinámica, sin duda, mucho más rápido.

  • instalaciones de la piscina es equivalente al servidor de aplicaciones para administrar los recursos del sistema, evita las frecuentes visitas al núcleo del servidor.

El propósito principal de la piscina es el concepto de reutilización: Deje que el hilo o proceso puede ser utilizado varias veces en el ciclo de vida. Reduce la creación y el proceso de crear una sobrecarga de hilo, "espacio de tiempo" para mejorar el rendimiento del programa. Las reglas no deben ser reutilizados, pero es la razón principal de los programadores utilizar en el grupo de aplicaciones.

División 1.2 de la piscina

La piscina se puede dividir en múltiples, son comunes 内存池, 进程池, 线程池y 连接池.

La diferencia entre el 1,3 y el proceso del grupo de grupo de subprocesos

grupo de subprocesos y el proceso de la piscina similar al uso constante. Los principales diferentes escenarios de aplicación, para determinar si las operaciones del programa o la piscina proceso de grupo de subprocesos, procedimientos tienen que mirar el negocio.

negocios uso recomendado
IO-intensiva Leer el archivo, la lectura y las conexiones de red frecuentes. subprocesos
De cálculo intensivo Consumen una gran cantidad de las matemáticas de la CPU y las operaciones lógicas, es decir, aquí estamos hablando de la computación paralela. inventario de procesos, hacer uso de las ventajas del hardware de varios núcleos

1.5 para crear un inventario de procesos (proceso)

  • Crear un inventario de procesos, colocado en un número adecuado de los procesos en la piscina
  • La cola de espera de la piscina proceso de evento de la adhesión
  • Constantemente a la espera de un evento mediante el proceso de la piscina proceso hasta que todos los eventos terminados
  • Después de procesar todos los eventos, piscina proceso cerrado, el proceso de recuperación de la piscina

En segundo lugar, las dos formas de crear un grupo de subprocesos \ inventario de procesos

De Python3.2python biblioteca estándar proporciona módulo concurrente y multiprocesamiento para nosotros para preparar el correspondiente asíncrono código multi-hilo / multi-proceso.

2,1 diferencia concurrente y multiprocesamiento

Los dos módulos diferencia esencial no es muy grande, y algunos son sólo ligeramente diferentes vías llamadas. En primer lugar algunos de multiprocesamiento, después de ahí concurrent.futures, que apareció sólo para reducir la dificultad de escribir código, que reducir el costo de aprendizaje.

Este blog es principalmente para introducir módulo basado concurrent.futures.

Tres, módulo de concurrent.futures

Introducción 3.1 Módulo

Desde el Python3.2 comenzando, biblioteca estándar Python proporciona concurrent.futures módulo que proporciona tarea asincrónica para comenzar interfaz de alto nivel para los desarrolladores.

módulo base concurrent.futures es Exectuor , el ejecutor es una clase abstracta, no se puede utilizar directamente. Sin embargo, dos subclases ThreadPoolExecutor y ProcessPoolExecutor que proporciona es muy útil, como su nombre indica se utilizan para crear tanto el código como las piscinas grupo de subprocesos proceso. Vamos a hacer las tareas correspondientes directamente en la piscina grupo de subprocesos / proceso, no es necesario que preocuparse por problemas de mantenimiento cola estancamiento, grupo de subprocesos / piscina ayudará automáticamente a procesar la programación.

3.2 Executor.submit crear un inventario de procesos / hilo

piscina de proceso / hilo, solamente un número fijo de hilos / procesos, designados por max_workers.

  • El ejecutor de tareas envía a la cola de tareas por Executor.submit, el retorno a un objeto futuro.

  • Futuro es un modo de diseño concurrente común. Un futuro objeto representa una serie de resultados que no están listos (completo), después de que el "futuro" en algún listo, puede llegar a los resultados.

  • El trabajo está programado para realizar diversas trabajadores. Pero tenga cuidado:

    • Una vez que se ejecuta una tarea que se ha completado la ejecución, siempre ocupará el trabajador!
    • Si no hay suficientes trabajadores, otras tareas se han estado esperando! Ejecutor, por tanto, no es adecuado para tareas en tiempo real.

Crear un ejemplo simple inventario de procesos:

'''
Executor.submit 创建进程实例
'''

from concurrent.futures import ProcessPoolExecutor
import time,  os

# 打印信息
def print_info(n):
    print("%s: 开启" % os.getpid())
    time.sleep(1)
    return n**2

if __name__ == '__main__':
    pool = ProcessPoolExecutor(4)  # 开启四个进程

    for i in range(10):  # 执行10个任务
        pool.submit(print_info, i)

Cuatro, concurrent.futures módulo común

concurrent.futures API contiene tres partes:

4.1 Módulo Ejecutor

Es decir, dos actuadores API

  • Constructor: Parámetros principales son max_workers, especifica el tamaño del grupo de subprocesos (o el número de trabajadores)

  • submit(fn, *args, **kwargs)  
    # 返回一个 future,用于获取结果
    
    • La función fn tarea enviada al actuador, y kwargs args parámetro fn es necesaria.
  • map(func, *iterables, timeout=None, chunksize=1)
    # 返回一个 futures 的迭代器
    
    • Cuando la tarea es la misma, sólo los parámetros son diferentes, puede utilizar este método en lugar de enviar. Cada elemento corresponde a un conjunto de parámetros iterables de func.
  • shutdown(wait=True): Cerrar el actuador, que normalmente se utiliza con el Administrador apaga automáticamente.

4.2 módulos futuros

Después de la tarea se presenta al actuador volverá a un futuro

función efecto
future.result (timout = None) El método más común devuelve los resultados de la tarea. Si la tarea no ha terminado todavía, este método ha estado esperando!
  • tiempo de espera especificado de tiempo de espera, sin límite de tiempo de espera es Ninguno.

  • exception(timeout=None): Dada la tarea tirado. Y el resultado (), como se esperaba para el final de la tarea.

  • cancel(): Cancelar esta tarea

  • add_done_callback(fn): El futuro es completa, ejecutar fn(future).

  • running(): Se está ejecutando

  • done(): Future llegando a su fin, boolean

  • ... Ver la documentación oficial

4.3 Otro módulo de función práctica

función función
concurrent.futures.as_completed (fs, timeout = Ninguno) fs de espera (futuros) iterables en el futuro finalización
  • Una vez en un futuro fs completado, la función devuelve inmediatamente al futuro.
  • Este enfoque, el futuro de cada vuelta, siempre el primero para completar el futuro. En lugar de esperar a que la tarea 1, Tarea 2 a esperar ...
  • A menudo a través for future in as_completed(fs):del uso de esta función.
función función
concurrent.futures.wait (fs, timeout = Ninguno, return_when = ALL_COMPLETED) Esperar hasta que sucedió return_when especificado, o tiempo de espera
  • return_when Hay tres opciones: ALL_COMPLETED (fs futuros se ha completado), FIRST__COMPLETED (FS cualquiera de una finalización futura) no FIRST_EXCEPTION (una tarea emite una excepción)

En quinto lugar, el ejemplo de programa

5.1 Ejemplos de piscina proceso

from concurrent.futures import ProcessPoolExecutor
import os,time,random



def task(n):
    print('%s is running' %os.getpid())
    time.sleep(2)
    return n**2


if __name__ == '__main__':
    p = ProcessPoolExecutor()  #不填则默认为cpu的个数
    # print(os.cpu_count())   # 获取本地cpu个数

    l=[]
    start=time.time()
    for i in range(10):
        obj=p.submit(task,i)   #submit()方法返回的是一个future实例,要得到结果需要用obj.result()
        l.append(obj)

    p.shutdown()  #类似用from multiprocessing import Pool实现进程池中的close及join一起的作用
    print('='*30)
    # print([obj for obj in l])
    print([obj.result() for obj in l])
    print(time.time()-start)

    #上面方法也可写成下面的方法
    # start = time.time()
    # with ProcessPoolExecutor() as p:   #类似打开文件,可省去.shutdown()
    #     future_tasks = [p.submit(task, i) for i in range(10)]
    # print('=' * 30)
    # print([obj.result() for obj in future_tasks])
    # print(time.time() - start)

complementario :

Después de 1, finalizó la implementación del método de apagado (), a continuación, ejecutar presentará error

2, concurrent.futures multiprocesamiento basan. Piscina realización, por lo que de hecho es más de grupo de subprocesos directamente / proceso a ser un poco más lenta. Sino que proporciona una API más conveniente y simple.

ejemplos de la piscina 5,2 hilo

from concurrent.futures import ThreadPoolExecutor
import threading
import os, time


def task(n):
    print('%s:%s is running' % (threading.currentThread().getName(),os.getpid()))
    time.sleep(2)
    return n**2


if __name__ == '__main__':
    p = ThreadPoolExecutor()   # 不填则默认为cpu的个数*5
    l = []
    start = time.time()
    for i in range(10): # 开启10个任务
        obj = p.submit(task,i)
        l.append(obj)
    p.shutdown()
    print('='*30)
    print([obj.result() for obj in l])
    print(time.time()-start)

Ejemplos de síncrona y asíncrona 5,3

  • llamada sincrónica: presentar completar tareas, como por ejemplo in situ, tales como la ejecución de la tarea, la tarea de obtener el valor de retorno, con el fin de continuar con la siguiente línea de código, lo que resulta en una ejecución del programa en serie
  • llamada asincrónica: presentar completar la tarea, no en su lugar y así sucesivamente, el programa se ejecuta en paralelo, la tarea se ha completado devuelve una instancia, debe obtener a través de un método especial

grupo de subprocesos y el proceso por defecto de la piscina se llevan a cabo de forma asíncrona. Esto puede maximizar la velocidad de ejecución del programa.

Ejemplos de devoluciones de llamada asincrónicas

# 异步调用

def counter(x):
    time.sleep(1)
    return x**x

if __name__ == '__main__':
    start = time.time()
    p = ProcessPoolExecutor(4)
    l = []
    for i in range(1, 10):
        results = p.submit(counter, i)
        l.append(results)

    print([i.result() for i in l])
    p.shutdown()
    print('花费时间:', time.time() - start)
    print('运算结束!')
    
'''
结果:
	[1, 4, 27, 256, 3125, 46656, 823543, 16777216, 387420489]
	花费时间: 3.282705783843994
	运算结束!
'''

ejemplo de devolución de llamada síncrona

# 同步调用
def counter(x):
    time.sleep(1)
    return x**x


if __name__ == '__main__':
    start = time.time()
    p = ProcessPoolExecutor(4)
    l = []
    for i in range(1, 10):
        res = p.submit(counter, i).result()
        l.append(res)

    print([i for i in l])
    p.shutdown(wait=True)
    print('花费时间:', time.time() - start)
    print('运算结束!')
    
    '''
    结果:
    [1, 4, 27, 256, 3125, 46656, 823543, 16777216, 387420489]
	花费时间: 9.329394340515137
	运算结束!
    '''

5.4 ejemplos de uso Executor.map

from concurrent import futures
import time


def test(x):
    time.sleep(2)
    return time.ctime(), x

if __name__ == '__main__':

    with futures.ThreadPoolExecutor() as T:
        for i in T.map(test,[1,2,3]):
            print(i)

    # 等同于下面注释代码
    # with futures.ThreadPoolExecutor() as T:
    #     l = []
    #     for i in [1, 2, 3]:
    #         obj = T.submit(test, i)
    #         l.append(obj)
    # 
    # print([i.result() for i in l])
    
    
    '''
    结果:
    ('Tue Apr  7 00:12:17 2020', 1)
	('Tue Apr  7 00:12:17 2020', 2)
	('Tue Apr  7 00:12:17 2020', 3)
    
    '''

Publicado 75 artículos originales · ganado elogios 82 · Vistas a 10000 +

Supongo que te gusta

Origin blog.csdn.net/weixin_42444693/article/details/105355073
Recomendado
Clasificación