共用方式為


教學課程:使用 .NET API 透過 Azure Batch 執行平行工作負載

使用 Azure Batch 在 Azure 中有效率地執行大規模的平行和高效能運算 (HPC) 批次作業。 本教學課程會逐步說明使用 Batch 執行平行工作負載的 C# 範例。 您會了解 Batch 應用程式的通用工作流程,以及如何以程式設計方式與 Batch 和儲存體資源進行互動。

  • 將應用程式套件新增至您的 Batch 帳戶。
  • 驗證 Batch 和儲存體帳戶。
  • 將輸入檔案上傳至儲存體。
  • 建立計算節點的集區來執行應用程式。
  • 建立作業和工作來處理輸入檔案。
  • 監視工作執行。
  • 擷取輸出檔案。

在本教學課程中,您會使用 ffmpeg 開放原始碼工具將 MP4 媒體檔案平行轉換為 MP3 格式。

如果您沒有 Azure 訂閱,請在開始之前,先建立 Azure 免費帳戶

必要條件

登入 Azure

登入 Azure 入口網站

新增應用程式套件

使用 Azure 入口網站,將 ffmpeg 新增至 Batch 帳戶作為應用程式套件。 應用程式套件可協助您管理工作應用程式並將其部署到集區中的計算節點。

  1. 在 Azure 入口網站中,按一下 [更多服務]>[Batch 帳戶],然後選取您的 Batch 帳戶名稱。

  2. 按一下 [應用程式]>[新增]

    批次帳戶 [應用程式] 區段的螢幕擷取畫面。

  3. 在 [應用程式識別碼] 欄位中輸入 ffmpeg,並在 [版本] 欄位中輸入套件版本 4.3.1。 選取您下載的 ffmpeg ZIP 檔案,然後選取 [提交]。 ffmpeg 應用程式套件會新增至您的 Batch 帳戶。

    [新增應用程式] 區段中識別碼和版本欄位的螢幕擷取畫面。

取得帳戶認證

在此範例中,您必須提供 Batch 和儲存體帳戶的認證。 在 Azure 入口網站中可以直接取得所需的認證。 (您也可以使用 Azure API 或命令列工具取得這些認證。)

  1. 選取 [所有服務]>[Batch 帳戶],然後選取您的 Batch 帳戶名稱。

  2. 若要查看 Batch 認證,請選取 [金鑰]。 將 [Batch 帳戶]、[URL] 和 [主要存取金鑰] 的值複製到文字編輯器。

  3. 若要查看儲存體帳戶名稱和金鑰,請選取 [儲存體帳戶]。 將 [儲存體帳戶名稱] 和 [金鑰1] 的值複製到文字編輯器。

下載及執行範例應用程式

下載範例應用程式

從 GitHub 下載或複製範例應用程式。 若要使用 Git 用戶端複製範例應用程式存放庫,請使用下列命令:

git clone https://github.com/Azure-Samples/batch-dotnet-ffmpeg-tutorial.git

瀏覽至包含 Visual Studio 解決方案檔案 BatchDotNetFfmpegTutorial.sln 的目錄。

此外,請確定解決方案中的 ffmpeg 應用程式套件參考符合您上傳至 Batch 帳戶的 ffmpeg 套件識別碼和版本。 例如,ffmpeg4.3.1

const string appPackageId = "ffmpeg";
const string appPackageVersion = "4.3.1";

建置及執行範例專案

在 Visual Studio 中建置及執行應用程式,或是在命令列使用 dotnet builddotnet run 命令。 執行此應用程式之後,檢閱程式碼以了解應用程式的每部分用途。 例如,在 Visual Studio 中:

  1. 以滑鼠右鍵按一下方案總管中的解決方案,然後選取 [建置方案]

  2. 出現提示時,請確認任何 NuGet 封裝的還原。 如果您需要下載遺漏的套件,請確保已安裝 NuGet 套件管理員

  3. 執行方案。 當您執行範例應用程式時,主控台輸出大致如下。 在執行期間,集區的計算節點啟動後,您會在 Monitoring all tasks for 'Completed' state, timeout in 00:30:00... 遇到暫停。

Sample start: 11/19/2018 3:20:21 PM

Container [input] created.
Container [output] created.
Uploading file LowPriVMs-1.mp4 to container [input]...
Uploading file LowPriVMs-2.mp4 to container [input]...
Uploading file LowPriVMs-3.mp4 to container [input]...
Uploading file LowPriVMs-4.mp4 to container [input]...
Uploading file LowPriVMs-5.mp4 to container [input]...
Creating pool [WinFFmpegPool]...
Creating job [WinFFmpegJob]...
Adding 5 tasks to job [WinFFmpegJob]...
Monitoring all tasks for 'Completed' state, timeout in 00:30:00...
Success! All tasks completed successfully within the specified timeout period.
Deleting container [input]...

Sample end: 11/19/2018 3:29:36 PM
Elapsed time: 00:09:14.3418742

移至 Azure 入口網站中您的 Batch 帳戶,以監視集區、計算節點、作業和工作。 例如,若要查看集區中計算節點的熱度圖,請按一下 [集區]>[WinFFmpegPool]

當工作正在執行時,熱度圖會如下所示:

Azure 入口網站中集區熱度圖的螢幕擷取畫面。

以預設設定執行應用程式時,一般的執行時間大約 10 分鐘。 建立集區佔用大部分的時間。

擷取輸出檔案

您可以使用 Azure 入口網站來下載 ffmpeg 工作所產生的 MP3 輸出檔案。

  1. 按一下 [所有服務]>[儲存體帳戶],然後按一下您的儲存體帳戶名稱。
  2. 按一下 [Blob]>[輸出]
  3. 以滑鼠右鍵按一下其中一個 MP3 輸出檔案,然後按 [下載]。 請依照瀏覽器的提示開啟或儲存檔案。

下載輸出檔案

此範例雖未示範,但您也可以用程式設計方式從計算節點或儲存體容器下載檔案。

檢閱程式碼

後面各節將範例應用程式細分為用來處理 Batch 服務中工作負載的數個步驟。 在閱讀本文的其餘部分時,請參考解決方案中的 Program.cs,因為本文並不會討論範例中的每一行程式碼。

驗證 Blob 和 Batch 用戶端

為了與連結的儲存體帳戶進行互動,應用程式會使用適用於 .NET 的 Azure.Storage.Blobs 程式庫。 正在使用 BlobServiceClient 類別,此類別會參考帳戶 URI 並驗證權杖,例如 DefaultAzureCredential

// TODO: Replace <storage-account-name> with your actual storage account name
Uri accountUri = new Uri("https://<storage-account-name>.blob.core.windows.net/");
BlobServiceClient blobClient = new BlobServiceClient(accountUri, new DefaultAzureCredential());

應用程式會透過 Resource Manager 的 ArmClient 來建立 BatchAccountResource 的參考,以在 Batch 服務中建立集區。 範例中的 Arm 用戶端會使用 DefaultAzureCredential 驗證。

ArmClient _armClient = new ArmClient(new DefaultAzureCredential());
var batchAccountIdentifier = ResourceIdentifier.Parse(BatchAccountResourceID);
BatchAccountResource batchAccount = await _armClient.GetBatchAccountResource(batchAccountIdentifier).GetAsync();

應用程式會建立 BatchClient 物件,以在 Batch 服務中建立和管理作業和工作。 範例中的批次用戶端會使用 DefaultAzureCredential 驗證。

// TODO: Replace <batch-account-name> with your actual storage account name
Uri batchUri = new Uri("https://<batch-account-name>t.eastus.batch.azure.com");
BatchClient _batchClient = new BatchClient(batchUri, new DefaultAzureCredential());

上傳輸入檔案

應用程式會將 blobServerClient 物件傳遞至 CreateContainerIfNotExistc 方法,以建立輸入檔案 (MP4 格式) 的儲存體容器和工作輸出的容器。

CreateContainerIfNotExist(blobClient, inputContainerName);
CreateContainerIfNotExist(blobClient, outputContainerName);

接著,檔案會從本機 InputFiles 資料夾上傳至輸入容器。 儲存體中的檔案會定義為 Batch ResourceFile 物件,Batch 之後可將這類物件下載到計算節點。

上傳檔案時需要 Program.cs 中的兩個方法:

  • UploadFilesToContainerAsync:傳回 ResourceFile 物件的集合,並在內部呼叫 UploadResourceFileToContainerAsync 以上傳在 inputFilePaths 參數中傳入的每個檔案。
  • UploadResourceFileToContainerAsync:將每個檔案當作 blob 上傳至輸入容器。 上傳檔案之後,它會取得此 blob 的共用存取簽章 (SAS) 並傳回代表它的 ResourceFile 物件。
string inputPath = Path.Combine(Environment.CurrentDirectory, "InputFiles");

List<string> inputFilePaths = new List<string>(Directory.GetFileSystemEntries(inputPath, "*.mp4",
    SearchOption.TopDirectoryOnly));

List<ResourceFile> inputFiles = await UploadFilesToContainerAsync(
  blobClient,
  inputContainerName,
  inputFilePaths);

如需使用 .NET 將檔案當作 Blob 上傳至儲存體帳戶的詳細資訊,請參閱使用 .NET 上傳、下載及列出 Blob

建立計算節點的集區

接著,範例會呼叫 CreatePoolIfNotExistAsync 以在 Batch 帳戶中建立計算節點集區。 這個已定義的方法會使用 BatchAccountResource.GetBatchAccountPools().CreateOrUpdateAsync 方法來設定節點數目、VM 大小和集區設定。 在此,BatchVmConfiguration 物件會將 BatchImageReference 指定至 Azure Marketplace 中發佈的 Windows Server 映像。 Batch 支援 Azure Marketplace 中各式各樣的 VM 映像,以及自訂 VM 映像。

使用已定義的常數可設定節點數目和 VM 大小。 Batch 支援專用節點和現成品節點,而您可以在集區中使用其中一種或同時使用兩種。 專用節點會保留給您的集區使用。 現成品節點則會以較低的價格從 Azure 中的剩餘容量提供。 如果 Azure 沒有足夠的容量,便無法使用現成品節點。 此範例預設建立的集區只包含 5 個大小為 Standard_A1_v2 的現成品節點。

注意

請務必檢查您的節點配額。 如需如何建立配額要求的指示,請參閱 Batch 服務配額和限制

ApplicationPackageReference 新增到集區設定,ffmpeg 應用程式便會部署至計算節點。

var credential = new DefaultAzureCredential();
ArmClient _armClient = new ArmClient(credential);

var batchAccountIdentifier = ResourceIdentifier.Parse(BatchAccountResourceID);
BatchAccountResource batchAccount = await _armClient.GetBatchAccountResource(batchAccountIdentifier).GetAsync();

BatchAccountPoolCollection collection = batchAccount.GetBatchAccountPools();
if (collection.Exists(poolId) == false)
{
    var poolName = poolId;
    var imageReference = new BatchImageReference()
    {
        Publisher = "MicrosoftWindowsServer",
        Offer = "WindowsServer",
        Sku = "2019-datacenter-smalldisk",
        Version = "latest"
    };
    string nodeAgentSku = "batch.node.windows amd64";


    ArmOperation<BatchAccountPoolResource> armOperation = await batchAccount.GetBatchAccountPools().CreateOrUpdateAsync(
        WaitUntil.Completed, poolName, new BatchAccountPoolData()
        {
            VmSize = "Standard_DS1_v2",
            DeploymentConfiguration = new BatchDeploymentConfiguration()
            {
                VmConfiguration = new BatchVmConfiguration(imageReference, nodeAgentSku)
            },
            ScaleSettings = new BatchAccountPoolScaleSettings()
            {
                FixedScale = new BatchAccountFixedScaleSettings()
                {
                    TargetDedicatedNodes = DedicatedNodeCount,
                    TargetLowPriorityNodes = LowPriorityNodeCount
                }
            },
            Identity = new ManagedServiceIdentity(ManagedServiceIdentityType.UserAssigned)
            {
                UserAssignedIdentities =
                {
                        [new ResourceIdentifier(ManagedIdentityId)] = new Azure.ResourceManager.Models.UserAssignedIdentity(),
                },
            },
            ApplicationPackages =
            {
                    new Azure.ResourceManager.Batch.Models.BatchApplicationPackageReference(new ResourceIdentifier(appPacakgeResourceID))
                    {
                        Version = appPackageVersion,
                    }
            },

        });
    BatchAccountPoolResource pool = armOperation.Value;

建立作業

Batch 工作會指定要在其中執行工作的集區及選擇性設定,例如工作的優先順序和排程。 此範例會藉由呼叫 CreateJobAsync 來建立作業。 這個已定義的方法會使用 BatchClient.CreateJobAsync 方法在您的集區上建立作業。

 BatchJobCreateContent batchJobCreateContent = new BatchJobCreateContent(jobId, new BatchPoolInfo { PoolId = poolId });
 await batchClient.CreateJobAsync(batchJobCreateContent);

建立工作

此範例會藉由呼叫 AddTasksAsync 方法在作業中建立工作,而這會建立一份 BatchTask 物件的清單。 每項 BatchTask 都會使用 CommandLine 屬數來執行 ffmpeg,以處理輸入 ResourceFile 物件。 ffmpeg 已在先前建立集區時安裝於每個節點上。 在此,命令列會執行 ffmpeg,將每個輸入 MP4 (影片) 檔案轉換為 MP3 (音訊) 檔案。

此範例會在執行命令列之後,為 MP3 檔案建立 OutputFile 物件。 每項工作的輸出檔案 (在此例中只有一個輸出檔案) 都會使用工作的 OutputFiles 屬性,上傳至所連結儲存體帳戶中的容器。 請注意 outputFile 物件上設定的條件。 工作順利完成後,工作的輸出檔只會上傳至容器 (OutputFileUploadCondition.TaskSuccess)。 如需進一步的實作詳細資料,請參閱 GitHub 上的完整程式碼範例

然後,範例會使用 CreateTaskAsync 方法將工作新增至作業,該方法會將工作排入佇列以在計算節點上執行。

將可執行檔的檔案路徑取代為您下載的版本名稱。 此範例程式碼會使用範例 ffmpeg-4.3.1-2020-11-08-full_build

// Create a collection to hold the tasks added to the job:
List<BatchTaskCreateContent> tasks = new List<BatchTaskCreateContent>();

for (int i = 0; i < inputFiles.Count; i++)
{
    // Assign a task ID for each iteration
    string taskId = String.Format("Task{0}", i);

    // Define task command line to convert the video format from MP4 to MP3 using ffmpeg.
    // Note that ffmpeg syntax specifies the format as the file extension of the input file
    // and the output file respectively. In this case inputs are MP4.
    string appPath = String.Format("%AZ_BATCH_APP_PACKAGE_{0}#{1}%", appPackageId, appPackageVersion);
    string inputMediaFile = inputFiles[i].StorageContainerUrl;
    string outputMediaFile = String.Format("{0}{1}",
        System.IO.Path.GetFileNameWithoutExtension(inputMediaFile),
        ".mp3");
    string taskCommandLine = String.Format("cmd /c {0}\\ffmpeg-4.3.1-2020-11-08-full_build\\bin\\ffmpeg.exe -i {1} {2}", appPath, inputMediaFile, outputMediaFile);

    // Create a batch task (with the task ID and command line) and add it to the task list

    BatchTaskCreateContent batchTaskCreateContent = new BatchTaskCreateContent(taskId, taskCommandLine);
    batchTaskCreateContent.ResourceFiles.Add(inputFiles[i]);

    // Task output file will be uploaded to the output container in Storage.
    // TODO: Replace <storage-account-name> with your actual storage account name
    OutputFileBlobContainerDestination outputContainer = new OutputFileBlobContainerDestination("https://<storage-account-name>.blob.core.windows.net/output/" + outputMediaFile)
    {
        IdentityReference = inputFiles[i].IdentityReference,
    };

    OutputFile outputFile = new OutputFile(outputMediaFile,
                                           new OutputFileDestination() { Container = outputContainer },
                                           new OutputFileUploadConfig(OutputFileUploadCondition.TaskSuccess));
    batchTaskCreateContent.OutputFiles.Add(outputFile);

    tasks.Add(batchTaskCreateContent);
}

// Call BatchClient.CreateTaskCollectionAsync() to add the tasks as a collection rather than making a
// separate call for each. Bulk task submission helps to ensure efficient underlying API
// calls to the Batch service. 

await batchClient.CreateTaskCollectionAsync(jobId, new BatchTaskGroup(tasks));

清除資源

應用程式在執行工作之後,會自動刪除它所建立的輸入儲存體容器,並且為您提供用於刪除 Batch 集區和工作的選項。 BatchClient 有方法可以刪除作業 DeleteJobAsync 並刪除集區 DeletePoolAsync,如果您確認刪除,就會呼叫此集區。 雖然您不需支付作業和工作本身的費用,但您需支付計算節點的費用。 因此,我們建議您只在必要時配置集區。 當您刪除集區時,節點上的所有工作輸出也會跟著刪除。 不過,輸出檔案會保留在儲存體帳戶中。

若不再需要,可刪除資源群組、Batch 帳戶和儲存體帳戶。 若要在 Azure 入口網站中這麼做,請選取 Batch 帳戶的資源群組,然後按一下 [刪除資源群組]

下一步

在本教學課程中,您已了解如何:

  • 將應用程式套件新增至您的 Batch 帳戶。
  • 驗證 Batch 和儲存體帳戶。
  • 將輸入檔案上傳至儲存體。
  • 建立計算節點的集區來執行應用程式。
  • 建立作業和工作來處理輸入檔案。
  • 監視工作執行。
  • 擷取輸出檔案。

如需更多使用 .NET API 來排程和處理 Batch 工作負載的範例,請參閱 GitHub 上的 Batch C# 範例