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

Úlohy s více instancemi umožňují spustit Azure Batch úlohu na více výpočetních uzlech současně. Tyto úlohy umožňují ve službě Batch scénáře vysokovýkonných výpočetních prostředí, jako jsou aplikace MPI (Message Passing Interface). V tomto článku se dozvíte, jak provádě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 linuxových uzlech).

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 – do úlohy odešlete více úkolů a služba Batch naplánuje spuštění každého úkolu na uzlu. Konfigurací nastavení více instancí úkolu však službě Batch sdělíte, 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í více instancí

Když do úlohy odešlete úkol s nastavením s více instancemi, služba Batch provede několik kroků, které jsou jedinečné pro úkoly s více instancemi:

  1. Služba Batch vytvoří jeden primární a několik dílčích úkoly na základě nastavení více instancí. 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 určí jeden z výpočetních uzlů jako hlavní a naplánuje spuštění primární úlohy na hlavním serveru. Naplánuje provádění dílčích úkolů na zbývajících výpočetních uzlech přidělených k úloze s více instancemi, a to jeden dílčí úkol na každý uzel.
  3. Primární a všechny dílčí úkoly stahují všechny společné soubory prostředků , které zadáte v nastavení více instancí.
  4. Po stažení běžných souborů prostředků spustí primární a dílčí úkoly příkaz pro koordinaci , který zadáte v nastavení více instancí. Příkaz pro koordinaci se obvykle používá k přípravě uzlů na provedení úkolu. To může zahrnovat spuštění služeb na pozadí (například microsoft MPIsmpd.exe) a ověření, že uzly jsou připravené ke zpracování zpráv mezi uzly.
  5. Primární úkol spustí příkaz aplikace na hlavním uzlu po úspěšném dokončení příkazu pro koordinaci primárním a všemi dílčími úkoly. Příkaz aplikace je příkazovým řádkem samotné úlohy s více instancemi a provádí ho pouze primární úkol. V řešení založeném na MS-MPI je to místo, kde spustíte aplikaci s podporou MPI pomocí mpiexec.exe.

Poznámka

I když je úloha s více instancemi funkčně odlišná, není jedinečným typem úlohy jako StartTask nebo JobPreparationTask. Úloha s více instancemi je jednoduše standardní úloha služby Batch (CloudTask ve službě Batch .NET), jejíž nastavení více instancí 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 úloh. Pokud chcete zakázat souběžné spouštění úloh, nastavte vlastnost CloudPool.TaskSlotsPerNode na hodnotu 1.

Poznámka

Služba 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 uzly nebo s hodnotou taskSlotsPerNode větší než 1, úloha se nikdy neplánuje – zůstane po neomezenou dobu ve stavu aktivní.

Fondy s povolenou funkcí InterComputeNodeCommunication neumožní automatické zrušení zřízení uzlu.

Použití StartTask k instalaci MPI

Pokud chcete spouštět aplikace MPI s úlohou s více instancemi, musíte nejprve na výpočetní uzly ve fondu nainstalovat implementaci MPI (například MS-MPI nebo Intel MPI). V tuto chvíli je vhodné použít startTask, který se spustí vždy, když se uzel připojí k fondu nebo se restartuje. 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();

Přímý přístup do paměti vzdáleného počítače (RDMA)

Když pro výpočetní uzly ve fondu Batch zvolíte velikost podporující RDMA , například A9, může vaše aplikace MPI využívat vysoce výkonnou síť Azure s přímým přístupem do vzdálené paměti (RDMA) s nízkou latencí.

V části Velikosti pro virtuální počítače v Azure (fondy VirtualMachineConfiguration) nebo Velikosti pro Cloud Services (pro fondy CloudServicesConfiguration) vyhledejte velikosti uvedené jako "Podporuje RDMA".

Poznámka

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

Vytvoření úlohy s více instancemi ve službě 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ím úkolem služby Batch nakonfigurovaným s nastavením pro 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í a dílčí úkoly

Při vytváření nastavení více instancí pro úlohu zadáte počet výpočetních uzlů, které mají úlohu provést. 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 se přiřadí celočíselné ID v rozsahu od 0 do numberOfInstances – 1. Úkol s ID 0 je primární úkol a všechna ostatní ID jsou dílčí úkoly. Pokud například pro úkol vytvoříte následující nastavení s více instancemi, 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 úkol s více instancemi, služba Batch určí jeden z výpočetních uzlů jako "hlavní" uzel a naplánuje spuštění primárního úkolu na hlavním uzlu. Dílčí úkoly jsou naplánované tak, aby se spouštěly na zbývajících uzlech přidělených k úloze s více instancemi.

Příkaz pro koordinaci

Příkaz pro koordinaci provádí primární i dílčí úkoly.

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

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

Všimněte si použití v tomto koordinačním start příkazu. To je povinné, smpd.exe protože aplikace se nevrací okamžitě po spuštění. Bez použití spouštěcího příkazu by se tento příkaz pro koordinaci 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 úkolu s více instancemi se provede pouze primární úlohou. Tento příkaz nazýváme příkaz aplikace , abychom ho odlišili od příkazu pro koordinaci.

V případě aplikací MS-MPI spusťte aplikaci s podporou MPI pomocí mpiexec.exepříkazu aplikace . 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á proměnnou CCP_NODES ve výchozím nastavení (viz Proměnné prostředí), ukázkový příkazový řádek aplikace výše ji vylučuje.

Proměnné prostředí

Služba Batch vytvoří několik proměnných prostředí specifických pro úkoly s více instancemi na výpočetních uzlech přidělených k úkolu s více instancemi. Na tyto proměnné prostředí mohou odkazovat vaše koordinační a aplikační příkazové řádky, stejně jako skripty a programy, které spouští.

Služba Batch vytváří následující proměnné prostředí pro úlohy 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ího uzlu.

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 vzít v úvahu pro úlohy s více instancemi: společné soubory prostředků , které stahují všechny úkoly (primární i dílčí úkoly), a soubory prostředků zadané pro samotný úkol s více instancemi, které stahuje jenom primární úkol.

V nastavení více instancí pro úlohu můžete zadat jeden nebo více běžných souborů prostředků . Tyto společné soubory prostředků se stahují ze služby Azure Storage do sdíleného adresáře úkolů každého uzlu primárním a všemi dílčími úkoly. Ke sdílenému adresáři úkolů můžete přistupovat z příkazového řádku aplikace a koordinace pomocí AZ_BATCH_TASK_SHARED_DIR proměnné prostředí. Cesta AZ_BATCH_TASK_SHARED_DIR je stejná na každém uzlu přiděleném úkolu 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 "nesdílí" adresář 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 k proměnným 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 úlohy. Jak už bylo zmíněno, na rozdíl od běžných souborů prostředků stahuje soubory prostředků zadané pro samotnou úlohu s více instancemi pouze primární úkol.

Důležité

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

Doba života úkolu

Životnost primární úlohy řídí životnost celé úlohy s více instancemi. Při ukončení primárního serveru se všechny dílčí úkoly ukončí. Ukončovací kód primární úlohy je ukončovací kód úlohy, a proto se používá k určení úspěchu nebo selhání úlohy pro účely opakování.

Pokud některý z dílčích úkolů selže a ukončí se například s nenulovým návratovým kódem, celá úloha s více instancemi selže. Úloha s více instancemi se pak ukončí a zopakuje 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í úlohy.

Omezení úlohy s více instancemi, jako jsou vlastnosti MaxTaskRetryCount, MaxWallClockTime a RetentionTime , se dodržují stejně jako u standardní úlohy a platí pro primární a všechny dílčí úkoly. Pokud však změníte vlastnostRetentionTime po přidání úlohy s více instancemi do úlohy, 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.

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

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

Pokud chcete získat informace o dílčích úkolech pomocí knihovny Batch .NET, zavolejte metodu CloudTask.ListSubtasks . Tato metoda vrací informace o všech dílčích úkolech a informace o výpočetním uzlu, který úlohy provedl. Z těchto informací můžete určit kořenový adresář jednotlivých dílčích úloh, 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čího úkolu. 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. Například když zavoláte metodu CloudTask.ListNodeFiles u úlohy s více instancemi, vrátí se pouze soubory primární úlohy.

Následující fragment kódu ukazuje, jak získat informace o dílčích úkolech a také požádat o 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 Služby Batch. Pokud chcete ukázku spustit, postupujte 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 byly nastaveny proměnné prostředí MS-MPI.
  2. Sestavte vydanou verzi ukázkového programu MPIHelloWorld . Toto je program, který bude spuštěn na výpočetních uzlech úlohou s více instancemi.
  3. Vytvořte soubor ZIP obsahující MPIHelloWorld.exe soubor (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í 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ávání a správa aplikací .

Tip

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

Spuště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 k AccountSettings.settings účtu Batch a Storage.

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

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

Tip

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

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