Sdílet prostřednictvím


Použití úloh s více instancemi ke spuštění aplikací MPI (Message Passing Interface) ve službě Batch

Úlohy s více instancemi umožňují spustit úlohu Služby Azure Batch na několika výpočetních uzlech současně. Tyto úlohy umožňují scénáře vysokovýkonných výpočetních prostředí, jako jsou aplikace MPI (Message Passing Interface) ve službě Batch. V tomto článku se dozvíte, jak spouštět úlohy s více instancemi pomocí knihovny Batch .NET .

Poznámka:

I když se příklady v tomto článku zaměřují na výpočetní uzly Batch .NET, MS-MPI a Windows, koncepty úloh s více instancemi, které jsou zde popsány, platí pro jiné platformy a technologie (například Python a Intel MPI na uzlech Linuxu).

Přehled úloh s více instancemi

Ve službě Batch se každý úkol obvykle spouští na jednom výpočetním uzlu – odešlete do úlohy více úkolů a služba Batch naplánuje každou úlohu pro spuštění na uzlu. Konfigurací nastavení více instancí úlohy však službě Batch řeknete, aby místo toho vytvořila jeden primární úkol a několik dílčích úkolů, které se pak spustí na více uzlech.

Diagram znázorňující přehled nastavení s více instancemi

Když do úlohy odešlete úlohu s nastavením více instancí, služba Batch provede několik kroků jedinečných pro úlohy s více instancemi:

  1. Služba Batch vytvoří jednu primární a několik dílčích dílčích funkcí na základě nastavení s více instancemi. Celkový počet úkolů (primární a všechny dílčí úkoly) odpovídá počtu instancí (výpočetních uzlů), které zadáte v nastavení více instancí.
  2. Služba Batch označí jeden z výpočetních uzlů jako hlavní uzel a naplánuje spuštění primární úlohy na hlavním serveru. Naplánuje dílčí úkoly tak, aby se spouštěly na zbývajících výpočetních uzlech přidělených úloze s více instancemi, jeden dílčí úkol na uzel.
  3. Primární a všechny dílčí úkoly stáhnou všechny běžné soubory prostředků, které zadáte v nastavení s více instancemi.
  4. Po stažení běžných souborů prostředků spustí primární a dílčí úkoly příkaz koordinace, který zadáte v nastavení s více instancemi. Příkaz koordinace se obvykle používá k přípravě uzlů pro provádění úlohy. Může to zahrnovat spuštění služeb na pozadí (například rozhraní MPI smpd.exemicrosoftu) a ověření, že uzly jsou připravené ke zpracování zpráv mezi uzly.
  5. Primární úloha spustí příkaz aplikace na hlavním uzlu po úspěšném dokončení koordinačního příkazu primárním a všemi dílčími úkoly. Příkaz aplikace je příkazový řádek samotné úlohy s více instancemi a spouští se pouze primární úlohou. V řešení založeném na MS-MPI se jedná o místo, kde spouštíte aplikaci s podporou MPI pomocí mpiexec.exe.

Poznámka:

I když je funkčně odlišný, "úloha s více instancemi" není jedinečný typ úlohy, jako je StartTask nebo JobPreparationTask. Úloha s více instancemi je jednoduše standardní úlohou služby Batch (CloudTask ve službě Batch .NET), jejíž nastavení s více instancemi bylo nakonfigurováno. V tomto článku to označujeme jako úlohu s více instancemi.

Požadavky na úlohy s více instancemi

Úlohy s více instancemi vyžadují fond s povolenou komunikací mezi uzly a se zakázaným souběžným spouštěním úkolů. Chcete-li zakázat souběžné provádění úloh, nastavte Vlastnost CloudPool.TaskSlotsPerNode na hodnotu 1.

Poznámka:

Batch omezuje velikost fondu, který má povolenou komunikaci mezi uzly.

Tento fragment kódu ukazuje, jak vytvořit fond pro úlohy s více instancemi pomocí knihovny Batch .NET.

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;

Poznámka:

Pokud se pokusíte spustit úlohu s více instancemi ve fondu se zakázanou komunikací mezi uzlu nebo s hodnotou taskSlotsPerNode větší než 1, není úloha nikdy naplánovaná – zůstane trvale ve stavu "aktivní".

Fondy s povoleným InterComputeNodeCommunication nepovolí automatické zrušení zřízení uzlu.

Instalace MPI pomocí StartTask

Pokud chcete spouštět aplikace MPI s úlohou s více instancemi, musíte napřed nainstalovat implementaci MPI (MS-MPI nebo Intel MPI) na výpočetní uzly ve fondu. Je vhodná doba k použití startTask, která se spustí při každém připojení uzlu k fondu nebo restartování. Tento fragment kódu vytvoří StartTask, který určuje instalační balíček MS-MPI jako soubor prostředků. Příkazový řádek spouštěcího úkolu se spustí po stažení souboru prostředků do uzlu. V tomto případě příkazový řádek provede bezobslužnou instalaci ms-MPI.

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

Vzdálený přímý přístup do paměti (RDMA)

Když zvolíte velikost podporující RDMA, jako je A9 pro výpočetní uzly ve fondu Batch, může aplikace MPI využívat vysoce výkonné a nízko latence vzdáleného přímého přístupu do paměti (RDMA) Azure.

Vyhledejte velikosti určené jako "podpora RDMA" ve velikostech pro virtuální počítače v Azure (pro fondy VirtualMachineConfiguration) nebo velikosti pro cloudové služby (pro fondy CloudServicesConfiguration).

Poznámka:

Pokud chcete využít RDMA na výpočetních uzlech s Linuxem, musíte na uzlech použít Intel MPI .

Vytvoření úlohy s více instancemi pomocí batch .NET

Teď, když jsme probrali požadavky na fond a instalaci balíčku MPI, vytvoříme úlohu s více instancemi. V tomto fragmentu kódu vytvoříme standardní CloudTask a pak nakonfigurujeme jeho vlastnost MultiInstanceSettings . Jak už bylo zmíněno dříve, úloha s více instancemi není odlišným typem úlohy, ale standardní úloha Batch nakonfigurovaná s nastavením více instancí.

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

Primární úkol a dílčí úkoly

Když pro úlohu vytvoříte nastavení s více instancemi, zadáte počet výpočetních uzlů, které mají být spuštěny. Když úkol odešlete do úlohy, služba Batch vytvoří jeden primární úkol a dostatek dílčích úkolů , které společně odpovídají zadanému počtu uzlů.

Těmto úkolům je přiřazeno celé číslo v rozsahu 0 až numberOfInstances – 1. Úkol s ID 0 je primárním úkolem a všechny ostatní ID jsou dílčí úkoly. Pokud například vytvoříte následující nastavení více instancí pro úlohu, primární úkol bude mít ID 0 a dílčí úkoly budou mít ID 1 až 9.

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

Hlavní uzel

Když odešlete úlohu s více instancemi, služba Batch označí jeden z výpočetních uzlů jako hlavní uzel a naplánuje, aby se primární úkol spustil na hlavním uzlu. Dílčí úkoly se plánují tak, aby se spouštěly ve zbývajících uzlech přidělených úloze s více instancemi.

Příkaz koordinace

Příkaz koordinace se provádí jak primárním, tak dílčím úkoly.

Vyvolání koordinačního příkazu je blocking - Batch nespustí příkaz aplikace, dokud se příkaz koordinace úspěšně nevrátil pro všechny dílčí úkoly. Příkaz koordinace by proto měl spustit všechny požadované služby na pozadí, ověřit, že jsou připravené k použití, a pak ukončit. Například tento koordinační příkaz pro řešení používající MS-MPI verze 7 spustí službu SMPD na uzlu a pak ukončí:

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

Všimněte si použití tohoto koordinačního start příkazu. To je povinné, protože smpd.exe aplikace se nevrací okamžitě po spuštění. Bez použití spouštěcího příkazu by se tento příkaz koordinace nevrátil, a proto by zablokoval spuštění příkazu aplikace.

Příkaz aplikace

Jakmile primární úkol a všechny dílčí úkoly dokončí provádění koordinačního příkazu, příkazový řádek úlohy s více instancemi se spustí pouze primárním úkolem. Říkáme tomu příkaz aplikace, abychom ho odlišili od koordinačního příkazu.

V případě aplikací MS-MPI pomocí příkazu aplikace spusťte aplikaci s povoleným rozhraním MPI .mpiexec.exe Tady je například příkaz aplikace pro řešení používající MS-MPI verze 7:

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

Poznámka:

Vzhledem k tomu, že ms-MPI mpiexec.exe používá CCP_NODES proměnnou ve výchozím nastavení (viz Proměnné prostředí), ukázkový příkazový řádek aplikace výše ji vyloučí.

Proměnné prostředí

Služba Batch vytvoří několik proměnných prostředí specifických pro úlohy s více instancemi na výpočetních uzlech přidělených k úloze s více instancemi. Příkazové řádky koordinace a aplikace můžou odkazovat na tyto proměnné prostředí, stejně jako skripty a programy, které spouští.

Následující proměnné prostředí jsou vytvořeny službou Batch pro použití úlohami s více instancemi:

  • 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

Úplné podrobnosti o těchto a dalších proměnných prostředí výpočetních uzlů služby Batch, včetně jejich obsahu a viditelnosti, najdete v tématu Proměnné prostředí výpočetních uzlů.

Tip

Ukázka kódu MPI služby Batch Linux obsahuje příklad použití několika těchto proměnných prostředí.

Soubory prostředků

Existují dvě sady souborů prostředků, které je potřeba zvážit pro úlohy s více instancemi: běžné soubory prostředků, které všechny úkoly stahují (primární i dílčí úkoly) a soubory prostředků určené pro samotnou úlohu s více instancemi, které stahuje pouze primární úkol.

V nastavení více instancí pro úlohu můžete zadat jeden nebo více běžných souborů prostředků. Tyto běžné soubory prostředků se stáhnou ze služby Azure Storage do sdíleného adresáře každého uzlu primárním a všemi dílčími úkoly. Ke sdílenému adresáři úlohy můžete přistupovat z aplikace a z příkazového řádku koordinace pomocí AZ_BATCH_TASK_SHARED_DIR proměnné prostředí. Cesta AZ_BATCH_TASK_SHARED_DIR je identická na každém uzlu přiděleném úloze s více instancemi, takže můžete sdílet jeden koordinační příkaz mezi primárním a všemi dílčími úkoly. Služba Batch adresář nesdílí ve smyslu vzdáleného přístupu, ale můžete ho použít jako přípojný nebo sdílený bod, jak je uvedeno výše v tipu o proměnných prostředí.

Soubory prostředků, které zadáte pro samotnou úlohu s více instancemi, AZ_BATCH_TASK_WORKING_DIRse ve výchozím nastavení stáhnou do pracovního adresáře úkolu. Jak už bylo zmíněno, na rozdíl od běžných souborů prostředků stahuje pouze primární úkol soubory prostředků určené pro samotnou úlohu s více instancemi.

Důležité

Vždy používejte proměnné AZ_BATCH_TASK_SHARED_DIR prostředí a AZ_BATCH_TASK_WORKING_DIR odkazujte na tyto adresáře v příkazových řádcích. Nepokoušejte se cesty sestavit ručně.

Doba života úkolu

Doba života primárního úkolu řídí životnost celého úkolu s více instancemi. Když se primární ukončí, ukončí se všechny dílčí úkoly. Ukončovací kód primárního kódu je ukončovací kód úkolu, který se proto používá k určení úspěšnosti nebo selhání úlohy pro účely opakování.

Pokud některý z dílčích úkolů selže, ukončí se s nenulovým návratovým kódem, například celá úloha s více instancemi selže. Úloha s více instancemi se pak ukončí a opakuje až do limitu opakování.

Když odstraníte úlohu s více instancemi, služba Batch odstraní také primární a všechny dílčí úkoly. Všechny adresáře dílčích úkolů a jejich soubory se z výpočetních uzlů odstraní stejně jako u standardního úkolu.

Omezení úloh pro úlohu s více instancemi, jako jsou MaxTaskRetryCount, MaxWallClockTime a RetentionTime vlastnosti, jsou dodrženy jako pro standardní úlohu a vztahují se na primární a všechny dílčí úkoly. Pokud však po přidání úlohy s více instancemi do úlohy změníte vlastnostRetentionTime, použije se tato změna pouze na primární úkol a všechny dílčí úkoly budou nadále používat původní retentionTime.

Poslední seznam úkolů výpočetního uzlu odráží ID dílčího úkolu, pokud byl poslední úkol součástí úkolu s více instancemi.

Získání informací o dílčích úkoly

Chcete-li získat informace o dílčích úkolech pomocí knihovny Batch .NET, zavolejte metodu CloudTask.ListSubtasks . Tato metoda vrátí informace o všech dílčích úkolech a informace o výpočetním uzlu, který spouštěl úlohy. Z těchto informací můžete určit kořenový adresář jednotlivých dílčích úkolů, ID fondu, jeho aktuální stav, ukončovací kód a další. Tyto informace můžete použít v kombinaci s Metodou PoolOperations.GetNodeFile k získání souborů dílčích úkolů. Všimněte si, že tato metoda nevrací informace pro primární úlohu (ID 0).

Poznámka:

Pokud není uvedeno jinak, metody Batch .NET, které pracují se samotnou službou CloudTask s více instancemi, se vztahují pouze na primární úlohu. Když například zavoláte metodu CloudTask.ListNodeFiles pro úlohu s více instancemi, vrátí se pouze soubory primárního úkolu.

Následující fragment kódu ukazuje, jak získat informace o dílčím úkolu a také požadovat obsah souboru z uzlů, na kterých se spustily.

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

Ukázka kódu

Ukázka kódu MultiInstanceTasks na GitHubu ukazuje, jak pomocí úlohy s více instancemi spustit aplikaci MS-MPI na výpočetních uzlech Batch. Ukázku spustíte podle následujících kroků.

Příprava

  1. Stáhněte si instalační programy sady MS-MPI SDK a Redist a nainstalujte je. Po instalaci můžete ověřit, že jsou nastavené proměnné prostředí MS-MPI.
  2. Sestavení verze ukázkového programu MPIHelloWorld Toto je program, který se bude spouštět na výpočetních uzlech úlohou s více instancemi.
  3. Vytvořte soubor ZIP obsahující MPIHelloWorld.exe (který jste vytvořili v kroku 2) a MSMpiSetup.exe (který jste stáhli v kroku 1). Tento soubor ZIP nahrajete jako balíček aplikace v dalším kroku.
  4. Pomocí webu Azure Portal vytvořte aplikaci Batch s názvem MPIHelloWorld a zadejte soubor ZIP, který jste vytvořili v předchozím kroku, jako verzi 1.0 balíčku aplikace. Další informace najdete v tématu Nahrání a správa aplikací .

Tip

Sestavení verze MPIHelloWorld.exe verze zajistí, že do balíčku aplikace nebudete muset zahrnout žádné další závislosti (například msvcp140d.dll nebovcruntime140d.dll).

Provádění

  1. Stáhněte si soubor azure-batch-samples .zip z GitHubu.

  2. Otevřete řešení MultiInstanceTasks v sadě Visual Studio 2019. Soubor MultiInstanceTasks.sln řešení se nachází v:

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

  3. V projektu Microsoft.Azure.Batch.Samples.Common zadejte přihlašovací údaje AccountSettings.settings k účtu Batch a Storage.

  4. Sestavte a spusťte řešení MultiInstanceTasks a spusťte ukázkovou aplikaci MPI na výpočetních uzlech ve fondu Batch.

  5. Volitelné: Před odstraněním prostředků pomocí webu Azure Portal nebo Batch Exploreru zkontrolujte ukázkový fond, úlohu a úlohu (MultiInstanceSamplePool, MultiInstanceSampleJob, MultiInstanceSampleTask).

Tip

Visual Studio Community si můžete zdarma stáhnout, pokud ještě sadu Visual Studio nemáte.

Výstup z MultiInstanceTasks.exe je podobný následujícímu:

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

Další kroky