¿Buen ejemplo de implementación de multiprocesamiento?

Estoy tratando de convertir uno de mis progtwigs para usar multiprocesamiento, preferiblemente los grupos de multiprocesamiento, ya que parecen más simples de hacer. En un nivel alto, el proceso está creando una serie de parches de imágenes y luego pasándolos a la GPU para la detección de objetos. La CPU y la parte de la GPU toman aproximadamente 4 segundos cada una, sin embargo, la CPU tiene 8 núcleos y no tiene que esperar a la GPU porque no se realizan más operaciones a los datos después de que pasa la GPU.

Aquí hay un diagtwig de cómo imagino que esto debería funcionar: diagrama multiproceso

Para ayudar en el proceso, me gustaría una demostración con una versión de alto nivel de mi implementación. Digamos que estamos recorriendo una lista de imágenes en una carpeta que tiene 10 imágenes. Cambiamos el tamaño de las imágenes 4 a la vez. Luego los convertimos a blanco y negro dos a la vez, podemos tomar la conversión como la parte de GPU del proceso aquí. Aquí es cómo se vería el código:

def im_resize(im, num1, num2): return im.resize((num1, num2), Image.ANTIALIAS) def convert_bw(im): return im.convert('L') def read_images(path): imlist = [] for pathAndFileName in glob.iglob(os.path.join(path, "*")): if pathAndFileName.endswith(tuple([".jpg", ".JPG"])): imlist.append(Image.open(pathAndFileName)) return imlist img_list = read_images("path/to/images/") final_img_list = [] for image in img_list: # Resize needs to run concurrently on 4 processes so that the next img_tmp is always ready to go for convert img_tmp = im_resize(image, 100, 100) # Convert is limited, need to run on 2 processes img_tmp = convert_bw(img_tmp) final_img_list.append(img_tmp) 

La razón de la cantidad específica de procesos y esto se debe a las métricas de rendimiento del sistema, esto es lo que reducirá el tiempo de ejecución. Solo quiero asegurarme de que la GPU no tiene que estar esperando a que la CPU termine de procesar las imágenes, y quiero tener una cola constante llena de imágenes preprocesadas listas para que la GPU se ejecute. Preferiblemente, me gustaría mantener un tamaño máximo en la cola de aproximadamente 4-10 imágenes preprocesadas. Si ustedes pueden ayudarme a ilustrar cómo lograría esto con este ejemplo simplificado, estoy seguro de que puedo encontrar la manera de traducirlo en lo que necesito para el mío.

¡Gracias!

    Aquí hay un bash tentativo de implementar lo que quieres:

     ... # Mapping functions can only take one arg, we provide tuple def img_resize_splat(a): img_resize(*a) if __name__=="__main__": # Make a CPU pool and a GPU pool cpu = Pool(4) gpu = Pool(2) # Hopefully this returns an iterable, and not a list with all images read into memory img_list = read_images("path/to/images/") # I'm assuming you want images to be processed as soon as ready, order doesn't matter resized = cpu.imap_unordered(img_resize_splat, ((img, 100, 100) for img in img_list)) converted = gpu.imap_unordered(convert_bw, resized) # This is an iterable with your results, slurp them up one at a time for bw_img in converted: # do something