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
はシングルスレッドで処理されていたらしい。
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で起動できる。
Invoke-Asyncでやる
パフォーマンス的にはBackground jobsを使う方法に劣るが、スレッドの管理がラップされていてシンプルに書けるらしい。
補足
今回使ったWindows PowerShellは、長年Windowsにくっついていた歴史とぬくもりのあるPowerShellであり、.NET Frameworkでできている。WIndows PowerShellのWorkflowは.NET Framework 3.0で導入されたWindows Workflow Foundationという技術を基盤にしている。
一方で、.NET Coreを基盤としたPowerShell Coreもある。ただ、こちらにはWorkflowが移植されてない。
そのため、お手軽にはマルチスレッドの処理ができない。以下のようにがんばることになる。
環境
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