如何在 PowerShell 中使用 ForEach-Object Parallel cmdlet?


Foreach-Object -Parallel 命令是在 PowerShell 7 預覽版 3 中引入的,它用於並行執行管道輸入,本文將對此進行更詳細的解釋。

請注意:Foreach-Object 和 Foreach 命令相同,但我們不能寫 Foreach -Parallel 命令,因為沒有這樣的命令,我們需要使用完整的命令 Foreach-Object -Parallel

執行並行物件的簡單示例。

示例

1..10 | ForEach-Object -Parallel{
    $_ * 1000  
    Sleep 1
}

輸出

1000
2000
3000
4000
5000
6000
7000
8000
9000
10000

讓我們比較使用和不使用 -Parallel 引數的計時。

並行執行

$time1 = Measure-Command {
    1..10 | ForEach-Object -Parallel{
        $_ * 1000  
        Sleep 1
    }

}
    
Write-Output "Parallel Time : Minutes : $($time1.Minutes) , Seconds : $($time1.Seconds) , Milliseconds : $($time1.TotalMilliseconds) "

輸出

Parallel Time : Minutes : 0 , Seconds : 2 , Milliseconds : 2500.9792 

順序執行

$time1 = Measure-Command {
    1..10 | ForEach-Object {
        $_ * 1000  
        Sleep 1
    }

}
    
Write-Output "Sequential Time : Minutes : $($time1.Minutes) , Seconds : $($time1.Seconds) , Milliseconds : $($time1.TotalMilliseconds) "

輸出

Sequential Time : Minutes : 0 , Seconds : 10 , Milliseconds : 10062.0786

您可以看到以上兩種執行之間的顯著差異,並行執行比順序執行快得多。

還有一個引數支援 foreach-Object 迴圈的並行化,即 -ThrottleLimit,表示並行執行的執行緒數。預設情況下,節流限制為 5。請檢視增加節流限制後的時間差異。

示例

$time1 = Measure-Command {
    1..10 | ForEach-Object -Parallel{
        $_ * 1000  
        Sleep 1
    } -ThrottleLimit 10

}
    
Write-Output "Sequential Time : Minutes : $($time1.Minutes) , Seconds : $($time1.Seconds) , Milliseconds : $($time1.TotalMilliseconds) "

輸出

Parallel Time : Minutes : 0 , Seconds : 1 , Milliseconds : 1615.4921 

如果您比較第一個並行時間示例,第二個更快,因為我們增加了節流限制。當您增加節流限制時,請確保哪個命令用於並行執行,以及有多少節流限制作為輸入傳遞,否則系統將因指令碼執行而超載,因為生成了許多 PowerShell 執行緒。

您也可以將此命令作為後臺作業執行,因為它支援 -AsJob 引數。

$fjob = 1..10 | ForEach-Object -Parallel{
        $_ * 1000  
        Sleep 1
} -ThrottleLimit 10 -AsJob 

$fjob | Receive-Job

其他遠端命令和 foreach-Object -Parallel 之間的區別在於,此命令在同一上下文中並行執行作業,這稱為 名稱空間,而其他遠端命令則使用 -ComputerName 引數或 Invoke-Command 在遠端計算機上順序執行,這就是並行執行對於遠端計算機快得多的原因。

當您在 PS 版本 7 中使用並行 foreach 迴圈時,並行迴圈內唯一可見的變數是管道變數,其他外部變數或物件可以使用 Using: 關鍵字訪問。例如:

示例

$computers = "Test1-Win2k12", "test1-Win2k16"
$command = "Win32_OperatingSystem"

$computers | ForEach-Object -Parallel {
   Get-CimInstance $using:command -ComputerName $_
}

您可以在上面的指令碼中看到,只有 $computers 可以透過 $_ 在 Foreach 迴圈中訪問,但要訪問 $command,我們需要使用 $using:Command,因為它在迴圈的作用域之外,但這在簡單的 foreach 迴圈中並非如此。

更新於:2020年11月11日

2K+ 次檢視

啟動您的 職業生涯

完成課程獲得認證

開始學習
廣告
© . All rights reserved.