Comment booster vos workflows bash avec GNU Parallèle

GNU parallelest un outil de ligne de commande pour exécuter des tâches en parallèle.

parallelest génial et appartient à la boîte à outils de chaque programmeur. Mais j'ai trouvé les documents un peu accablants au début. Heureusement, vous pouvez commencer à être utile parallelavec seulement quelques commandes de base.

Pourquoi est-ce parallelsi utile?

Comparons les exécutions séquentielles et parallèles de la même tâche gourmande en calcul.

Imaginez que vous ayez un dossier de fichiers audio .wav à convertir en .flac:

Ce sont des fichiers assez gros, chacun pèse au moins un gigaoctet.

Nous utiliserons un autre excellent outil de ligne de commande, ffmpeg, pour convertir les fichiers. Voici ce que nous devons exécuter pour chaque fichier.

ffmpeg -i audio1.wav audio1.flac

Écrivons un script pour convertir chacun séquentiellement:

# convert.sh ffmpeg -i audio1.wav audio1.flac ffmpeg -i audio2.wav audio2.flac ffmpeg -i audio3.wav audio3.flac ffmpeg -i audio4.wav audio4.flac ffmpeg -i audio5.wav audio5.flac

Nous pouvons chronométrer l'exécution d'un travail en préfixant timelors de l'appel du script depuis le terminal. timeimprimera le temps réel écoulé pendant l'exécution.

time ./convert.sh

Notre scénario se termine en un peu plus d'une minute.

Pas mal. Mais maintenant, exécutons-le en parallèle!

Nous n'avons rien à changer sur notre script. Avec le -adrapeau, nous pouvons diriger notre script directement dans parallel. parallelexécutera chaque ligne comme une commande distincte.

parallel -a ./convert.sh

En utilisant parallel, notre conversion s'est déroulée un peu plus de la moitié du temps. Agréable!

Avec seulement cinq fichiers, cette différence n'est pas si grave. Mais avec des listes plus grandes et des tâches plus longues, nous pouvons gagner beaucoup de temps avec parallel.

J'ai rencontré parallelen travaillant avec une tâche de traitement de données qui aurait probablement duré une heure ou plus si elle était effectuée de manière séquentielle. Avec parallel, cela n'a pris que quelques minutes.

parallella puissance dépend également de votre ordinateur. L'Intel i7 de mon MacBook Pro n'a que 4 cœurs. Même cette petite tâche les a tous poussés à leur limite:

Les ordinateurs plus puissants peuvent avoir des processeurs avec 8, 16 ou même 32 cœurs, offrant un gain de temps considérable grâce à la parallélisation de vos travaux.

Être utile avec parallel

L'autre grand avantage de parallelest sa brièveté et sa simplicité. Commençons par un mauvais script Python et convertissons-le en un appel propre à parallel.

Voici un script Python pour effectuer notre conversion de fichier audio:

import subprocess path = Path.home()/'my-data-here' for audio_file in list(path.glob('*.wav')): cmd = ['ffmpeg', '-i', str(audio_file), f'{audio_file.name.split(".")[0]}.flac'] subprocess.run(cmd, stdout=subprocess.PIPE)

Yikes! C'est en fait beaucoup de code à penser juste pour convertir certains fichiers. (Cela prend environ 1,2 minutes pour s'exécuter).

Convertissons notre Python en parallel.

Appel d'un script avec parallel -a

parallel -a your-script-here.sh est le joli one-liner que nous avons utilisé ci-dessus pour pipe dans notre script bash.

C'est génial mais vous oblige à écrire le script bash que vous souhaitez exécuter. Dans notre exemple, nous avons écrit encore à chaque appel individuel à ffmpegen convert.sh.

Interpolation de tuyaux et de chaînes avec parallel

Heureusement, parallelnous donne un moyen de supprimer convert.shentièrement.

Voici tout ce que nous devons courir pour accomplir notre conversion:

ls *.wav | parallel ffmpeg -i {} {.}.flac

Décomposons cela.

Nous obtenons une liste de tous les fichiers .wav de notre répertoire avec ls *.wav. Ensuite, nous envoyons |cette liste à ( ) parallel.

Parallel fournit des moyens utiles de faire une interpolation de chaîne, afin que nos chemins de fichiers soient correctement saisis.

Le premier est {}, qui parallelremplace automatiquement par une ligne de notre entrée.

Le deuxième opérateur est {.}, qui entrera une ligne mais avec toutes les extensions de fichier supprimées.

Si nous développions la commande exécutée par parallelpour notre première ligne d'entrée, nous verrions ...

ffmpeg -i audio1.wav audio1.flac

Args avec Parallel

En fin de compte, nous n'avons même pas besoin de canaliser lspour terminer notre tâche. Nous pouvons faire plus simple encore:

parallel ffmpeg -i {} {.}.flac ::: *.wav

Les arguments passés pour parallelse produire après la commande et sont séparés par :::. Dans ce cas, notre argument est *.wav, qui fournira la liste de tous les fichiers .wav de notre répertoire. Ces fichiers deviennent l'entrée pour notre travail ultra-rapide parallel.

Fun fact: parallel was built by Ole Tange and published in 2011. According to him, you can use the tool for research without citing the source paper for the modest fee of 10,000 euros!

Thanks for reading!