Köra uppgifter samtidigt för att maximera användningen av Batch-beräkningsnoder

Du kan maximera resursanvändningen på ett mindre antal beräkningsnoder i poolen genom att köra mer än en aktivitet samtidigt på varje nod.

Vissa scenarier fungerar bäst med alla en nods resurser som är dedikerade till en enda aktivitet, men vissa arbetsbelastningar kan se kortare jobbtider och lägre kostnader när flera aktiviteter delar dessa resurser. Beakta följande scenarier:

  • Minimera dataöverföringen för uppgifter som kan dela data. Du kan avsevärt minska kostnaderna för dataöverföring genom att kopiera delade data till ett mindre antal noder och sedan köra uppgifter parallellt på varje nod. Detta gäller särskilt om data som ska kopieras till varje nod måste överföras mellan geografiska regioner.
  • Maximera minnesanvändningen för uppgifter som kräver en stor mängd minne, men bara under korta tidsperioder och vid varierande tidpunkter under körningen. Du kan använda färre, men större, beräkningsnoder med mer minne för att effektivt hantera sådana toppar. Dessa noder har flera aktiviteter som körs parallellt på varje nod, men varje uppgift kan dra nytta av nodernas rikliga minne vid olika tidpunkter.
  • Minska nodnummergränserna när kommunikation mellan noder krävs i en pool. För närvarande är pooler som konfigurerats för kommunikation mellan noder begränsade till 50 beräkningsnoder. Om varje nod i en sådan pool kan köra uppgifter parallellt kan ett större antal aktiviteter köras samtidigt.
  • Replikera ett lokalt beräkningskluster, till exempel när du först flyttar en beräkningsmiljö till Azure. Om din aktuella lokala lösning kör flera uppgifter per beräkningsnod kan du öka det maximala antalet nodaktiviteter för att bättre spegla den konfigurationen.

Exempel på ett scenario

Tänk dig till exempel ett uppgiftsprogram med processor- och minneskrav så att Standard_D1 noder är tillräckliga. Men för att slutföra jobbet inom den tid som krävs behövs 1 000 av dessa noder.

I stället för att använda Standard_D1 noder som har 1 CPU-kärna kan du använda Standard_D14 noder som har 16 kärnor vardera och aktivera parallell aktivitetskörning. Det innebär att 16 gånger färre noder kan användas – i stället för 1 000 noder krävs bara 63. Om stora programfiler eller referensdata krävs för varje nod förbättras jobbvaraktigheten och effektiviteten, eftersom data endast kopieras till 63 noder.

Aktivera parallell aktivitetskörning

Du konfigurerar beräkningsnoder för parallell aktivitetskörning på poolnivå. Med Batch .NET-biblioteket anger du egenskapen CloudPool.TaskSlotsPerNode när du skapar en pool. Om du använder Batch REST API anger du elementet taskSlotsPerNode i begärandetexten när poolen skapas.

Anteckning

Du kan bara ange taskSlotsPerNode egenskapen element och TaskSlotsPerNode när poolen skapas. De kan inte ändras när en pool redan har skapats.

Azure Batch kan du ange aktivitetsfack per nod upp till (4 x) antalet nodskärnor. Om poolen till exempel har konfigurerats med noder av storleken "Large" (fyra kärnor) taskSlotsPerNode kan den vara inställd på 16. Oavsett hur många kärnor noden har kan du dock inte ha fler än 256 aktivitetsfack per nod. Mer information om antalet kärnor för varje nodstorlek finns i Storlekar för Serviços de Nuvem. Mer information om tjänstbegränsningar finns i Kvoter och gränser för Azure Batch-tjänsten.

Tips

Tänk på att ta hänsyn taskSlotsPerNode till värdet när du skapar en autoskalningsformel för din pool. Till exempel kan en formel som utvärderas $RunningTasks påverkas dramatiskt av en ökning av aktiviteter per nod. Mer information finns i Skala beräkningsnoder automatiskt i en Azure Batch pool.

Ange aktivitetsdistribution

När du aktiverar samtidiga uppgifter är det viktigt att ange hur du vill att aktiviteterna ska distribueras mellan noderna i poolen.

Med egenskapen CloudPool.TaskSchedulingPolicy kan du ange att aktiviteter ska tilldelas jämnt över alla noder i poolen ("sprida"). Eller så kan du ange att så många aktiviteter som möjligt ska tilldelas till varje nod innan aktiviteter tilldelas till en annan nod i poolen ("packning").

Tänk dig till exempel poolen med Standard_D14 noder (i exemplet ovan) som har konfigurerats med värdet 16 för CloudPool.TaskSlotsPerNode . Om CloudPool.TaskSchedulingPolicy har konfigurerats med en ComputeNodeFillType av Pack skulle den maximera användningen av alla 16 kärnor av varje nod och tillåta att en pool för automatisk skalning tar bort oanvända noder (noder utan tilldelade uppgifter) från poolen. Detta minimerar resursanvändningen och sparar pengar.

Definiera variabla platser per aktivitet

En aktivitet kan definieras med egenskapen CloudTask.RequiredSlots och ange hur många platser som krävs för att köras på en beräkningsnod. Standardvärdet är 1. Du kan ange variabla aktivitetsplatser om dina aktiviteter har olika vikter vad gäller resursanvändning på beräkningsnoden. På så sätt kan varje beräkningsnod ha ett rimligt antal samtidiga uppgifter som körs utan att överbelasta systemresurser som cpu eller minne.

För en pool med egenskapen taskSlotsPerNode = 8kan du till exempel skicka processorintensiva uppgifter med flera kärnor med requiredSlots = 8, medan andra uppgifter kan anges till requiredSlots = 1. När den här blandade arbetsbelastningen schemaläggs körs de CPU-intensiva uppgifterna uteslutande på deras beräkningsnoder, medan andra aktiviteter kan köras samtidigt (upp till åtta aktiviteter samtidigt) på andra noder. På så sätt kan du balansera din arbetsbelastning mellan beräkningsnoder och förbättra resursanvändningens effektivitet.

Se till att du inte anger att en aktivitet ska requiredSlots vara större än poolens taskSlotsPerNode. Detta resulterar i att aktiviteten aldrig kan köras. Batch-tjänsten validerar för närvarande inte den här konflikten när du skickar aktiviteter eftersom ett jobb kanske inte har en pool som är bunden vid sändningstillfället, eller så kan den ändras till en annan pool genom att inaktivera/återaktivera.

Tips

När du använder variabla aktivitetsfack är det möjligt att stora aktiviteter med fler nödvändiga platser tillfälligt inte kan schemaläggas eftersom det inte finns tillräckligt med platser tillgängliga på någon beräkningsnod, även om det fortfarande finns inaktiva platser på vissa noder. Du kan höja jobbprioriteten för dessa aktiviteter för att öka deras chans att konkurrera om tillgängliga platser på noder.

Batch-tjänsten genererar TaskScheduleFailEvent när den inte schemalägger en aktivitet som ska köras och fortsätter att försöka schemalägga igen tills nödvändiga platser blir tillgängliga. Du kan lyssna på händelsen för att identifiera potentiella schemaläggningsproblem och åtgärda detta.

Batch .NET-exempel

Följande Batch .NET API-kodfragment visar hur du skapar en pool med flera aktivitetsfack per nod och hur du skickar en aktivitet med nödvändiga platser.

Skapa en pool med flera aktivitetsfack per nod

Det här kodfragmentet visar en begäran om att skapa en pool som innehåller fyra noder, med fyra tillåtna aktivitetsfack per nod. Den anger en aktivitetsschemaläggningsprincip som fyller varje nod med aktiviteter innan aktiviteter tilldelas till en annan nod i poolen.

Mer information om hur du lägger till pooler med hjälp av Batch .NET API finns i BatchClient.PoolOperations.CreatePool.

CloudPool pool =
    batchClient.PoolOperations.CreatePool(
        poolId: "mypool",
        targetDedicatedComputeNodes: 4
        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");

pool.TaskSlotsPerNode = 4;
pool.TaskSchedulingPolicy = new TaskSchedulingPolicy(ComputeNodeFillType.Pack);
pool.Commit();

Skapa en uppgift med nödvändiga platser

Det här kodfragmentet skapar en uppgift med icke-standard requiredSlots. Den här aktiviteten körs bara när det finns tillräckligt med lediga platser på en beräkningsnod.

CloudTask task = new CloudTask(taskId, taskCommandLine)
{
    RequiredSlots = 2
};

Lista beräkningsnoder med antal för aktiviteter och platser som körs

Det här kodfragmentet visar en lista över alla beräkningsnoder i poolen och skriver ut antalet för aktiviteter och aktivitetsfack som körs per nod.

ODATADetailLevel nodeDetail = new ODATADetailLevel(selectClause: "id,runningTasksCount,runningTaskSlotsCount");
IPagedEnumerable<ComputeNode> nodes = batchClient.PoolOperations.ListComputeNodes(poolId, nodeDetail);

await nodes.ForEachAsync(node =>
{
    Console.WriteLine(node.Id + " :");
    Console.WriteLine($"RunningTasks = {node.RunningTasksCount}, RunningTaskSlots = {node.RunningTaskSlotsCount}");

}).ConfigureAwait(continueOnCapturedContext: false);

Visa en lista över antalet aktiviteter för jobbet

Det här kodfragmentet hämtar uppgiftsantal för jobbet, som innehåller både uppgifter och antal aktivitetsfack per aktivitetstillstånd.

TaskCountsResult result = await batchClient.JobOperations.GetJobTaskCountsAsync(jobId);

Console.WriteLine("\t\tActive\tRunning\tCompleted");
Console.WriteLine($"TaskCounts:\t{result.TaskCounts.Active}\t{result.TaskCounts.Running}\t{result.TaskCounts.Completed}");
Console.WriteLine($"TaskSlotCounts:\t{result.TaskSlotCounts.Active}\t{result.TaskSlotCounts.Running}\t{result.TaskSlotCounts.Completed}");

Batch REST-exempel

Följande Batch REST API-kodfragment visar hur du skapar en pool med flera aktivitetsfack per nod och hur du skickar en aktivitet med nödvändiga platser.

Skapa en pool med flera aktivitetsfack per nod

Det här kodfragmentet visar en begäran om att skapa en pool som innehåller två stora noder med högst fyra aktiviteter per nod.

Mer information om hur du lägger till pooler med hjälp av REST-API:et finns i Lägga till en pool i ett konto.

{
  "odata.metadata":"https://myaccount.myregion.batch.azure.com/$metadata#pools/@Element",
  "id":"mypool",
  "vmSize":"large",
  "virtualMachineConfiguration": {
    "imageReference": {
      "publisher": "canonical",
      "offer": "ubuntuserver",
      "sku": "18.04-lts"
    },
    "nodeAgentSKUId": "batch.node.ubuntu 18.04"
  },
  "targetDedicatedComputeNodes":2,
  "taskSlotsPerNode":4,
  "enableInterNodeCommunication":true,
}

Skapa en uppgift med nödvändiga platser

Det här kodfragmentet visar en begäran om att lägga till en uppgift med icke-standard requiredSlots. Den här aktiviteten körs bara när det finns tillräckligt med lediga platser på beräkningsnoden.

{
  "id": "taskId",
  "commandLine": "bash -c 'echo hello'",
  "userIdentity": {
    "autoUser": {
      "scope": "task",
      "elevationLevel": "nonadmin"
    }
  },
  "requiredSLots": 2
}

Kodexempel på GitHub

ParallelTasks-projektet på GitHub illustrerar användningen av egenskapen CloudPool.TaskSlotsPerNode.

Det här C#-konsolprogrammet använder Batch .NET-biblioteket för att skapa en pool med en eller flera beräkningsnoder. Den kör ett konfigurerbart antal aktiviteter på dessa noder för att simulera en variabel belastning. Utdata från programmet visar vilka noder som körde varje aktivitet. Programmet innehåller också en sammanfattning av jobbparametrarna och varaktigheten.

Nedan visas till exempel sammanfattningsdelen av utdata från två olika körningar av ParallelTasks-exempelprogrammet. Jobbvaraktigheter som visas här inkluderar inte tid för att skapa pooler, eftersom varje jobb skickades till en tidigare skapad pool vars beräkningsnoder var i inaktivitetstillstånd vid sändningstillfället.

Den första körningen av exempelprogrammet visar att med en enda nod i poolen och standardinställningen för en aktivitet per nod är jobbvaraktigheten över 30 minuter.

Nodes: 1
Node size: large
Task slots per node: 1
Max slots per task: 1
Tasks: 32
Duration: 00:30:01.4638023

Den andra körningen av exemplet visar en betydande minskning av jobbvaraktigheten. Det beror på att poolen har konfigurerats med fyra aktiviteter per nod, vilket gör att parallell aktivitetskörning kan slutföra jobbet inom nästan en fjärdedel av tiden.

Nodes: 1
Node size: large
Task slots per node: 4
Max slots per task: 1
Tasks: 32
Duration: 00:08:48.2423500

Nästa steg