PowerShellでマルチスレッド処理(仮)

夏が終わりそうで切ない。

切ないので、何の気の迷いか、PowerShellの激軽なメモを書いてみる。

やりたいこと

3秒待ってprocessの連番を出力するだけの処理。これを5回繰り返す際に、並列でやらせたい。

function Do-Process()
{
    param([int] $process_num)

    $tid = [threading.thread]::CurrentThread.ManagedThreadId
    Start-Sleep -Seconds 3
    Write-Host "theadId:$tid, process:$process_num"
}

まず、直列のほうを実行する。

function Test-Sync()
{
    foreach ($i in 1..5)
    {
        Do-Process ${i}
    }
}

$time = Measure-Command {
    Test-Sync
}

実行結果はいかのとおり。

PS C:\temp> .\parallel_test.ps1
theadId:14, process:1
theadId:14, process:2
theadId:14, process:3
theadId:14, process:4
theadId:14, process:5

1から5まで順番に、単一のスレッドで実行されている。これをマルチスレッド化したい。

Workflowを使ってやる

Workflowってなんぞ?って人は、Windows PowerShell ワークフローについてをどうぞ。

workflow Test-Parallel()
{
    foreach -parallel ($i in 1..5)
    {
        Do-Process ${i}
    }
}

$time = Measure-Command {
    Test-Parallel
}

実行結果は以下のとおり。

PS C:\temp> .\parallel_test.ps1
theadId:9, process:5
theadId:4, process:3
theadId:11, process:1
theadId:12, process:2
theadId:6, process:4

処理の順番はバラバラで、スレッドも異なっている。 マルチスレッドで処理されている。ようにみえる。

PowerShell 3.0の時点では、-parallel はシングルスレッドで処理されていたらしい。

blogahf.blogspot.com

MSのひとも以下のように言っている。

As an Activity author you can’t make any assumptions about what thread your activity will be invoked on or how that thread will relate to any other thread used by any other activity.
Windows Workflow Foundation (WF4) Activities and Threads – Ron Jacobs

謎。かしこい人、教えてください。

Background jobsでやる

PowerShell 2.0以降では、jobをbackgroundで起動できる。

docs.microsoft.com

Invoke-Asyncでやる

パフォーマンス的にはBackground jobsを使う方法に劣るが、スレッドの管理がラップされていてシンプルに書けるらしい。

gallery.technet.microsoft.com

補足

今回使ったWindows PowerShellは、長年Windowsにくっついていた歴史とぬくもりのあるPowerShellであり、.NET Frameworkでできている。WIndows PowerShellのWorkflowは.NET Framework 3.0で導入されたWindows Workflow Foundationという技術を基盤にしている。

一方で、.NET Coreを基盤としたPowerShell Coreもある。ただ、こちらにはWorkflowが移植されてない。

github.com

そのため、お手軽にはマルチスレッドの処理ができない。以下のようにがんばることになる。

winscript.jp

環境

Windows 10。

PS C:\temp> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.15063.1209
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.15063.1209
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

参考