web-dev-qa-db-fra.com

Pool de multiprocesseurs avec une boucle for

J'ai une liste de fichiers que je passe dans une boucle for et je fais tout un tas de fonctions. Quelle est la façon la plus simple de paralléliser cela? Je ne suis pas sûr de pouvoir trouver cette chose exacte n'importe où et je pense que mon implémentation actuelle est incorrecte car je n'ai vu qu'un seul fichier en cours d'exécution. D'après certaines lectures que j'ai faites, je pense que cela devrait être un cas parfaitement parallèle.

L'ancien code ressemble à ceci:

import pandas as pd
filenames = ['file1.csv', 'file2.csv', 'file3.csv', 'file4.csv']
for file in filenames:
    file1 = pd.read_csv(file)
    print('running ' + str(file))
    a = function1(file1)
    b = function2(a)
    c = function3(b)
    for d in range(1,6):
            e = function4(c, d)
    c.to_csv('output.csv')

(incorrectement) Code parallélisé

import pandas as pd
from multiprocessing import Pool
filenames = ['file1.csv', 'file2.csv', 'file3.csv', 'file4.csv']
def multip(filenames):
    file1 = pd.read_csv(file)
    print('running ' + str(file))
    a = function1(file1)
    b = function2(a)
    c = function3(b)
    for d in range(1,6):
            e = function4(c, d)
    c.to_csv('output.csv')

if __name__ == '__main__'
    pool = Pool(processes=4)
    runstuff = pool.map(multip(filenames))

Ce que je (pense) je veux faire est d'avoir n fichier être calculé par cœur (peut-être par processus?). J'ai aussi fait

multiprocessing.cpu_count()

et ai obtenu 8 (j'ai un quad donc c'est probablement en tenant compte des threads). Étant donné que j'ai environ 10 fichiers au total, si je peux mettre un fichier par processus pour accélérer les choses, ce serait génial! J'espère que les 2 fichiers restants trouveront également un processus une fois les processus du premier tour terminés.

Modifier: pour plus de clarté, les fonctions (c'est-à-dire fonction1, fonction2, etc.) alimentent également d'autres fonctions (c'est-à-dire fonction1a, fonction1b) à l'intérieur de leurs fichiers respectifs. J'appelle la fonction 1 à l'aide d'une instruction d'importation.

J'obtiens l'erreur suivante:

OSError: Expected file path name or file-like object, got <class 'list'> type

Apparemment, je n'aime pas qu'on me passe une liste, mais je ne veux pas faire de noms de fichiers [0] dans l'instruction if car cela n'exécute qu'un seul fichier

8
Monty
import multiprocessing
names = ['file1.csv', 'file2.csv']
def multip(name):
     [do stuff here]

if __name__ == '__main__':
    #use one less process to be a little more stable
    p = multiprocessing.Pool(processes = multiprocessing.cpu_count()-1)
    #timing it...
    start = time.time()
    for file in names:
    p.apply_async(multip, [file])

    p.close()
    p.join()
    print("Complete")
    end = time.time()
    print('total time (s)= ' + str(end-start))

EDIT: remplacez le if__name __ == '____main___' par celui-ci. Cela exécute tous les fichiers:

if __name__ == '__main__':

    p = Pool(processes = len(names))
    start = time.time()
    async_result = p.map_async(multip, names)
    p.close()
    p.join()
    print("Complete")
    end = time.time()
    print('total time (s)= ' + str(end-start))
9
Monty