El programa Python se congela cuando la llamada de multiprocesamiento sigue a una llamada secuencial

Resuelto proprit asked hace 7 meses • 0 respuestas

Encontré un problema extraño con un programa Python que procesaba imágenes con la pyvipsbiblioteca. Aquí hay una versión simplificada de mi problema.

Intento crear una matriz numpy (que proviene de ceros en mi ejemplo simple) varias veces (2 veces en el ejemplo).

Cuando lo hago secuencialmente, todo está bien. Cuando uso el multiprocessingmódulo, también funciona como debería. Pero durante mis pruebas noté que el programa se congela cuando realizo estas dos ejecuciones rápidamente, una tras otra . De ahí el programa a continuación. Cuando lo ejecuto, se congela antes del primer "paso 3" en la parte de multiprocesamiento.

Creo que está vinculado a un mecanismo de recolección de basura, pero aquí estoy perdido.

Estoy usando Python 3.11.3 y pyvips 2.2.2 (con vips-8.15.1). Utilizo Spyder con su consola IPython en una máquina Linux (una distribución basada en Ubuntu 22.04).

import multiprocessing
import numpy as np
import pyvips

def myfunction(useless):
    print("step 1")
    image = pyvips.Image.new_from_array(np.zeros((8, 8, 3)), interpretation="rgb")
    print("step 2")
    res = np.asarray(image)
    print("step 3")
    return res

def main(nbpool):
    srcrange = range(2)
    if nbpool == 0:
        res = list()
        for srcid in srcrange:
            res.append(myfunction(srcid))
        return res
    else:
        pool = multiprocessing.Pool(nbpool)
        return pool.map(myfunction, srcrange)

if __name__ == "__main__":
    res1 = main(0)
    print("Now with multiprocessing")
    res2 = main(1)
proprit avatar Feb 16 '24 16:02 proprit
Aceptado

El problema que está experimentando puede deberse al hecho de que el módulo de multiprocesamiento no funciona bien con las notebooks IPython o Jupyter. Esto se debe a que estos entornos no son seguros para la bifurcación y el multiprocesamiento depende de la capacidad de bifurcar de forma segura el intérprete de Python.

Una forma de resolver potencialmente este problema es utilizar multiprocessing.set_start_method('spawn')al principio de su secuencia de comandos. Esto hará que el módulo de multiprocesamiento cree un nuevo intérprete de Python para cada proceso hijo, lo que puede evitar problemas con la bifurcación en entornos que no son seguros para la bifurcación.

Así es como puedes modificar tu script:

import multiprocessing
import numpy as np
import pyvips

# Set the start method for multiprocessing
multiprocessing.set_start_method('spawn')

def myfunction(useless):
    print("step 1")
    image = pyvips.Image.new_from_array(np.zeros((8, 8, 3)), interpretation="rgb")
    print("step 2")
    res = np.asarray(image)
    print("step 3")
    return res

def main(nbpool):
    srcrange = range(2)
    if nbpool == 0:
        res = list()
        for srcid in srcrange:
            res.append(myfunction(srcid))
        return res
    else:
        pool = multiprocessing.Pool(nbpool)
        return pool.map(myfunction, srcrange)

if __name__ == "__main__":
    res1 = main(0)
    print("Now with multiprocessing")
    res2 = main(1)

Tenga en cuenta que el uso del método de inicio 'spawn' puede hacer que su programa se ejecute más lento, ya que se debe crear un nuevo intérprete de Python para cada proceso hijo. Sin embargo, puede ayudar a evitar problemas de bifurcación en entornos como portátiles IPython o Jupyter.

msalam avatar Feb 16 '2024 10:02 msalam