2

J'essaye de traiter un fichier en utilisant le noyau unique de mon CPU. Mais je suppose que ce n'est pas suffisant d'utiliser un seul noyau. Au lieu de cela, si j'avais accès aux multiples cœurs de mon système, je pourrais accélérer et accélérer le processus.en utilisant Multi Thread pour le traitement de fichiers en utilisant python3

Mais malheureusement, je sais traiter un fichier en utilisant un seul coeur. Voici ce que je faisais:

data = open('datafile','r',encoding='ascii',errors='ignore') 
for line in data.readlines(): 
    splitted = line.lower().strip().split() 
    check = process(splitted[0],splitted[1]) 
    if check == '': 
     pass 
data.close() 

Je veux savoir comment je peux utiliser la capacité totale de la CPU pour le traitement Teh process() tout en prenant le line séparément et obtenir la sortie comme vous le souhaitez? Même comment je peux éviter l'état de blocage du thread pendant le traitement car cela peut être dangereux pour la sortie du processus.

S'il vous plaît partagez votre point de vue avec moi.

+0

Quelle impasse? L'état d'interblocage nécessite au moins une serrure, vous savez? Maintenant que Python a cette chose appelée GIL, la seule façon d'utiliser plusieurs cœurs est d'utiliser des processus au lieu de threads. Maintenant, le disque parallèle io peut ou non augmenter les performances (en fonction du disque que vous avez), ce que je suggère est d'utiliser 'multiprocesing.Pool' et d'y envoyer des" morceaux "du processus principal pour le traitement parallèle. – freakish

+0

@freakish plonger le fichier dans des morceaux peut perdre des données, ce que je ne veux pas, car il est un peu important de maintenir les données complètes. –

+0

Pourquoi perdrait-il les données? Vous venez de lire ligne après ligne et d'envoyer chaque ligne à un processus enfant. Il n'y a pas de perte de données ici. – freakish

Répondre

1

Tout d'abord: vous avez besoin de plusieurs processus pour utiliser plusieurs cœurs. Pas de discussions. C'est une limitation due à GIL.

Voici maintenant un exemple de la façon dont vous pouvez le mettre en œuvre avec multiprocessing.Pool:

from multiprocessing import Pool, cpu_count 

def process(arg1, arg2): 
    ... 

workers_count = 2*cpu_count()+1 # or whatever you need 
pool = Pool(processes=workers_count) 

with open('datafile','r',encoding='ascii',errors='ignore') as fo: 
    buffer = [] 
    for line in fo: 
     splitted = line.lower().strip().split() 
     buffer.append((splitted[0], splitted[1])) 
     if len(buffer) == workers_count: 
      results = pool.map(process, buffer) 
      buffer = [] 
      # do something with results 
    if buffer: 
     results = pool.map(process, buffer) 
     # do something with results again 

Alors ce qu'il fait, il lit le fichier ligne par ligne et une fois qu'il recueille suffisamment de données qu'il envoie à une piscine multiprocessus et attend pour le traitement parallèle. Notez qu'à moins d'avoir SSD, l'exécution du disque io en parallèle ne fera que détériorer les performances (il ne serait pas non plus trivial de paralléliser les lectures ligne par ligne). Ce que vous devez savoir cependant, c'est que puisque plusieurs processus sont utilisés, vous ne pouvez pas partager la mémoire entre eux, c'est-à-dire que la fonction process ne doit pas lire/écrire dans des variables globales.

+0

Oui, j'ai SSD. Que se passera-t-il si j'utilise la variable globale pour stocker les données temporaires, car il est préférable de les utiliser facilement lors du traitement des données via 'process()'? –

+0

@JafferWilson Si vous utilisez SSD, vous pouvez jouer avec des lectures parallèles, c'est-à-dire en appelant '.read()' dans le pool. Cependant, cela sera très difficile à mettre en œuvre car chaque travailleur devrait savoir où commencer à lire le fichier et combien de lignes il devrait lire. Cela ne semble pas facile à mettre en œuvre. – freakish

+0

@JafferWilson En ce qui concerne le stockage de données temporaires, vous pouvez toujours avoir une variable locale dans la fonction 'process', n'est-ce pas? Le problème se poserait si, par exemple, vous aviez un compteur global que vous incrémentez après chaque appel 'process'. Le partage d'état entre les appels à 'process' ne fonctionnera pas avec plusieurs processus. – freakish