Tutoriel : Exécuter une charge de travail parallèle avec Azure Batch à l’aide de l’API Python

Utilisez Azure Batch pour exécuter des programmes de traitement par lots de calcul haute performance (HPC) en parallèle, efficacement et à grande échelle dans Azure. Ce didacticiel vous permet de découvrir un exemple d’exécution Python d’une charge de travail parallèle utilisant Batch. Vous découvrez un workflow d’application Batch courant et comment interagir par programme avec les ressources de stockage et Batch.

  • S’authentifier avec des comptes de stockage et Batch.
  • Charger des fichiers d’entrée sur le stockage.
  • Créer un pool de nœuds de calcul pour exécuter une application.
  • Créer un travail et des tâches pour traiter les fichiers d’entrée.
  • Surveiller l’exécution d’une tâche.
  • Récupérer les fichiers de sortie.

Dans ce tutoriel, vous convertissez des fichiers multimédias MP4 au format MP3, en parallèle, à l’aide de l’outil open source ffmpeg.

Si vous n’avez pas d’abonnement Azure, créez un compte gratuit Azure avant de commencer.

Prérequis

Connexion à Azure

Connectez-vous au portail Azure.

Obtenir les informations d’identification du compte

Dans le cadre de cet exemple, vous devez fournir les informations d’identification de vos comptes Azure Batch et de stockage. Pour obtenir rapidement les informations d’identification nécessaires, dirigez-vous vers le portail Azure. (Vous pouvez aussi les obtenir avec les API Azure ou des outils en ligne de commande.)

  1. Sélectionnez Tous les services>Comptes Batch, puis le nom de votre compte Batch.

  2. Pour voir les informations d’identification Batch, sélectionnez Clés. Copiez les valeurs des champs Compte Batch, URL et Clé d’accès principale dans un éditeur de texte.

  3. Pour voir le nom et les clés du compte de stockage, sélectionnez Compte de stockage. Copiez les valeurs des champs Nom du compte de stockage et Clé1 dans un éditeur de texte.

Télécharger et exécuter l’exemple d’application

Télécharger l’exemple d’application

Téléchargez ou clonez l’exemple d’application à partir de GitHub. Pour cloner le référentiel d’exemple d’application avec un client Git, utilisez la commande suivante :

git clone https://github.com/Azure-Samples/batch-python-ffmpeg-tutorial.git

Naviguez vers le répertoire qui contient le fichier batch_python_tutorial_ffmpeg.py.

Dans votre environnement Python, installez les packages requis à l’aide de pip.

pip install -r requirements.txt

Utilisez un éditeur de code pour ouvrir le fichier config.py. Mettez à jour les chaînes d’identification de compte Batch et de stockage avec les valeurs propres à vos comptes. Par exemple :

_BATCH_ACCOUNT_NAME = 'yourbatchaccount'
_BATCH_ACCOUNT_KEY = 'xxxxxxxxxxxxxxxxE+yXrRvJAqT9BlXwwo1CwF+SwAYOxxxxxxxxxxxxxxxx43pXi/gdiATkvbpLRl3x14pcEQ=='
_BATCH_ACCOUNT_URL = 'https://yourbatchaccount.yourbatchregion.batch.azure.com'
_STORAGE_ACCOUNT_NAME = 'mystorageaccount'
_STORAGE_ACCOUNT_KEY = 'xxxxxxxxxxxxxxxxy4/xxxxxxxxxxxxxxxxfwpbIC5aAWA8wDu+AFXZB827Mt9lybZB1nUcQbQiUrkPtilK5BQ=='

Exécuter l’application

Pour exécuter le script :

python batch_python_tutorial_ffmpeg.py

Lorsque vous exécutez l’exemple d’application, la sortie de la console est identique à ce qui suit. Pendant l’exécution, l’étape Monitoring all tasks for 'Completed' state, timeout in 00:30:00... fait l’objet d’une pause correspondant au démarrage des nœuds de calcul du pool.

Sample start: 11/28/2018 3:20:21 PM

Container [input] created.
Container [output] created.
Uploading file LowPriVMs-1.mp4 to container [input]...
Uploading file LowPriVMs-2.mp4 to container [input]...
Uploading file LowPriVMs-3.mp4 to container [input]...
Uploading file LowPriVMs-4.mp4 to container [input]...
Uploading file LowPriVMs-5.mp4 to container [input]...
Creating pool [LinuxFFmpegPool]...
Creating job [LinuxFFmpegJob]...
Adding 5 tasks to job [LinuxFFmpegJob]...
Monitoring all tasks for 'Completed' state, timeout in 00:30:00...
Success! All tasks completed successfully within the specified timeout period.
Deleting container [input]....

Sample end: 11/28/2018 3:29:36 PM
Elapsed time: 00:09:14.3418742

Accédez à votre compte Batch dans le portail Azure pour surveiller le pool, les nœuds de calcul, les travaux et les tâches. Par exemple, pour voir une carte thermique des nœuds de calcul de votre pool, sélectionnez Pools>LinuxFFmpegPool.

Lorsque les tâches sont en cours d’exécution, la carte thermique est similaire à ce qui suit :

Screenshot of Pool heat map.

Le temps d’exécution standard est d’environ 5 minutes lorsque l’application fonctionne dans sa configuration par défaut. La création d’un pool est l’opération la plus longue.

Récupérer les fichiers de sortie

Vous pouvez utiliser le portail Azure pour télécharger les fichiers de sortie MP3 générés par les tâches ffmpeg.

  1. Cliquez sur Tous les services>Comptes de stockage, puis sur le nom de votre compte de stockage.
  2. Cliquez sur BLOB>sortie.
  3. Cliquez avec le bouton droit sur l’un des fichiers de sortie MP3 puis cliquez sur Télécharger. Suivez les invites dans votre navigateur pour ouvrir ou enregistrer le fichier.

Download output file

Même si ce n’est pas montré dans cet exemple, vous pouvez aussi télécharger les fichiers par programmation depuis les nœuds de calcul ou depuis le conteneur de stockage.

Vérifier le code

Dans les sections suivantes, nous examinons l’exemple d’application en nous servant des opérations qu’elle effectue pour traiter une charge de travail dans le service Batch. Référez-vous au code Python lorsque vous lisez le reste de cet article, car certaines lignes de code de cet exemple ne sont pas expliquées ici.

Authentifier les clients Blob et Batch

Pour interagir avec un compte de stockage, l’application utilise le package azure-storage-blob pour créer un objet BlockBlobService.

blob_client = azureblob.BlockBlobService(
    account_name=_STORAGE_ACCOUNT_NAME,
    account_key=_STORAGE_ACCOUNT_KEY)

L’application crée un objet BatchServiceClient pour créer et gérer des pools, des travaux et des tâches dans le service Batch. Le client Batch dans l’exemple utilise l’authentification de la clé partagée. Batch prend également en charge l’authentification via Microsoft Entra ID pour authentifier des utilisateurs ou une application sans assistance.

credentials = batchauth.SharedKeyCredentials(_BATCH_ACCOUNT_NAME,
                                             _BATCH_ACCOUNT_KEY)

batch_client = batch.BatchServiceClient(
    credentials,
    base_url=_BATCH_ACCOUNT_URL)

Charger des fichiers d’entrée

L’application utilise la référence blob_client pour créer un conteneur de stockage pour les fichiers MP4 d’entrée et un conteneur pour la sortie de la tâche. Ensuite, elle appelle la fonction upload_file_to_container pour charger des fichiers MP4 du répertoire InputFiles local vers le conteneur. Les fichiers de stockage sont définis en tant qu’objets Batch ResourceFile que Batch peut télécharger ultérieurement sur les nœuds de calcul.

blob_client.create_container(input_container_name, fail_on_exist=False)
blob_client.create_container(output_container_name, fail_on_exist=False)
input_file_paths = []

for folder, subs, files in os.walk(os.path.join(sys.path[0], './InputFiles/')):
    for filename in files:
        if filename.endswith(".mp4"):
            input_file_paths.append(os.path.abspath(
                os.path.join(folder, filename)))

# Upload the input files. This is the collection of files that are to be processed by the tasks.
input_files = [
    upload_file_to_container(blob_client, input_container_name, file_path)
    for file_path in input_file_paths]

Créer un pool de nœuds de calcul

Ensuite, l’exemple crée un pool de nœuds de traitement dans le compte Batch, avec un appel à create_pool. Cette fonction définie utilise la classe PoolAddParameter Batch pour définir le nombre de nœuds, la taille de machine virtuelle et une configuration de pool. Ici, un objet VirtualMachineConfiguration spécifie une référence ImageReference sur une image Ubuntu Server 20.04 LTS publiée dans la Place de marché Azure. Azure Batch prend en charge une large plage de machine virtuelle dans la Place de marché Microsoft Azure, ainsi que des images de machines virtuelles personnalisées.

Le nombre de nœuds et la taille de machine virtuelle sont définis à l’aide de constantes définies. Azure Batch prend en charge les nœuds dédiés et les nœuds de faible priorité que vous pouvez utiliser dans vos pools. Les nœuds dédiés sont réservés à votre pool. Les nœuds de faible priorité sont proposés à prix réduit à partir de la capacité de machine virtuelle excédentaire dans Azure. Les nœuds spot deviennent indisponibles si la capacité d’Azure est insuffisante. L’exemple par défaut crée un pool contenant seulement cinq nœuds spot taille Standard_A1_v2.

En plus des propriétés du nœud physique, cette configuration de pool inclut un objet StartTask. La tâche StartTask s’exécute sur chacun des nœuds rejoignant le pool, ainsi qu’à chaque redémarrage d’un nœud. Dans cet exemple, StartTask exécute les commandes de l’interpréteur de commandes Bash pour installer le package ffmpeg et les dépendances sur les nœuds.

La méthode pool.add soumet le pool au service Batch.

new_pool = batch.models.PoolAddParameter(
    id=pool_id,
    virtual_machine_configuration=batchmodels.VirtualMachineConfiguration(
        image_reference=batchmodels.ImageReference(
            publisher="Canonical",
            offer="UbuntuServer",
            sku="20.04-LTS",
            version="latest"
        ),
        node_agent_sku_id="batch.node.ubuntu 20.04"),
    vm_size=_POOL_VM_SIZE,
    target_dedicated_nodes=_DEDICATED_POOL_NODE_COUNT,
    target_low_priority_nodes=_LOW_PRIORITY_POOL_NODE_COUNT,
    start_task=batchmodels.StartTask(
        command_line="/bin/bash -c \"apt-get update && apt-get install -y ffmpeg\"",
        wait_for_success=True,
        user_identity=batchmodels.UserIdentity(
            auto_user=batchmodels.AutoUserSpecification(
                scope=batchmodels.AutoUserScope.pool,
                elevation_level=batchmodels.ElevationLevel.admin)),
    )
)
batch_service_client.pool.add(new_pool)

Créer un travail

Un programme de traitement par lots spécifie un pool pour exécuter des tâches et des paramètres facultatifs tels qu’une priorité et un calendrier pour le travail. L’exemple crée un travail avec un appel à create_job. Cette fonction définie utilise la classe JobAddParameter pour créer un travail sur votre pool. La méthode job.add soumet le pool au service Batch. Dans un premier temps, le travail n’a aucune tâche.

job = batch.models.JobAddParameter(
    id=job_id,
    pool_info=batch.models.PoolInformation(pool_id=pool_id))

batch_service_client.job.add(job)

Créer des tâches

L’application crée des tâches dans le travail avec un appel à add_tasks. Cette fonction définie crée une liste d’objets de tâches à l’aide de la classe TaskAddParameter. Chaque tâche exécute ffmpeg pour traiter un objet resource_files d’entrée à l’aide d’un paramètre command_line. ffmpeg a été précédemment installé sur chaque nœud lors de la création du pool. Ici, la ligne de commande exécute ffmpeg pour convertir chaque fichier (vidéo) MP4 en fichier MP3 (audio).

L’exemple crée un objet OutputFile pour le fichier MP3 après l’exécution de la ligne de commande. Les fichiers de sortie de chaque tâche (un, dans ce cas) sont chargés sur un conteneur dans le compte de stockage lié, à l’aide de la propriété output_files de la tâche.

Ensuite, l’application ajoute des tâches au travail avec la méthode task.add_collection, qui les met en file d’attente afin de les exécuter sur les nœuds de calcul.

tasks = list()

for idx, input_file in enumerate(input_files):
    input_file_path = input_file.file_path
    output_file_path = "".join((input_file_path).split('.')[:-1]) + '.mp3'
    command = "/bin/bash -c \"ffmpeg -i {} {} \"".format(
        input_file_path, output_file_path)
    tasks.append(batch.models.TaskAddParameter(
        id='Task{}'.format(idx),
        command_line=command,
        resource_files=[input_file],
        output_files=[batchmodels.OutputFile(
            file_pattern=output_file_path,
            destination=batchmodels.OutputFileDestination(
                container=batchmodels.OutputFileBlobContainerDestination(
                    container_url=output_container_sas_url)),
            upload_options=batchmodels.OutputFileUploadOptions(
                upload_condition=batchmodels.OutputFileUploadCondition.task_success))]
    )
    )
batch_service_client.task.add_collection(job_id, tasks)

Surveiller les tâches

Lorsque les tâches sont ajoutées à un travail, le service les met automatiquement en file d’attente et planifie leur exécution sur les nœuds de calcul dans le pool associé. Selon les paramètres que vous spécifiez, Batch gère l’ensemble des opérations de mise en file d’attente, de planification, de ré-exécution et d’administration des tâches.

Il existe plusieurs approches pour l’exécution de la tâche d’analyse. La fonction wait_for_tasks_to_complete de cet exemple utilise l’objet TaskState pour surveiller les tâches relatives à un état spécifique. Dans ce cas, il s’agit de l’état terminé, dans un délai imparti.

while datetime.datetime.now() < timeout_expiration:
    print('.', end='')
    sys.stdout.flush()
    tasks = batch_service_client.task.list(job_id)

    incomplete_tasks = [task for task in tasks if
                        task.state != batchmodels.TaskState.completed]
    if not incomplete_tasks:
        print()
        return True
    else:
        time.sleep(1)
...

Nettoyer les ressources

Après avoir exécuté les tâches, l’application supprime automatiquement le conteneur de stockage d’entrée créé et vous donne la possibilité de supprimer le travail et le pool Azure Batch. Les classes JobOperations et PoolOperations de BatchServiceClient disposent toutes deux de méthodes de suppression, appelées si l’utilisateur confirme la suppression. Bien que vous ne soyez pas facturé pour les travaux et les tâches à proprement parler, les nœuds de calcul vous sont facturés. Par conséquent, nous vous conseillons d’affecter les pools uniquement en fonction des besoins. Lorsque vous supprimez le pool, toutes les sorties de tâche sur les nœuds sont supprimées. Toutefois, les fichiers d’entrée et de sortie restent dans le compte de stockage.

Lorsque vous n’en avez plus besoin, supprimez le groupe de ressources, le compte Batch et le compte de stockage. Pour ce faire, dans le portail Azure, sélectionnez le groupe de ressources pour le compte Batch, puis choisissez Supprimer le groupe de ressources.

Étapes suivantes

Dans ce didacticiel, vous avez appris à :

  • S’authentifier avec des comptes de stockage et Batch.
  • Charger des fichiers d’entrée sur le stockage.
  • Créer un pool de nœuds de calcul pour exécuter une application.
  • Créer un travail et des tâches pour traiter les fichiers d’entrée.
  • Surveiller l’exécution d’une tâche.
  • Récupérer les fichiers de sortie.

Pour plus d’exemples d’utilisation de l’API Python pour planifier et traiter les charges de travail Batch, consultez les exemples Batch Python sur GitHub.