PowerShellで並列実行させる方法【Workflow】

こんにちは。
けいぞうです。

今回はPowerShellスクリプトで並列実行をする方法についての備忘録記事。

PowerShellで並列実行する方法

並列実行ではない例

まずは並列実行でない場合のサンプルスクリプトです。

#実際に処理したい内容のFunction
function Test($text){
    Start-Sleep -Seconds 2
    Write-Host "$text"
}

#普通にFunctionを呼び出す
function CallTestNormal()
{
    foreach ($i in 1..5) {
        Test "ループ ${i} 回目"
    }
}

(Measure-Command{ CallTestNormal }).Seconds

CallTestNolmalの中で、Test関数を5回呼び出しています。


Test関数では2秒待機してから標準出力しているので、結果的に全部で10秒処理に時間がかかることになります。

実行結果はこんな感じです。ちゃんと10秒かかっています。

ループ 1 回目
ループ 2 回目
ループ 3 回目
ループ 4 回目
ループ 5 回目
10

並列実行させる例

このTest関数の呼び出しを並列実行させたい場合は以下のように記述することで実現可能です。

#実際に処理したい内容のFunction
function Test($text){
    Start-Sleep -Seconds 2
    Write-Host "$text"
}

#WorkflowでFunctionを並列で呼び出す
Workflow CallTestWorkflow()
{
    foreach -parallel ($i in 1..5) {
        Test "ループ ${i} 回目"
    }
}

(Measure-Command{ CallTestWorkflow }).Seconds

変わったところは、呼び出し元の関数が「Function」ではなく「Workflow」になったことと、foreachに「-parallel」が付いたこと。

こう記述することで、foreachの中は非同期で実行してくれます。

つまり、厳密には並列実行というよりは、処理結果を待たずに次の呼び出しを実行しているといった感じですかね。

実行結果はこんな感じです。

ループ 3 回目
ループ 5 回目
ループ 4 回目
ループ 2 回目
ループ 1 回目
3

2秒ちょっとで終わると思ったんですが、3秒かかりました。

あと不思議なことに、最初の実行では9秒くらいかかったりするのですが、2回目以降は大体2秒くらいで処理してくれます。

謎です。