Dela via


Självstudie: Kör en parallell arbetsbelastning med Azure Batch med hjälp av .NET API

Använd Azure Batch till att effektivt köra storskaliga parallella program och HPC-program (databehandling med höga prestanda) i Azure. I den här självstudien går vi igenom ett C#-exempel på att köra en parallell arbetsbelastning med Batch. Du lär dig ett vanligt arbetsflöde för Batch-program och hur du interagerar programmatiskt med Batch- och Storage-resurser.

  • Lägg till ett programpaket till ditt Batch-konto.
  • Autentisera med Batch- och Storage-konton.
  • Ladda upp indatafiler till Storage.
  • Skapa en pool med beräkningsnoder för att köra ett program.
  • Skapa ett jobb och uppgifter för att bearbeta indatafiler.
  • Övervaka aktivitetskörning.
  • Hämta utdatafiler.

I den här självstudien konverterar du MP4-mediefiler till MP3-format parallellt med hjälp av verktyget ffmpeg med öppen källkod.

Om du inte har en Azure-prenumeration skapar du ett kostnadsfritt Azure-konto innan du börjar.

Förutsättningar

Logga in på Azure

Logga in på Azure-portalen.

Lägg till ett programpaket

Använd Azure-portalen och lägg till ffmpeg i Batch-kontot som ett programpaket. Med programpaket kan du hantera uppgiftsprogram och deras distribution till beräkningsnoderna i din pool.

  1. I Azure Portal klickar du på Fler tjänster>Batch-konton och väljer namnet på ditt Batch-konto.

  2. Klicka på Program>Lägg till.

    Skärmbild av avsnittet Program i batchkontot.

  3. Ange ffmpeg i fältet Program-ID och en paketversion av 4.3.1 i fältet Version . Välj zip-filen ffmpeg som du laddade ned och välj sedan Skicka. Programpaketet för ffmpeg läggs till i Batch-kontot.

    Skärmbild av fälten ID och version i avsnittet Lägg till program.

Hämta kontouppgifter

Du måste ange autentiseringsuppgifter för dina Batch- och Storage-konton i det här exemplet. Ett enkelt sätt att hämta de autentiseringsuppgifter som behövs är i Azure-portalen. (Du kan också hämta autentiseringsuppgifterna via Azures API:er och kommandoradsverktyg.)

  1. Välj Alla tjänster>Batch-konton och välj sedan namnet på ditt Batch-konto.

  2. Om du vill se Batch-autentiseringsuppgifterna väljer du Nycklar. Kopiera värdena för Batch-konto, URL och Primär åtkomstnyckel till en textredigerare.

  3. Om du vill se lagringskontots namn och nycklar väljer du Lagringskonto. Kopiera värdena för Lagringskontonamn och Key1 till en textredigerare.

Ladda ned och kör exempelappen

Ladda ned exempelprogrammet

Ladda ned eller klona exempelappen från GitHub. Om du vill klona lagringsplatsen för exempelappen med en Git-klient använder du följande kommando:

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

Gå till katalogen som innehåller Visual Studio-lösningsfilen BatchDotNetFfmpegTutorial.sln.

Kontrollera också att referensen för ffmpeg-programpaketet i lösningen matchar identifieraren och versionen av ffmpeg-paketet som du laddade upp till ditt Batch-konto. Till exempel ffmpeg och 4.3.1.

const string appPackageId = "ffmpeg";
const string appPackageVersion = "4.3.1";

Skapa och kör exempelprojektet

Skapa och kör programmet i Visual Studio eller på kommandoraden med kommandona dotnet build och dotnet run. När du har kört appen ska du granska koden för att lära dig hur varje del av appen fungerar. Till exempel i Visual Studio:

  1. Högerklicka på lösningen i Solution Explorer och välj Skapa lösning.

  2. Bekräfta återställningen av NuGet-paket om du uppmanas att göra det. Om du behöver hämta paket som saknas ska du se till att NuGet Package Manager är installerad.

  3. Kör lösningen. När du kör exempelappen ser konsolens utdata ut ungefär så här. Under körningen uppstår det en paus vid Monitoring all tasks for 'Completed' state, timeout in 00:30:00... medan poolens beräkningsnoder startas.

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

Gå till Batch-kontot på Azure-portalen för att övervaka poolen, beräkningsnoderna, jobbet och aktiviteterna. Om du till exempel vill se en termisk karta över beräkningsnoderna i din pool klickar du på Pooler>WinFFmpegPool.

När uppgifter körs ser den termiska kartan ut ungefär så här:

Skärmbild av poolens värmekarta i Azure Portal.

Körningen tar normalt runt 10 minuter om du kör programmet med standardkonfigurationen. Att skapa poolen är det som tar mest tid.

hämta utdatafilerna.

Du kan använda Azure-portalen till att hämta de utdatafiler i MP3-format som genereras av ffmpeg-uppgifter.

  1. Klicka på Alla tjänster>Lagringskonton och sedan på namnet på lagringskontot.
  2. Klicka på Blobbar>Utdata.
  3. Högerklicka på en av MP3-utdatafilerna och klicka sedan på Ladda ned. Följ anvisningarna i webbläsaren för att öppna eller spara filen.

Ladda ned utdatafil

Även om det inte visas i det här exemplet kan du också ladda ned filerna programmatiskt från beräkningsnoderna eller från lagringscontainern.

Granska koden

I följande avsnitt bryter vi ned exempelprogrammet i de steg som utförs när en arbetsbelastning bearbetas i Batch-tjänsten. Se filen Program.cs i lösningen medan du läser resten av den här artikeln, eftersom inte alla kodrader i exemplet diskuteras.

Autentisera Blob- och Batch-klienter

För att interagera med det länkade lagringskontot använder appen Azure.Storage.Blobs-biblioteket för .NET. Använda klassen BlobServiceClient som tar en referens till kontots URI och autentiserar token, till exempel 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());

Appen skapar en referens till BatchAccountResource via Resurshanterarens ArmClient för att skapa poolen i Batch-tjänsten. Arm-klienten i exemplet använder StandardAzureCredential-autentisering .

ArmClient _armClient = new ArmClient(new DefaultAzureCredential());
var batchAccountIdentifier = ResourceIdentifier.Parse(BatchAccountResourceID);
BatchAccountResource batchAccount = await _armClient.GetBatchAccountResource(batchAccountIdentifier).GetAsync();

Appen skapar ett BatchClient-objekt för att skapa och jobb och uppgifter i Batch-tjänsten. Batch-klienten i exemplet använder StandardAzureCredential-autentisering .

// 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());

Ladda upp indatafiler

Appen skickar blobServerClient-objektet till metoden CreateContainerIfNotExistc för att skapa en lagringscontainer för indatafilerna (MP4-format) och en container för uppgiftsutdata.

CreateContainerIfNotExist(blobClient, inputContainerName);
CreateContainerIfNotExist(blobClient, outputContainerName);

Sedan laddas filer upp till indatacontainern från den lokala mappen InputFiles . De lagrade filerna har definierats som Batch ResourceFile-objekt som Batch senare kan hämta till beräkningsnoder.

Två metoder i Program.cs är inblandade i att ladda upp filerna:

  • UploadFilesToContainerAsync: Returnerar en samling ResourceFile objekt och anropar UploadResourceFileToContainerAsync internt för att ladda upp varje fil som skickas i parametern inputFilePaths .
  • UploadResourceFileToContainerAsync: laddar upp varje fil som en blob till containern för indata. När filen har laddats upp hämtar den en signatur för delad åtkomst (SAS) för blobben och returnerar ett ResourceFile objekt som representerar den.
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);

Mer information om hur du laddar upp filer som blobar till ett lagringskonto med .NET finns i Ladda upp, ladda ned och lista blobar med hjälp av .NET.

Skapa en pool med beräkningsnoder

Därefter skapar exempelkoden en pool med beräkningsnoder i Batch-kontot med ett anrop till CreatePoolIfNotExistAsync. Den här definierade metoden använder BatchAccountResource.GetBatchAccountPools(). CreateOrUpdateAsync-metod för att ange antalet noder, VM-storlek och en poolkonfiguration. Här anger ett BatchVmConfiguration-objekt en BatchImageReference till en Windows Server-avbildning som publicerats på Azure Marketplace. Batch har stöd för ett stort antal Linux- och Windows Server-avbildningar på Azure Marketplace samt för anpassade VM-avbildningar.

Antalet noder och VM-storleken anges med definierade konstanter. Batch har stöd för dedikerade noder och spotnoder, och du kan använda antingen eller båda i dina pooler. Dedikerade noder är reserverade för din pool. Spotnoder erbjuds till ett reducerat pris från överskott av VM-kapacitet i Azure. Dekornoder blir otillgängliga om Azure inte har tillräckligt med kapacitet. Exemplet skapar som standard en pool som endast innehåller 5 oanvända noder i storlek Standard_A1_v2.

Kommentar

Kontrollera dina nodkvoter. Se Batch-tjänstkvoter och -gränser för instruktioner om hur du skapar en kvotbegäran.

Programmet ffmpeg distribueras till beräkningsnoderna genom att en ApplicationPackageReference läggs till i poolkonfigurationen.

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(appPacakgeResourceID))
                    {
                        Version = appPackageVersion,
                    }
            },

        });
    BatchAccountPoolResource pool = armOperation.Value;

Skapa ett jobb

Ett Batch-jobb anger en pool för körning av uppgifter, samt valfria inställningar som en prioritet och ett schema för arbetet. I exemplet skapas ett jobb med ett anrop till CreateJobAsync. Den här definierade metoden använder metoden BatchClient.CreateJobAsync för att skapa ett jobb i poolen.

 BatchJobCreateContent batchJobCreateContent = new BatchJobCreateContent(jobId, new BatchPoolInfo { PoolId = poolId });
 await batchClient.CreateJobAsync(batchJobCreateContent);

Skapa uppgifter

Exemplet skapar uppgifter i jobbet med ett anrop till AddTasksAsync metoden, vilket skapar en lista över BatchTask-objekt . Varje BatchTask kör ffmpeg för bearbetning av ett ResourceFile-indataobjekt med egenskapen CommandLine. ffmpeg installerades tidigare på varje nod när poolen skapades. Här kör kommandoraden ffmpeg för att konvertera varje MP4-indatafil (video) till en MP3-fil (ljud).

I exemplet skapas ett OutputFile-objekt för MP3-filen när du kör kommandoraden. Varje uppgifts utdatafiler (i det här fallet en) laddas upp till en container i länkade lagringskontot med uppgiftsegenskapen OutputFiles. Observera de villkor som angetts på objektet outputFile. En utdatafil från en uppgift laddas upp till containern först när uppgiften har slutförts (OutputFileUploadCondition.TaskSuccess). Ytterligare information om implementering finns i det fullständiga kodexemplet på GitHub.

Sedan lägger exemplet till uppgifter i jobbet med metoden CreateTaskAsync , som köar dem för att köras på beräkningsnoderna.

Ersätt filsökvägen för den körbara filen med namnet på den version som du laddade ned. Den här exempelkoden använder exemplet 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));

Rensa resurser

När uppgifterna har körts tar appen automatiskt bort den lagringscontainer som skapades och du får möjlighet att ta bort Batch-poolen och jobbet. BatchClient har en metod för att ta bort ett jobb DeleteJobAsync och ta bort en pool DeletePoolAsync, som anropas om du bekräftar borttagningen. Även om du inte debiteras för själva jobben och aktiviteterna debiteras du för beräkningsnoder. Vi rekommenderar därför att du endast allokerar pooler efter behov. När du tar bort poolen raderas alla aktivitetsutdata på noderna. Utdatafilerna ligger däremot kvar i lagringskontot.

När de inte längre behövs tar du bort resursgruppen, Batch-kontot och lagringskontot. Om du vill göra det i Azure-portalen väljer du resursgruppen för Batch-kontot och klickar på Ta bort resursgrupp.

Nästa steg

I den här självstudiekursen lärde du dig att:

  • Lägg till ett programpaket till ditt Batch-konto.
  • Autentisera med Batch- och Storage-konton.
  • Ladda upp indatafiler till Storage.
  • Skapa en pool med beräkningsnoder för att köra ett program.
  • Skapa ett jobb och uppgifter för att bearbeta indatafiler.
  • Övervaka aktivitetskörning.
  • Hämta utdatafiler.

Fler exempel på hur du använder .NET API för att schemalägga och bearbeta Batch-arbetsbelastningar finns i Batch C#-exemplen på GitHub.