並行執行工作以充分使用 Batch 計算節點

藉由在每個節點上同時執行一個以上的工作,您可以在集區中較少的計算節點上,將資源使用量最大化。

雖然在某些情節中,將節點的所有資源專用於單一工作的效果最好,但多個工作共用這些資源時,某些工作負載可能會產生較短的作業時間和較低的成本。 請考量下列案例:

  • 最小化資料傳輸,適用於可共用資料的工作。 您可以將共用資料複製到較少數量的節點,然後在每個節點上平行執行工作,以大幅降低資料傳輸費用。 此策略尤其適用於當要複製到每個節點的資料必須在地理區域之間傳輸時。
  • 最大化記憶體使用量,適用於需要大量記憶體的工作,但只有在短時間之內,以及在執行期間的可變時間。 您可以運用具有更多記憶體的較少但較大的計算節點,有效率地處理這類高峰流量。 這些節點會有在每個節點上執行的多個平行工作,但是每個工作會在不同的時間利用節點的大量記憶體。
  • 當集區內需要節點間通訊時,緩和節點數目的限制。 目前,針對節點間通訊設定的集區限制為 50 個計算節點。 如果這類集區中的每個節點能夠以平行方式執行工作,則可以同時執行較多的工作。
  • 複寫內部部署計算叢集,例如當您第一次將計算環境移至 Azure 時。 如果目前的內部部署解決方案在每個計算節點執行多個工作,您可以增加節點工作的數目上限,以更密切地反映該組態。

範例案例

例如,假設有 CPU 和記憶體需求的工作應用程式,讓 Standard_D1 節點已足夠。 然而,為了在要求的時間內完成作業,需要 1,000 個這類節點。

如果不使用 Standard_D1 節點 (具有一個 CPU 核心),您可以使用每個節點具有 16 個核心的 Standard_D14 節點,並啟用平行工作執行。 您的節點用量可能會少於 16 倍,因此僅需要 63 個節點,而不是 1,000 節點。 由於資料只需複製到 63 個節點,如果每個節點都需要大型應用程式檔案或參考資料,那麼作業持續時間和效率都能獲得改善。

啟用平行工作執行

您可以針對集區層級的平行工作執行,設定計算節點。 使用 Batch .NET 程式庫時,請在建立集區時設定 CloudPool.TaskSlotsPerNode 屬性。 如果您使用 Batch REST API,請在集區建立期間於要求本文中設定 taskSlotsPerNode 元素。

注意

您只能在建立集區時設定 taskSlotsPerNode 元素和 TaskSlotsPerNode 屬性。 建立集區後便無法加以修改。

Azure Batch 允許您設定每個節點的工作位置數目,最多為節點核心數目的 4 倍。 例如,如果集區設定的節點大小為 [大] \(四個核心),則 taskSlotsPerNode 可以設定為 16。 不過,不論節點具有多少核心,每個節點的工作位置都不能超過 256 個。 如需每個節點大小的核心數目的詳細資料,請參閱 雲端服務 (傳統) 的大小。 如需服務限制的詳細資訊,請參閱 Batch 服務配額和限制

提示

為您的集區建構自動調整公式時,請務必考慮 taskSlotsPerNode 值。 例如,評估 $RunningTasks 的公式可能大幅受到每個節點的工作增加的影響。 如需詳細資訊,請參閱建立自動公式以調整 Batch 集區中的計算節點

指定工作發佈

啟用並行工作時,請務必指定您希望在集區內進行跨節點分佈工作的方式。

使用 CloudPool.TaskSchedulingPolicy 屬性,您可以指定工作應該跨集區中的所有節點平均指派 (「散佈」)。 或者,您可以在工作指派到集區中其他節點之前,盡可能將最多工作指派給每個節點 (「封裝」)。

例如,考量 Standard_D14 節點的集區 (上述範例),以 CloudPool.TaskSlotsPerNode 為 16 的值進行設定。 如果 CloudPool.TaskSchedulingPolicyComputeNodeFillTypePack 進行設定,它會最大化每個節點全部 16 個核心的使用量,並且允許自動調整集區從集區移除未使用的節點 (未指派任何工作的節點)。 自動調整可最小化資源使用量,同時節省成本。

定義每個工作的可變位置

您可以使用 CloudTask.RequiredSlots 屬性來定義工作,指定在計算節點上執行所需的位置數目。 預設值是 1。 如果您的工作有與計算節點上資源使用量相關聯的不同加權,您可以設定可變工作位置。 變數工作位置可讓每個計算節點有合理的並行執行工作數目,而不需要占用 CPU 或記憶體的系統資源。

例如,對於具有屬性 taskSlotsPerNode = 8 的集區,您可以使用 requiredSlots = 8 提交多核心所需的 CPU 密集型工作,而其他工作可設定為 requiredSlots = 1。 當排程此混合工作負載時,CPU 密集型工作將會在其計算節點上獨佔執行,而其他工作可以在其他節點上同時執行 (一次最多八個工作)。 此混合工作負載有助於平衡計算節點之間的工作負載,並改善資源使用量的效率。

請確定您未將工作的 requiredSlots 指定為大於集區的 taskSlotsPerNode,或者一律不支行工作。 當您提交工作時,Batch 服務目前不會驗證此衝突。 由於作業在提交時可能沒有集區繫結,或藉由停用/重新啟用來變更為不同的集區,因此不會驗證衝突。

提示

使用可變工作位置時,具有更多必要位置的大型工作可能會暫時無法排程,因為任何計算節點上都沒有足夠的位置可用,即使某些節點上仍有閒置位置也一樣。 您可以提高這些工作的作業優先順序,以提高其在節點上競爭可用位置的機會。

Batch 服務會在無法排程工作執行時,發出 TaskScheduleFailEvent,並持續重試排程,直到所需的位置可用為止。 您可以接聽該事件來偵測潛在的工作排程問題,並視情況減輕問題。

Batch .NET 範例

下列 Batch .NET API 程式碼片段示範如何為每個節點建立具有多個工作位置的集區,以及如何提交具有必要位置的工作。

建立每個節點具有多個工作位置的集區

此程式碼片段示範建立集區的要求,該集區包含四個節點,而每個節點最多有四個工作位置。 其會指定工作排程原則,該原則會先以工作填滿每個節點,再將工作指派給集區中的其他節點。

如需有關使用 Batch .NET API 新增集區的詳細資訊,請參閱 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();

建立具有必要位置的工作

此程式碼片段使用非預設 requiredSlots 建立工作。 在計算節點上有足夠的可用位置時,此工作便會執行。

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

列出計算節點,其中包含執行中工作和位置的計數

此程式碼片段會列出集區中的所有計算節點,並列印每個節點執行中工作和工作位置的計數。

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

列出作業的工作計數

此程式碼片段會取得作業的工作計數,其中包含每個工作狀態的工作和工作位置計數。

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 範例

下列 Batch REST API 程式碼片段示範如何為每個節點建立具有多個工作位置的集區,以及如何提交具有必要位置的工作。

建立每個節點具有多個工作位置的集區

此程式碼片段示範建立集區的要求,該集區包含兩個大型節點,而每個節點最多有四項工作。

如需有關如何使用 REST API 新增集區的詳細資訊,請參閱將集區新增至帳戶

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

建立具有必要位置的工作

此程式碼片段示範使用非預設 requiredSlots 的新增工作要求。 只有在計算節點上有足夠的可用位置時,此工作才會執行。

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

GitHub 上的程式碼範例

GitHub 上的 ParallelTasks 專案提供使用 CloudPool.TaskSlotsPerNode 屬性的說明。

這個 C# 主控台應用程式使用 Batch .NET 程式庫來建立具有一或多個計算節點的集區。 它會在這些節點上執行可設定數目的工作,以模擬可變負載。 應用程式的輸出示範每個工作執行哪些節點。 此應用程式也會提供作業參數和持續時間的摘要。

下列範例顯示 ParallelTasks 應用程式範例兩個不同執行的輸出摘要部分。 此處顯示的作業期間不包含集區建立時間,因為每個作業都提交到先前建立的集區,其計算節點在提交時處於「閒置」狀態。

首次執行範例應用程式會顯示該部分與集區中的單一節點,以及每個節點一項作業的預設設定,作業持續時間超過 30 分鐘。

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

第二次執行範例會顯示作業持續時間大幅降低。 此減少的原因在於集區已設定為每個節點四項工作,可允許平行工作執行以在近一季的時間完成作業。

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

下一步