Tutorial: Executar uma carga de trabalho paralela com o Azure Batch através da API Python

Utilize o Azure Batch para executar trabalhos de lote de computação de alto desempenho (HPC) e paralelos em larga escala de forma eficaz no Azure. Este tutorial guia-o por um exemplo Python de execução de uma carga de trabalho paralela com o Batch. Obteve mais informações sobre um fluxo de trabalho de aplicações do Batch comum e como interagir programaticamente com recursos do Batch e de Armazenamento.

  • Autentique-se com contas de lote e armazenamento.
  • Carregue arquivos de entrada para o armazenamento.
  • Crie um pool de nós de computação para executar um aplicativo.
  • Crie um trabalho e tarefas para processar arquivos de entrada.
  • Monitore a execução da tarefa.
  • Recupere arquivos de saída.

Neste tutorial, você converte arquivos de mídia MP4 para o formato MP3, em paralelo, usando a ferramenta de código aberto ffmpeg .

Se não tiver uma subscrição do Azure, crie uma conta gratuita do Azure antes de começar.

Pré-requisitos

  • Python versão 3.8 ou posterior

  • Gestor de pacotes pip

  • Uma conta do Batch do Azure e uma conta de Armazenamento do Microsoft Azure associada. Para criar essas contas, consulte os guias de início rápido em lote para o portal do Azure ou a CLI do Azure.

Iniciar sessão no Azure

Inicie sessão no portal do Azure.

Obter credenciais da conta

Neste exemplo, tem de apresentar as credenciais para as contas do Batch e de Armazenamento. É uma forma simples de obter as credenciais necessárias no portal do Azure. (Também pode obter estas credenciais com as APIs do Azure ou as ferramentas de linha de comandos.)

  1. Selecione Todas as contas de Lote de serviços>e, em seguida, selecione o nome da sua conta de Lote.

  2. Para ver as credenciais do lote, selecione Chaves. Copie os valores da conta do Batch, o URL e a Chave de acesso primária para um editor de texto.

  3. Para ver o nome e as chaves da conta de armazenamento, selecione Conta de armazenamento. Copie os valores do Nome da conta de armazenamento e Chave1 para um editor de texto.

Baixe e execute o aplicativo de exemplo

Transferir a aplicação de exemplo

Transfira ou clonar a aplicação de exemplo a partir do GitHub. Para clonar o repositório de aplicações de exemplo com um cliente Git, utilize o seguinte comando:

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

Navegue até o diretório que contém o arquivo batch_python_tutorial_ffmpeg.py.

No ambiente do Python, instale os pacotes necessários através de pip.

pip install -r requirements.txt

Use um editor de código para abrir o arquivo config.py. Atualize as cadeias de credenciais das contas do Batch e de armazenamento com os valores exclusivos das suas contas. Por exemplo:

_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=='

Executar a aplicação

Para executar o script:

python batch_python_tutorial_ffmpeg.py

Quando executar a aplicação de exemplo, o resultado da consola é semelhante ao seguinte. Durante a execução, ocorre uma pausa em Monitoring all tasks for 'Completed' state, timeout in 00:30:00... enquanto os nós de computação do conjunto são iniciados.

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

Aceda à conta do Batch no portal do Azure para monitorizar o conjunto, os nós de computação, o trabalho e as tarefas. Por exemplo, para ver um mapa de calor dos nós de computação em seu pool, selecione Pools>LinuxFFmpegPool.

Quando as tarefas estiverem em execução, o mapa térmico é semelhante ao seguinte:

Screenshot of Pool heat map.

O tempo de execução normal é de aproximadamente 5 minutos quando executa a aplicação na configuração predefinida. A criação do conjunto demora mais tempo.

Obter ficheiros de saída

Pode utilizar o portal do Azure para transferir os ficheiros MP3 de saída gerados pelas tarefas ffmpeg.

  1. Clique em Todos os serviços>Contas de armazenamento e, em seguida, clique no nome da sua conta de armazenamento.
  2. Clique em Blobs>saída.
  3. Clique com o botão direito do rato em um dos ficheiros MP3 de saída e, em seguida, clique em Transferir. Siga as instruções no seu browser para abrir ou guardar o ficheiro.

Download output file

Apesar de não estar mostrado neste exemplo, também pode transferir os ficheiros programaticamente a partir dos nós de computação ou do contentor de armazenamento.

Rever o código

As secções seguintes dividem a aplicação de exemplo nos passos que executa para processar uma carga de trabalho no serviço Batch. Veja o código Python ao ler o resto deste artigo, uma vez que nem todas as linhas de código no exemplo são abordadas.

Autenticar clientes Blob e Batch

Para interagir com uma conta de armazenamento, a aplicação utiliza o pacote azure-storage-blob para criar um objeto BlockBlobService.

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

A aplicação cria um objeto BatchServiceClient para criar e gerir conjuntos, trabalhos e tarefas no serviço Batch. O cliente Batch no exemplo utiliza a autenticação de chave partilhada. O Batch também oferece suporte à autenticação por meio do Microsoft Entra ID, para autenticar usuários individuais ou um aplicativo autônomo.

credentials = batchauth.SharedKeyCredentials(_BATCH_ACCOUNT_NAME,
                                             _BATCH_ACCOUNT_KEY)

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

Carregar ficheiros de entrada

A aplicação utiliza a referência blob_client para criar um contentor de armazenamento para os ficheiros MP4 de entrada e um contentor para o resultado da tarefa. Em seguida, ele chama a upload_file_to_container função para carregar arquivos MP4 no diretório local InputFiles para o contêiner. Os ficheiros no armazenamento estão definidos como objetos ResourceFile que o Batch pode transferir mais tarde para os nós de computação.

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]

Criar um conjunto de nós de computação

Em seguida, o exemplo cria um conjunto de nós de computação na conta do Batch, com uma chamada para create_pool. Esta função definida utiliza a classe PoolAddParameter do Batch para definir o número de nós, o tamanho da VM e uma configuração de conjuntos. Aqui, um objeto VirtualMachineConfiguration especifica um ImageReference para uma imagem do Ubuntu Server 20.04 LTS publicada no Azure Marketplace. O Batch suporta inúmeras imagens da VM no Azure Marketplace, bem como imagens da VM personalizadas.

O número de nós e o tamanho da VM são definidos através de constantes definidas. O Batch suporta nós dedicados e nós Spot, e você pode usar um ou ambos em seus pools. Os nós dedicados estão reservados para o conjunto. Os nós spot são oferecidos a um preço reduzido a partir da capacidade excedente da VM no Azure. Os nós spot ficam indisponíveis se o Azure não tiver capacidade suficiente. O exemplo por padrão cria um pool contendo apenas cinco nós Spot em tamanho Standard_A1_v2.

Além das propriedades dos nós físicos, esta configuração de conjuntos inclui um objeto StartTask. O StartTask é executado em cada nó à medida que esse nó se associa ao conjunto, e sempre que um nó for reiniciado. Neste exemplo, o StartTask executa comandos da shell Bash para instalar o pacote ffmpeg e as dependências nos nós.

O método pool.add submete o conjunto para o serviço 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)

Criar um trabalho

Um trabalho do Batch especifica um conjunto para executar tarefas e definições opcionais, como uma prioridade e agenda para o trabalho. O exemplo cria um trabalho com uma chamada para create_job. Esta função definida utiliza a classe JobAddParameter para criar um trabalho no conjunto. O método job.add submete o conjunto para o serviço Batch. Inicialmente, os trabalhos não têm tarefas.

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

batch_service_client.job.add(job)

Criar tarefas

A aplicação cria tarefas no trabalho com uma chamada para add_tasks. Esta função definida cria uma lista de objetos de tarefas através da classe TaskAddParameter. Cada tarefa executa o ffmpeg para processar um objeto resource_files de entrada através de um parâmetro command_line. O ffmpeg foi instalado anteriormente em cada nó quando o conjunto foi criado. Aqui, a linha de comandos executa o ffmpeg para converter cada ficheiro MP4 (vídeo) de entrada num ficheiro MP3 (áudio).

O exemplo cria um objeto OutputFile para o ficheiro MP3 depois de executar a linha de comandos. Os ficheiros de saída de cada tarefa (um, neste caso) são carregados para um contentor na conta de armazenamento associada através da propriedade output_files da tarefa.

Em seguida, a aplicação adiciona tarefas ao trabalho com o método task.add_collection, o que as coloca em fila para serem executadas nos nós de computação.

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)

Monitorizar tarefas

Quando as tarefas forem adicionadas a um trabalho, o Batch coloca automaticamente em fila e agenda-as para execução nos nós de computação no conjunto associado. Com base nas definições especificadas, o Batch processa todas as tarefas de colocação em fila, agendamento, repetições e outras funções de administração de tarefas.

Existem várias abordagens à monitorização da execução de tarefas. A função wait_for_tasks_to_complete neste exemplo utiliza o objeto TaskState para monitorizar as tarefas num determinado estado, neste caso, o estado de concluído, dentro de um limite de tempo.

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)
...

Clean up resources (Limpar recursos)

Depois de executar as tarefas, a aplicação elimina automaticamente o contentor de armazenamento de entrada que criou e dá-lhe a opção de eliminar o conjunto e o trabalho do Batch. As classes JobOperations e PoolOperations do BatchClient têm métodos de eliminação, que são chamados se confirmar a eliminação. Apesar de os próprios trabalhos e tarefas não lhe serem cobrados, os nós de computação são cobrados. Assim, recomendamos que atribua conjuntos apenas conforme necessário. Quando eliminar o conjunto, todos os resultados da tarefa nos nós são eliminados. No entanto, os ficheiros de entrada e saída permanecem na conta de armazenamento.

Quando já não forem necessários, elimine o grupo de recursos, a conta do Batch e a conta de armazenamento. Para fazer isso no portal do Azure, selecione o grupo de recursos para a conta de lote e escolha Excluir grupo de recursos.

Próximos passos

Neste tutorial, ficou a saber como:

  • Autentique-se com contas de lote e armazenamento.
  • Carregue arquivos de entrada para o armazenamento.
  • Crie um pool de nós de computação para executar um aplicativo.
  • Crie um trabalho e tarefas para processar arquivos de entrada.
  • Monitore a execução da tarefa.
  • Recupere arquivos de saída.

Para obter mais exemplos de como usar a API Python para agendar e processar cargas de trabalho em lote, consulte os exemplos de Python em lote no GitHub.