Esercitazione: Eseguire un carico di lavoro parallelo con Azure Batch usando l'API .NET
Usare Azure Batch per eseguire in modo efficiente processi batch paralleli e HPC (High Performance Computing) su larga scala in Azure. Questa esercitazione illustra un esempio C# di esecuzione di un carico di lavoro parallelo usando Batch. Vengono fornite informazioni su un flusso di lavoro dell'applicazione Batch comune e su come interagire a livello di codice con le risorse di Archiviazione e Batch.
- Aggiungere un pacchetto dell'applicazione all'account Batch.
- Eseguire l'autenticazione con gli account di archiviazione e Batch.
- Caricare i file di input nella risorsa di archiviazione.
- Creare un pool di nodi di calcolo per eseguire un'applicazione.
- Creare un processo e le attività per elaborare i file di input.
- Monitorare l'esecuzione delle attività.
- Recuperare i file di output.
In questa esercitazione file multimediali MP4 vengono convertiti in parallelo in formato MP3 usando lo strumento open source ffmpeg.
Se non si ha una sottoscrizione di Azure, creare un account Azure gratuito prima di iniziare.
Prerequisiti
Visual Studio 2017 o versioni successive oppure .NET Core SDK per Linux, macOS o Windows.
Un account Batch e un account di archiviazione di Azure collegato. Per creare questi account, vedere le guide di avvio rapido di Batch per il portale di Azure o l'interfaccia della riga di comando di Azure.
Scaricare la versione appropriata di ffmpeg per il caso d'uso nel computer locale. Questa esercitazione e l'app di esempio correlata usano la versione completa di ffmpeg 4.3.1 per sistemi Windows a 64 bit. Per questa esercitazione è necessario solo il file ZIP. Non è necessario decomprimere il file o installarlo in locale.
Accedere ad Azure
Accedere al portale di Azure.
Aggiungere un pacchetto dell'applicazione
Usare il portale di Azure per aggiungere ffmpeg all'account Batch come pacchetto dell'applicazione. I pacchetti dell'applicazione aiutano a gestire le applicazioni di attività e la loro distribuzione nei nodi di calcolo del pool.
Nel portale di Azure fare clic su Altri servizi>Account Batch e quindi selezionare il nome dell'account Batch.
Fare clic su Applicazioni>Aggiungi.
Immettere ffmpeg nel campo ID applicazione e la versione del pacchetto 4.3.1 nel campo Versione. Selezionare il file ZIP ffmpeg scaricato e quindi selezionare Invia. Il pacchetto dell'applicazione ffmpeg viene aggiunto all'account Batch.
Ottenere le credenziali dell'account
Per questo esempio, è necessario fornire le credenziali per gli account di archiviazione e Batch. Un modo semplice per ottenere le credenziali necessarie consiste nell'usare il portale di Azure. È anche possibile ottenere le credenziali usando le API di Azure o gli strumenti da riga di comando.
Selezionare Tutti i servizi>Account Batch e quindi selezionare il nome dell'account Batch.
Per visualizzare le credenziali di Batch, selezionare Chiavi. Copiare i valori di Account Batch, URL e Chiave di accesso primaria in un editor di testo.
Per visualizzare il nome e le chiavi dell'account di archiviazione, selezionare Account di archiviazione. Copiare i valori dei campi Nome account di archiviazione e Key1 in un editor di testo.
Scaricare ed eseguire l'app di esempio
Scaricare l'app di esempio
Scaricare o clonare l'app di esempio da GitHub. Per clonare il repository dell'app di esempio con un client Git, usare il comando seguente:
git clone https://github.com/Azure-Samples/batch-dotnet-ffmpeg-tutorial.git
Passare alla directory che contiene il file di soluzione di Visual Studio BatchDotNetFfmpegTutorial.sln.
Assicurarsi inoltre che il riferimento al pacchetto dell'applicazione ffmpeg nella soluzione corrisponda all'ID e alla versione del pacchetto ffmpeg caricato nell'account Batch. Ad esempio, ffmpeg
e 4.3.1
.
const string appPackageId = "ffmpeg";
const string appPackageVersion = "4.3.1";
Compilare ed eseguire il progetto di esempio
Compilare ed eseguire l'applicazione in Visual Studio oppure eseguire i comandi dotnet build
e dotnet run
dalla riga di comando. Dopo l'esecuzione dell'applicazione, esaminare il codice per comprendere le operazioni eseguite da ogni parte dell'applicazione. Ad esempio, in Visual Studio:
Fare clic con il pulsante destro del mouse sulla soluzione in Esplora soluzioni e selezionare Compila soluzione.
Confermare il ripristino di eventuali pacchetti NuGet, se richiesto. Se è necessario scaricare i pacchetti mancanti, verificare che lo strumento Gestione pacchetti NuGet sia installato.
Eseguire la soluzione. Quando si esegue l'applicazione di esempio, l'output della console è simile al seguente. Durante l'esecuzione si verifica una pausa in corrispondenza di
Monitoring all tasks for 'Completed' state, timeout in 00:30:00...
mentre vengono avviati i nodi di calcolo del pool.
Sample start: 11/19/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 [WinFFmpegPool]...
Creating job [WinFFmpegJob]...
Adding 5 tasks to job [WinFFmpegJob]...
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/19/2018 3:29:36 PM
Elapsed time: 00:09:14.3418742
Passare all'account Batch nel portale di Azure per monitorare il pool, i nodi di calcolo, il processo e le attività. Per visualizzare, ad esempio, una mappa termica dei nodi di calcolo nel pool, fare clic su Pool>WinFFmpegPool.
Quando le attività sono in esecuzione, la mappa termica è simile all'esempio seguente:
Quando si esegue l'applicazione con la configurazione predefinita, il tempo di esecuzione tipico è di circa 10 minuti. La maggior parte del tempo è necessaria per la creazione del pool.
Recuperare i file di output
È possibile usare il portale di Azure per scaricare i file MP3 di output generati dalle attività ffmpeg.
- Fare clic su Tutti i servizi>Account di archiviazione e quindi fare clic sul nome dell'account di archiviazione.
- Fare clic su BLOB>output.
- Fare clic con il pulsante destro del mouse su uno dei file MP3 di output e quindi scegliere Scarica. Seguire i prompt nel browser per aprire o salvare il file.
Anche se non viene mostrato in questo esempio, è anche possibile scaricare i file a livello di codice dai nodi di calcolo o dal contenitore di archiviazione.
Esaminare il codice
Nelle sezioni seguenti si esamineranno in dettaglio i singoli passaggi eseguiti dall'applicazione di esempio per l'elaborazione di un carico di lavoro nel servizio Batch. Fare riferimento al file Program.cs nella soluzione mentre si legge la parte restante di questo articolo, perché non vengono illustrate tutte le righe di codice dell'esempio.
Autenticare i client BLOB e Batch
Per interagire con l'account di archiviazione collegato, l'app usa la libreria client Azure.Storage.Blobs per .NET. Viene usata la classe BlobServiceClient, che accetta un riferimento all'URI dell'account e al Token di autenticazione, ad esempio DefaultAzureCredential.
// TODO: Replace <storage-account-name> with your actual storage account name
Uri accountUri = new Uri("https://<storage-account-name>.blob.core.windows.net/");
BlobServiceClient blobClient = new BlobServiceClient(accountUri, new DefaultAzureCredential());
L'app crea un riferimento a BatchAccountResource tramite ARMClient di Resource Manager per creare il pool nel servizio Batch. Il client ARM nell'esempio usa l'autenticazione DefaultAzureCredential.
ArmClient _armClient = new ArmClient(new DefaultAzureCredential());
var batchAccountIdentifier = ResourceIdentifier.Parse(BatchAccountResourceID);
BatchAccountResource batchAccount = await _armClient.GetBatchAccountResource(batchAccountIdentifier).GetAsync();
L'app crea un oggetto BatchClient per creare e gestire pool, processi e attività nel servizio Batch. Il client Batch nell'esempio usa l'autenticazione DefaultAzureCredential.
// TODO: Replace <batch-account-name> with your actual storage account name
Uri batchUri = new Uri("https://<batch-account-name>t.eastus.batch.azure.com");
BatchClient _batchClient = new BatchClient(batchUri, new DefaultAzureCredential());
Caricare i file di input
L'app passa l'oggetto blobServerClient
al metodo CreateContainerIfNotExist
per creare un contenitore di archiviazione per i file di input (formato MP4) e un contenitore per l'output dell'attività.
CreateContainerIfNotExist(blobClient, inputContainerName);
CreateContainerIfNotExist(blobClient, outputContainerName);
I file vengono quindi caricati nel contenitore di input dalla cartella InputFiles locale. I file nel contenitore di archiviazione sono definiti come oggetti ResourceFile di Batch che successivamente Batch può scaricare nei nodi di calcolo.
Per il caricamento dei file vengono usati due metodi in Program.cs:
UploadFilesToContainerAsync
: restituisce una raccolta di oggettiResourceFile
e chiama internamenteUploadResourceFileToContainerAsync
per caricare ogni file passato nel parametroinputFilePaths
.UploadResourceFileToContainerAsync
: carica ogni file come BLOB nel contenitore di input. Dopo il caricamento del file, ottiene una firma di accesso condiviso per il BLOB e restituisce un oggettoResourceFile
che lo rappresenta.
string inputPath = Path.Combine(Environment.CurrentDirectory, "InputFiles");
List<string> inputFilePaths = new List<string>(Directory.GetFileSystemEntries(inputPath, "*.mp4",
SearchOption.TopDirectoryOnly));
List<ResourceFile> inputFiles = await UploadFilesToContainerAsync(
blobClient,
inputContainerName,
inputFilePaths);
Per informazioni dettagliate sul caricamento di file come BLOB in un account di archiviazione con .NET, vedere Caricare, scaricare ed elencare BLOB con .NET.
Creare un pool di nodi di calcolo
L'esempio crea quindi un pool di nodi di calcolo nell'account Batch con una chiamata a CreatePoolIfNotExistAsync
. Questo metodo definito usa il metodo BatchAccountResource.GetBatchAccountPools().CreateOrUpdateAsync per impostare il numero di nodi, le dimensioni delle VM e una configurazione del pool. In questo caso, un oggetto BatchVmConfiguration specifica un oggetto BatchImageReference che fa riferimento a un'immagine di Windows Server pubblicata in Azure Marketplace. Batch supporta una vasta gamma di immagini di VM in Azure Marketplace, oltre che immagini di VM personalizzate.
Il numero di nodi e le dimensioni delle VM vengono impostati usando costanti definite. Batch supporta nodi dedicati e nodi spot e nei pool è possibile usare uno di questi tipi o entrambi. I nodi dedicati sono riservati per il pool. I nodi spot vengono offerti a un prezzo ridotto usando la capacità in eccesso delle VM in Azure. I nodi spot non sono disponibili se Azure non ha capacità sufficiente. L'esempio crea per impostazione predefinita un pool che contiene solo 5 nodi spot con dimensioni Standard_A1_v2.
Nota
Assicurarsi di controllare le quote del nodo. Per istruzioni su come creare una richiesta di aumento della quota, vedere Quote e limiti del servizio Batch.
L'applicazione ffmpeg viene distribuita nei nodi di calcolo aggiungendo un oggetto ApplicationPackageReference alla configurazione del pool.
var credential = new DefaultAzureCredential();
ArmClient _armClient = new ArmClient(credential);
var batchAccountIdentifier = ResourceIdentifier.Parse(BatchAccountResourceID);
BatchAccountResource batchAccount = await _armClient.GetBatchAccountResource(batchAccountIdentifier).GetAsync();
BatchAccountPoolCollection collection = batchAccount.GetBatchAccountPools();
if (collection.Exists(poolId) == false)
{
var poolName = poolId;
var imageReference = new BatchImageReference()
{
Publisher = "MicrosoftWindowsServer",
Offer = "WindowsServer",
Sku = "2019-datacenter-smalldisk",
Version = "latest"
};
string nodeAgentSku = "batch.node.windows amd64";
ArmOperation<BatchAccountPoolResource> armOperation = await batchAccount.GetBatchAccountPools().CreateOrUpdateAsync(
WaitUntil.Completed, poolName, new BatchAccountPoolData()
{
VmSize = "Standard_DS1_v2",
DeploymentConfiguration = new BatchDeploymentConfiguration()
{
VmConfiguration = new BatchVmConfiguration(imageReference, nodeAgentSku)
},
ScaleSettings = new BatchAccountPoolScaleSettings()
{
FixedScale = new BatchAccountFixedScaleSettings()
{
TargetDedicatedNodes = DedicatedNodeCount,
TargetLowPriorityNodes = LowPriorityNodeCount
}
},
Identity = new ManagedServiceIdentity(ManagedServiceIdentityType.UserAssigned)
{
UserAssignedIdentities =
{
[new ResourceIdentifier(ManagedIdentityId)] = new Azure.ResourceManager.Models.UserAssignedIdentity(),
},
},
ApplicationPackages =
{
new Azure.ResourceManager.Batch.Models.BatchApplicationPackageReference(new ResourceIdentifier(appPackageResourceID))
{
Version = appPackageVersion,
}
},
});
BatchAccountPoolResource pool = armOperation.Value;
Creare un processo
Un processo Batch specifica un pool in cui eseguire le attività e impostazioni facoltative, ad esempio una priorità e una pianificazione per il lavoro. L'esempio crea un processo con una chiamata a CreateJobAsync
. Questo metodo definito usa il metodo BatchClient.CreateJobAsync per creare un processo nel pool.
BatchJobCreateContent batchJobCreateContent = new BatchJobCreateContent(jobId, new BatchPoolInfo { PoolId = poolId });
await batchClient.CreateJobAsync(batchJobCreateContent);
Creare attività
L'esempio crea le attività del processo con una chiamata al metodo AddTasksAsync
, che crea un elenco di oggetti BatchTask. Ogni oggetto BatchTask
esegue ffmpeg per elaborare un oggetto ResourceFile
di input usando una proprietà CommandLine. Lo strumento ffmpeg è stato installato in precedenza in ogni nodo al momento della creazione del pool. In questo caso, la riga di comando esegue ffmpeg per convertire ogni file (video) MP4 di input in un file (audio) MP3.
L'esempio crea un oggetto OutputFile per il file MP3 dopo l'esecuzione della riga di comando. I file di output di ogni attività, in questo caso uno, vengono caricati in un contenitore nell'account di archiviazione collegato, usando la proprietà OutputFiles dell'attività. Notare le condizioni impostate sull'oggetto outputFile
. Un file di output da un'attività viene caricato nel contenitore solo dopo il completamento corretto dell'attività (OutputFileUploadCondition.TaskSuccess
). Vedere l'esempio di codice completo su GitHub per altri dettagli sull'implementazione.
L'esempio aggiunge quindi le attività al processo con il metodo CreateTaskAsync, che le accoda per l'esecuzione nei nodi di calcolo.
Sostituire il percorso del file eseguibile con il nome della versione scaricata. Questo codice di esempio usa la versione ffmpeg-4.3.1-2020-11-08-full_build
.
// Create a collection to hold the tasks added to the job:
List<BatchTaskCreateContent> tasks = new List<BatchTaskCreateContent>();
for (int i = 0; i < inputFiles.Count; i++)
{
// Assign a task ID for each iteration
string taskId = String.Format("Task{0}", i);
// Define task command line to convert the video format from MP4 to MP3 using ffmpeg.
// Note that ffmpeg syntax specifies the format as the file extension of the input file
// and the output file respectively. In this case inputs are MP4.
string appPath = String.Format("%AZ_BATCH_APP_PACKAGE_{0}#{1}%", appPackageId, appPackageVersion);
string inputMediaFile = inputFiles[i].StorageContainerUrl;
string outputMediaFile = String.Format("{0}{1}",
System.IO.Path.GetFileNameWithoutExtension(inputMediaFile),
".mp3");
string taskCommandLine = String.Format("cmd /c {0}\\ffmpeg-4.3.1-2020-11-08-full_build\\bin\\ffmpeg.exe -i {1} {2}", appPath, inputMediaFile, outputMediaFile);
// Create a batch task (with the task ID and command line) and add it to the task list
BatchTaskCreateContent batchTaskCreateContent = new BatchTaskCreateContent(taskId, taskCommandLine);
batchTaskCreateContent.ResourceFiles.Add(inputFiles[i]);
// Task output file will be uploaded to the output container in Storage.
// TODO: Replace <storage-account-name> with your actual storage account name
OutputFileBlobContainerDestination outputContainer = new OutputFileBlobContainerDestination("https://<storage-account-name>.blob.core.windows.net/output/" + outputMediaFile)
{
IdentityReference = inputFiles[i].IdentityReference,
};
OutputFile outputFile = new OutputFile(outputMediaFile,
new OutputFileDestination() { Container = outputContainer },
new OutputFileUploadConfig(OutputFileUploadCondition.TaskSuccess));
batchTaskCreateContent.OutputFiles.Add(outputFile);
tasks.Add(batchTaskCreateContent);
}
// Call BatchClient.CreateTaskCollectionAsync() to add the tasks as a collection rather than making a
// separate call for each. Bulk task submission helps to ensure efficient underlying API
// calls to the Batch service.
await batchClient.CreateTaskCollectionAsync(jobId, new BatchTaskGroup(tasks));
Pulire le risorse
Al termine dell'esecuzione delle attività, l'app elimina automaticamente il contenitore di archiviazione di input creato e consente di scegliere se eliminare il processo e il pool di Batch. L'oggetto BatchClient dispone di un metodo per eliminare un processo DeleteJobAsync ed eliminare un pool DeletePoolAsync, che vengono chiamati se si conferma l'eliminazione. Anche se non vengono addebitati costi per i processi e per le attività, vengono invece addebiti costi per i nodi di calcolo. È quindi consigliabile allocare solo i pool necessari. Quando si elimina il pool, tutto l'output delle attività nei nodi viene eliminato. I file di output rimangono tuttavia nell'account di archiviazione.
Quando non sono più necessari, eliminare il gruppo di risorse, l'account Batch e l'account di archiviazione. A tale scopo, nel portale di Azure selezionare il gruppo di risorse per l'account Batch e fare clic su Elimina gruppo di risorse.
Passaggi successivi
Questa esercitazione ha descritto come:
- Aggiungere un pacchetto dell'applicazione all'account Batch.
- Eseguire l'autenticazione con gli account di archiviazione e Batch.
- Caricare i file di input nella risorsa di archiviazione.
- Creare un pool di nodi di calcolo per eseguire un'applicazione.
- Creare un processo e le attività per elaborare i file di input.
- Monitorare l'esecuzione delle attività.
- Recuperare i file di output.
Per altri esempi di uso dell'API .NET per pianificare ed elaborare i carichi di lavoro di Batch, vedere gli esempi C# per Batch su GitHub.