Parallélisation rapide de code (bio)python

, par Stéphane

Comment exécuter facilement un programme plus rapidement sur un ordinateur moderne ?

Voici les commandes rapides pour transformer un programme monotâche en python en programme capable d’utiliser tous les processeurs de votre machine.

Programme exemple monotâche en biopython

Le code simplifié ci-dessous permet de lire l’ensemble des transcrits du transcriptome de Physarum polycephalum autrement connu sous le nom de BLOB, vous pouvez trouver une présentation sur YouTube de ce petit organisme par Audrey DUSSOTOUR : https://www.youtube.com/watch?v=wjzEMIox_a8.

#!/usr/bin/env python3

from Bio import SeqIO

def processTranscrit(identifiant):
   try:
       r = SeqIO.read(f"{identifiant}.fasta", "fasta")
       print(r.id)
   except Exception as e:
       print(f" **** Erreur pour traiter {identifiant} : {e}")

def main():
   proteome = "proteome_physarum.fasta"
  for r in SeqIO.parse(proteome, "fasta"):
       processTranscrit(r.id)

if __name__ == "__main__":
   main()

Ce programme va lire le fichier avec biopython (voir une excellente introduction par Olivier Dameron et Grégory Farrant : https://inria.hal.science/hal-01095475 ), extraire les séquences d’intérêt une par une, puis les traiter avec la fonction processTranscrit qui pour l’exemple ne fait que l’affichage de l’identifiant de la séquence.

Programme parallélisé

Pour paralléliser notre code où pour le moment une boucle monotâche est présente dans la fonction main(), il suffit de faire appel à la bibliothèque multiprocessing de python en début de code :

# Multiprocessing du calcul
# https://docs.python.org/fr/3/library/multiprocessing.html
import multiprocessing as mp
from multiprocessing import Process, Pool, TimeoutError

La boucle de la fonction main() faisant appel à la fonction processTranscrit(identifiant) devient ainsi :

   pool = mp.Pool(mp.cpu_count()/2)
   pool.map(processTranscrit, [r.id for r in SeqIO.parse(proteome, "fasta")])
   pool.close()

Il faut tout d’abord créer un Pool qui va indiquer le nombre de tâches à exécuter, soit le nombre de cœur divisé par deux dans mon cas, pour n’utiliser que les processeurs physiques, ajouter toutes les tâches à réaliser avec la fonction map qui fait appel aux compréhension de listes en python, puis de lancer le calcul avec la méthode close().

Le code s’exécute ainsi en parallèle sur 4 tâches, threads en anglais, sur ma machine, le temps de calcul initial qui dépassait une journée est ainsi descendu à moins de 6 heures...

Pour aller plus loin

Une explication plus complète et en anglais est disponible sur le site https://www.analyticsvidhya.com/blog/2021/04/a-beginners-guide-to-multi-processing-in-python/