Taken met meerdere exemplaren gebruiken om MPI-toepassingen (Message Passing Interface) uit te voeren in Batch

Met taken met meerdere exemplaren kunt u tegelijkertijd een Azure Batch taak uitvoeren op meerdere rekenknooppunten. Deze taken maken high performance computing-scenario's mogelijk, zoals MPI-toepassingen (Message Passing Interface) in Batch. In dit artikel leert u hoe u taken met meerdere exemplaren uitvoert met behulp van de Batch .NET-bibliotheek .

Notitie

Hoewel de voorbeelden in dit artikel gericht zijn op Batch .NET, MS-MPI en Windows rekenknooppunten, zijn de hier besproken concepten van taken met meerdere exemplaren van toepassing op andere platforms en technologieën (Bijvoorbeeld Python en Intel MPI op Linux-knooppunten).

Overzicht van taak met meerdere exemplaren

In Batch wordt elke taak normaal gesproken uitgevoerd op één rekenknooppunt. U verzendt meerdere taken naar een taak en de Batch-service plant elke taak voor uitvoering op een knooppunt. Door echter de instellingen voor meerdere exemplaren van een taak te configureren, moet u Batch in plaats daarvan één primaire taak en meerdere subtaken maken die vervolgens op meerdere knooppunten worden uitgevoerd.

Diagram showing an overview of multi-instance settings.

Wanneer u een taak met instellingen voor meerdere exemplaren naar een taak verzendt, voert Batch verschillende stappen uit die uniek zijn voor taken met meerdere exemplaren:

  1. De Batch-service maakt één primaire en meerdere subtaken op basis van de instellingen voor meerdere exemplaren . Het totale aantal taken (primaire plus alle subtaken) komt overeen met het aantal exemplaren (rekenknooppunten ) dat u opgeeft in de instellingen voor meerdere exemplaren.
  2. Batch wijst een van de rekenknooppunten aan als hoofdknooppunten en plant de primaire taak die op de hoofdtaak moet worden uitgevoerd. Hiermee worden de subtaken gepland die moeten worden uitgevoerd op de rest van de rekenknooppunten die zijn toegewezen aan de taak met meerdere exemplaren, één subtaak per knooppunt.
  3. De primaire en alle subtaken downloaden alle algemene resourcebestanden die u opgeeft in de instellingen voor meerdere exemplaren.
  4. Nadat de algemene resourcebestanden zijn gedownload, voeren de primaire en subtaken de coördinatieopdracht uit die u opgeeft in de instellingen voor meerdere exemplaren. De coördinatieopdracht wordt doorgaans gebruikt om knooppunten voor te bereiden voor het uitvoeren van de taak. Dit kan bijvoorbeeld achtergrondservices (zoals Microsoft MPI'ssmpd.exe) starten en controleren of de knooppunten gereed zijn voor het verwerken van berichten tussen knooppunten.
  5. De primaire taak voert de toepassingsopdracht uit op het hoofdknooppunt nadat de coördinatieopdracht is voltooid door de primaire en alle subtaken. De opdracht van de toepassing is de opdrachtregel van de taak met meerdere exemplaren zelf en wordt alleen uitgevoerd door de primaire taak. In een op MS-MPI gebaseerde oplossing voert u uw toepassing met MPI uit met behulp van mpiexec.exe.

Notitie

Hoewel het functioneel uniek is, is de 'taak met meerdere exemplaren' geen uniek taaktype, zoals de StartTask of JobPreparationTask. De taak met meerdere exemplaren is gewoon een standaard Batch-taak (CloudTask in Batch .NET) waarvan de instellingen voor meerdere exemplaren zijn geconfigureerd. In dit artikel verwijzen we hiernaar als de taak met meerdere exemplaren.

Vereisten voor taken met meerdere exemplaren

Voor taken met meerdere exemplaren is een pool vereist waarvoor communicatie tussen knooppunten is ingeschakeld en waarvoor gelijktijdige taakuitvoering is uitgeschakeld. Als u gelijktijdige taakuitvoering wilt uitschakelen, stelt u de eigenschap CloudPool.TaskSlotsPerNode in op 1.

Notitie

Batch beperkt de grootte van een pool waarvoor communicatie tussen knooppunten is ingeschakeld.

Dit codefragment laat zien hoe u een pool maakt voor taken met meerdere exemplaren met behulp van de Batch .NET-bibliotheek.

CloudPool myCloudPool =
    myBatchClient.PoolOperations.CreatePool(
        poolId: "MultiInstanceSamplePool",
        targetDedicatedComputeNodes: 3
        virtualMachineSize: "standard_d1_v2",
        VirtualMachineConfiguration: new VirtualMachineConfiguration(
        imageReference: new ImageReference(
                        publisher: "MicrosoftWindowsServer",
                        offer: "WindowsServer",
                        sku: "2019-datacenter-core",
                        version: "latest"),
        nodeAgentSkuId: "batch.node.windows amd64");

// Multi-instance tasks require inter-node communication, and those nodes
// must run only one task at a time.
myCloudPool.InterComputeNodeCommunicationEnabled = true;
myCloudPool.TaskSlotsPerNode = 1;

Notitie

Als u probeert een taak met meerdere exemplaren uit te voeren in een pool met communicatie tussen knooppunten uitgeschakeld of met een taskSlotsPerNode-waarde die groter is dan 1, wordt de taak nooit gepland. De taak blijft voor onbepaalde tijd in de status Actief.

Een StartTask gebruiken om MPI te installeren

Als u MPI-toepassingen wilt uitvoeren met een taak met meerdere exemplaren, moet u eerst een MPI-implementatie (MS-MPI of Intel MPI, bijvoorbeeld) installeren op de rekenknooppunten in de pool. Dit is een goed moment om een StartTask te gebruiken, die wordt uitgevoerd wanneer een knooppunt lid wordt van een pool of opnieuw wordt opgestart. Met dit codefragment maakt u een StartTask waarmee het MS-MPI-installatiepakket als resourcebestand wordt opgegeven. De opdrachtregel van de starttaak wordt uitgevoerd nadat het resourcebestand is gedownload naar het knooppunt. In dit geval voert de opdrachtregel een installatie zonder toezicht van MS-MPI uit.

// Create a StartTask for the pool which we use for installing MS-MPI on
// the nodes as they join the pool (or when they are restarted).
StartTask startTask = new StartTask
{
    CommandLine = "cmd /c MSMpiSetup.exe -unattend -force",
    ResourceFiles = new List<ResourceFile> { new ResourceFile("https://mystorageaccount.blob.core.windows.net/mycontainer/MSMpiSetup.exe", "MSMpiSetup.exe") },
    UserIdentity = new UserIdentity(new AutoUserSpecification(elevationLevel: ElevationLevel.Admin)),
    WaitForSuccess = true
};
myCloudPool.StartTask = startTask;

// Commit the fully configured pool to the Batch service to actually create
// the pool and its compute nodes.
await myCloudPool.CommitAsync();

Remote Direct Memory Access (RDMA)

Wanneer u een rdma-compatibele grootte kiest, zoals A9 voor de rekenknooppunten in uw Batch-pool, kan uw MPI-toepassing gebruikmaken van het RDMA-netwerk (High Performance, Low-Latency Remote Direct Memory Access) van Azure.

Zoek naar de grootten die zijn opgegeven als RDMA in Grootten voor virtuele machines in Azure (voor VirtualMachineConfiguration-pools) of Grootten voor Cloud Services (voor CloudServicesConfiguration-pools).

Notitie

Als u wilt profiteren van RDMA op Linux-rekenknooppunten, moet u Intel MPI op de knooppunten gebruiken.

Een taak met meerdere exemplaren maken met Batch .NET

Nu we de poolvereisten en mpI-pakketinstallatie hebben behandeld, gaan we de taak met meerdere exemplaren maken. In dit codefragment maken we een standaard CloudTask en configureren we vervolgens de eigenschap MultiInstanceSettings . Zoals eerder vermeld, is de taak met meerdere exemplaren geen afzonderlijk taaktype, maar een standaard Batch-taak die is geconfigureerd met instellingen voor meerdere exemplaren.

// Create the multi-instance task. Its command line is the "application command"
// and will be executed *only* by the primary, and only after the primary and
// subtasks execute the CoordinationCommandLine.
CloudTask myMultiInstanceTask = new CloudTask(id: "mymultiinstancetask",
    commandline: "cmd /c mpiexec.exe -wdir %AZ_BATCH_TASK_SHARED_DIR% MyMPIApplication.exe");

// Configure the task's MultiInstanceSettings. The CoordinationCommandLine will be executed by
// the primary and all subtasks.
myMultiInstanceTask.MultiInstanceSettings =
    new MultiInstanceSettings(numberOfNodes) {
    CoordinationCommandLine = @"cmd /c start cmd /c ""%MSMPI_BIN%\smpd.exe"" -d",
    CommonResourceFiles = new List<ResourceFile> {
    new ResourceFile("https://mystorageaccount.blob.core.windows.net/mycontainer/MyMPIApplication.exe",
                     "MyMPIApplication.exe")
    }
};

// Submit the task to the job. Batch will take care of splitting it into subtasks and
// scheduling them for execution on the nodes.
await myBatchClient.JobOperations.AddTaskAsync("mybatchjob", myMultiInstanceTask);

Primaire taak en subtaken

Wanneer u de instellingen voor meerdere exemplaren voor een taak maakt, geeft u het aantal rekenknooppunten op dat de taak moet uitvoeren. Wanneer u de taak naar een taak verzendt, maakt de Batch-service één primaire taak en voldoende subtaken die overeenkomen met het aantal opgegeven knooppunten.

Aan deze taken wordt een geheel getal-id toegewezen in het bereik van 0 aan numberOfInstances - 1. De taak met id 0 is de primaire taak en alle andere id's zijn subtaken. Als u bijvoorbeeld de volgende instellingen voor meerdere exemplaren voor een taak maakt, heeft de primaire taak een id van 0 en hebben de subtaken id's 1 tot en met 9.

int numberOfNodes = 10;
myMultiInstanceTask.MultiInstanceSettings = new MultiInstanceSettings(numberOfNodes);

Hoofdknooppunt

Wanneer u een taak met meerdere exemplaren verzendt, wijst de Batch-service een van de rekenknooppunten aan als het hoofdknooppunt en plant de primaire taak die moet worden uitgevoerd op het hoofdknooppunt. De subtaken worden gepland om uit te voeren op de rest van de knooppunten die zijn toegewezen aan de taak met meerdere exemplaren.

Coördinatieopdracht

De coördinatieopdracht wordt uitgevoerd door zowel de primaire als subtaken.

De aanroep van de coördinatieopdracht blokkeert--Batch voert de toepassingsopdracht pas uit als de coördinatieopdracht is geretourneerd voor alle subtaken. De coördinatieopdracht moet daarom alle vereiste achtergrondservices starten, controleren of ze gereed zijn voor gebruik en vervolgens afsluiten. Deze coördinatieopdracht voor een oplossing met MS-MPI versie 7 start bijvoorbeeld de SMPD-service op het knooppunt en sluit vervolgens:

cmd /c start cmd /c ""%MSMPI_BIN%\smpd.exe"" -d

Let op het gebruik van start deze coördinatieopdracht. Dit is vereist omdat de smpd.exe toepassing niet direct na de uitvoering wordt geretourneerd. Zonder het gebruik van de startopdracht zou deze coördinatieopdracht niet worden geretourneerd en zou de toepassingsopdracht daarom niet worden uitgevoerd.

Toepassingsopdracht

Zodra de primaire taak en alle subtaken klaar zijn met het uitvoeren van de coördinatieopdracht, wordt de opdrachtregel van de taak met meerdere exemplaren alleen uitgevoerd door de primaire taak. We noemen deze de toepassingsopdracht om deze te onderscheiden van de coördinatieopdracht.

Voor MS-MPI-toepassingen gebruikt u de toepassingsopdracht om uw MPI-toepassing uit te voeren met mpiexec.exe. Hier volgt bijvoorbeeld een toepassingsopdracht voor een oplossing met MS-MPI versie 7:

cmd /c ""%MSMPI_BIN%\mpiexec.exe"" -c 1 -wdir %AZ_BATCH_TASK_SHARED_DIR% MyMPIApplication.exe

Notitie

Omdat MS-MPI mpiexec.exe de CCP_NODES variabele standaard gebruikt (zie Omgevingsvariabelen), sluit de bovenstaande voorbeeldtoepassingsopdrachtregel deze uit.

Omgevingsvariabelen

Batch maakt verschillende omgevingsvariabelen die specifiek zijn voor taken met meerdere exemplaren op de rekenknooppunten die zijn toegewezen aan een taak met meerdere exemplaren. Uw coördinatie- en toepassingsopdrachten kunnen verwijzen naar deze omgevingsvariabelen, net zoals de scripts en programma's die ze uitvoeren.

De volgende omgevingsvariabelen worden gemaakt door de Batch-service voor gebruik door taken met meerdere exemplaren:

  • CCP_NODES
  • AZ_BATCH_NODE_LIST
  • AZ_BATCH_HOST_LIST
  • AZ_BATCH_MASTER_NODE
  • AZ_BATCH_TASK_SHARED_DIR
  • AZ_BATCH_IS_CURRENT_NODE_MASTER

Zie Omgevingsvariabelen voor Rekenknooppunten voor volledige informatie over deze en de andere omgevingsvariabelen voor Batch-rekenknooppunten, inclusief de inhoud en zichtbaarheid.

Tip

Het Voorbeeld van MPI-code voor Batch Linux bevat een voorbeeld van hoe verschillende van deze omgevingsvariabelen kunnen worden gebruikt.

Resourcebestanden

Er zijn twee sets resourcebestanden waarmee u rekening moet houden voor taken met meerdere exemplaren: algemene resourcebestanden die alle taken downloaden (zowel primaire als subtaken) en de resourcebestanden die zijn opgegeven voor de taak met meerdere exemplaren zelf, die alleen de primaire taak downloadt.

U kunt een of meer algemene resourcebestanden opgeven in de instellingen voor meerdere exemplaren voor een taak. Deze algemene resourcebestanden worden gedownload van Azure Storage naar de gedeelde map van elk knooppunt door de primaire en alle subtaken. U hebt toegang tot de gedeelde taakmap vanuit de opdrachtregels voor toepassingen en coördinatie met behulp van de AZ_BATCH_TASK_SHARED_DIR omgevingsvariabele. Het AZ_BATCH_TASK_SHARED_DIR pad is identiek op elk knooppunt dat is toegewezen aan de taak met meerdere exemplaren, zodat u één coördinatieopdracht tussen de primaire en alle subtaken kunt delen. Batch deelt de map niet in een externe toegangszin, maar u kunt deze gebruiken als koppel- of sharepunt zoals eerder vermeld in de tip over omgevingsvariabelen.

Resourcebestanden die u opgeeft voor de taak met meerdere exemplaren zelf, worden standaard gedownload naar de werkmap AZ_BATCH_TASK_WORKING_DIRvan de taak. Zoals vermeld, downloadt alleen de primaire taak resourcebestanden die zijn opgegeven voor de taak met meerdere exemplaren zelf.

Belangrijk

Gebruik altijd de omgevingsvariabelen AZ_BATCH_TASK_SHARED_DIR en AZ_BATCH_TASK_WORKING_DIR raadpleeg deze mappen in uw opdrachtregels. Probeer de paden niet handmatig samen te stellen.

Levensduur van taak

De levensduur van de primaire taak bepaalt de levensduur van de volledige taak met meerdere exemplaren. Wanneer de primaire uitgangen worden beëindigd, worden alle subtaken beëindigd. De afsluitcode van de primaire is de afsluitcode van de taak en wordt daarom gebruikt om het slagen of mislukken van de taak te bepalen voor nieuwe pogingen.

Als een van de subtaken mislukt, mislukt het afsluiten met een retourcode zonder nul, bijvoorbeeld de volledige taak met meerdere exemplaren. De taak met meerdere exemplaren wordt vervolgens beëindigd en opnieuw geprobeerd, tot aan de limiet voor opnieuw proberen.

Wanneer u een taak met meerdere exemplaren verwijdert, worden de primaire en alle subtaken ook verwijderd door de Batch-service. Alle subtakenmappen en hun bestanden worden verwijderd uit de rekenknooppunten, net als voor een standaardtaak.

TaskConstraints voor een taak met meerdere exemplaren, zoals de eigenschappen MaxTaskRetryCount, MaxWallClockTime en RetentionTime , worden gehonoreerd als voor een standaardtaak en zijn van toepassing op de primaire en alle subtaken. Als u echter de eigenschapRetentionTime wijzigt nadat u de taak met meerdere exemplaren aan de taak hebt toegevoegd, wordt deze wijziging alleen toegepast op de primaire taak en blijven alle subtaken de oorspronkelijke RetentionTime gebruiken.

De recente takenlijst van een rekenknooppunt weerspiegelt de id van een subtaak als de recente taak deel uitmaakt van een taak met meerdere exemplaren.

Informatie over subtaken verkrijgen

Als u informatie over subtaken wilt verkrijgen met behulp van de Batch .NET-bibliotheek, roept u de methode CloudTask.ListSubtasks aan. Deze methode retourneert informatie over alle subtaken en informatie over het rekenknooppunt dat de taken heeft uitgevoerd. Op basis van deze informatie kunt u de hoofdmap van elke subtaak, de pool-id, de huidige status, afsluitcode en meer bepalen. U kunt deze informatie gebruiken in combinatie met de methode PoolOperations.GetNodeFile om de bestanden van de subtaak te verkrijgen. Houd er rekening mee dat deze methode geen informatie retourneert voor de primaire taak (id 0).

Notitie

Tenzij anders vermeld, zijn Batch .NET-methoden die op de CloudTask met meerdere exemplaren werken alleen van toepassing op de primaire taak. Wanneer u bijvoorbeeld de methode CloudTask.ListNodeFiles aanroept voor een taak met meerdere exemplaren, worden alleen de bestanden van de primaire taak geretourneerd.

In het volgende codefragment ziet u hoe u subtaakgegevens kunt verkrijgen en hoe u bestandsinhoud aanvraagt van de knooppunten waarop ze zijn uitgevoerd.

// Obtain the job and the multi-instance task from the Batch service
CloudJob boundJob = batchClient.JobOperations.GetJob("mybatchjob");
CloudTask myMultiInstanceTask = boundJob.GetTask("mymultiinstancetask");

// Now obtain the list of subtasks for the task
IPagedEnumerable<SubtaskInformation> subtasks = myMultiInstanceTask.ListSubtasks();

// Asynchronously iterate over the subtasks and print their stdout and stderr
// output if the subtask has completed
await subtasks.ForEachAsync(async (subtask) =>
{
    Console.WriteLine("subtask: {0}", subtask.Id);
    Console.WriteLine("exit code: {0}", subtask.ExitCode);

    if (subtask.State == SubtaskState.Completed)
    {
        ComputeNode node =
            await batchClient.PoolOperations.GetComputeNodeAsync(subtask.ComputeNodeInformation.PoolId,
                                                                 subtask.ComputeNodeInformation.ComputeNodeId);

        NodeFile stdOutFile = await node.GetNodeFileAsync(subtask.ComputeNodeInformation.TaskRootDirectory + "\\" + Constants.StandardOutFileName);
        NodeFile stdErrFile = await node.GetNodeFileAsync(subtask.ComputeNodeInformation.TaskRootDirectory + "\\" + Constants.StandardErrorFileName);
        stdOut = await stdOutFile.ReadAsStringAsync();
        stdErr = await stdErrFile.ReadAsStringAsync();

        Console.WriteLine("node: {0}:", node.Id);
        Console.WriteLine("stdout.txt: {0}", stdOut);
        Console.WriteLine("stderr.txt: {0}", stdErr);
    }
    else
    {
        Console.WriteLine("\tSubtask {0} is in state {1}", subtask.Id, subtask.State);
    }
});

Codevoorbeeld

Het codevoorbeeld MultiInstanceTasks op GitHub laat zien hoe u een taak met meerdere exemplaren gebruikt om een MS-MPI-toepassing uit te voeren op Batch-rekenknooppunten. Volg de onderstaande stappen om het voorbeeld uit te voeren.

Voorbereiding

  1. Download de MS-MPI SDK en Redist-installatieprogramma's en installeer deze. Na de installatie kunt u controleren of de MS-MPI-omgevingsvariabelen zijn ingesteld.
  2. Bouw een releaseversie van het MPIHelloWorld-voorbeeld-MPI-programma . Dit is het programma dat wordt uitgevoerd op rekenknooppunten door de taak met meerdere exemplaren.
  3. Maak een zip-bestand met MPIHelloWorld.exe (dat u in stap 2 hebt gemaakt) en MSMpiSetup.exe (die u in stap 1 hebt gedownload). In de volgende stap uploadt u dit zip-bestand als een toepassingspakket.
  4. Gebruik de Azure Portal om een Batch-toepassing met de naam MPIHelloWorld te maken en geef het zip-bestand op dat u in de vorige stap hebt gemaakt als versie 1.0 van het toepassingspakket. Zie Upload en beheer toepassingen voor meer informatie.

Tip

Het bouwen van een releaseversie zorgt MPIHelloWorld.exe ervoor dat u geen aanvullende afhankelijkheden (bijvoorbeeld msvcp140d.dll ) vcruntime140d.dllin uw toepassingspakket hoeft op te nemen.

Uitvoering

  1. Download het bestand azure-batch-samples .zip van GitHub.

  2. Open de multiInstanceTasks-oplossing in Visual Studio 2019. Het MultiInstanceTasks.sln oplossingsbestand bevindt zich in:

    azure-batch-samples\CSharp\ArticleProjects\MultiInstanceTasks\

  3. Voer uw Batch- en Storage-accountreferenties in AccountSettings.settings het project Microsoft.Azure.Batch.Samples.Common in.

  4. Bouw en voer de MultiInstanceTasks-oplossing uit om de MPI-voorbeeldtoepassing uit te voeren op rekenknooppunten in een Batch-pool.

  5. Optioneel: Gebruik de Azure Portal of Batch Explorer om de voorbeeldgroep, taak en taak te onderzoeken ('MultiInstanceSamplePool', 'MultiInstanceSampleJob', 'MultiInstanceSampleTask') voordat u de resources verwijdert.

Tip

U kunt Visual Studio Community gratis downloaden als u nog geen Visual Studio hebt.

Uitvoer van MultiInstanceTasks.exe is vergelijkbaar met het volgende:

Creating pool [MultiInstanceSamplePool]...
Creating job [MultiInstanceSampleJob]...
Adding task [MultiInstanceSampleTask] to job [MultiInstanceSampleJob]...
Awaiting task completion, timeout in 00:30:00...

Main task [MultiInstanceSampleTask] is in state [Completed] and ran on compute node [tvm-1219235766_1-20161017t162002z]:
---- stdout.txt ----
Rank 2 received string "Hello world" from Rank 0
Rank 1 received string "Hello world" from Rank 0

---- stderr.txt ----

Main task completed, waiting 00:00:10 for subtasks to complete...

---- Subtask information ----
subtask: 1
        exit code: 0
        node: tvm-1219235766_3-20161017t162002z
        stdout.txt:
        stderr.txt:
subtask: 2
        exit code: 0
        node: tvm-1219235766_2-20161017t162002z
        stdout.txt:
        stderr.txt:

Delete job? [yes] no: yes
Delete pool? [yes] no: yes

Sample complete, hit ENTER to exit...

Volgende stappen