PowerShellで始める並列処理:基本から応用まで

PowerShellは、Windows環境の自動化やスクリプト実行に欠かせないツールです。

多くの作業を効率化できるPowerShellですが、通常の処理は順番に実行されるため、大量のデータを扱う場合や時間のかかるタスクでは待ち時間が発生します。

こうした問題を解決するために「並列処理」を導入すると、複数の作業を同時に実行し、処理速度を大幅に向上させることができます。

本記事では、PowerShellにおける並列処理の使い方を基礎から解説します。

また、実際に動作するサンプルコードを通じて、並列処理の利便性と効率化のポイントについて学びましょう。


並列処理とは?

並列処理」とは、同時に複数の処理を実行する手法のことです。

通常の処理では、タスクは1つずつ順番に実行されますが、並列処理を使用すると、複数のタスクが同時に進行し、処理時間を短縮できます。

  • シングルタスク: A → B → C
  • 並列タスク: A | B | C (同時実行)

これにより、たとえば複数のAPIリクエストやファイル処理を効率化できます。


PowerShellにおける並列処理の基本

PowerShell 7以降では、ForEach-Object -Parallelコマンドが使えるようになり、より簡単に並列処理を扱えるようになりました。

ForEach-Object -Parallel の基本構文

$items = 1..10
$items | ForEach-Object -Parallel {
    # ここに並列で実行したい処理を書く
    "Processing item $_"
}
  • $_: 現在のループ対象の要素
  • -Parallel: 各要素を並列で処理するオプション

並列処理の具体例

ここでは、実用的な例として、複数のファイルに対して同時に処理を行うスクリプトを紹介します。

たとえば、ログファイルの内容をチェックし、特定の文字列を探すケースを考えましょう。

例1: ログファイルの並列検索

$logFiles = Get-ChildItem -Path "C:\Logs" -Filter *.log

$logFiles | ForEach-Object -Parallel {
    param($file)  # パラメーターを使ってファイルを受け渡し
    if (Select-String -Path $file.FullName -Pattern "ERROR") {
        "$($file.Name): エラーが見つかりました。"
    } else {
        "$($file.Name): 問題ありません。"
    }
} -ArgumentList $_

ポイント

  • param を使って、並列処理内に値を受け渡します。
  • -ArgumentList でパラメーターを渡す必要がある点に注意。

例2: APIリクエストの並列実行

次の例では、複数のAPIに同時にリクエストを送り、そのレスポンスを取得します。

$urls = @(
    "https://api.example.com/data1",
    "https://api.example.com/data2",
    "https://api.example.com/data3"
)

$urls | ForEach-Object -Parallel {
    param($url)
    $response = Invoke-RestMethod -Uri $url
    "Received response from $url: $($response.status)"
} -ArgumentList $_

このように、APIへのリクエストも並列で実行することで、待ち時間を大幅に短縮できます。


並列処理を効果的に使うポイントと注意点

効果的に使うポイント

  1. I/O処理(ファイルやネットワーク操作)に特に効果的。
  2. CPU負荷が高い処理も分割することで、パフォーマンスが向上する。
  3. タイムアウトが設定可能な処理(APIリクエストなど)で有効。

注意点

  1. リソースの使いすぎに注意:並列処理を多用すると、CPUやメモリを消費するため、必要以上の並列化は避ける。
  2. スレッド間の競合に注意:同じリソースを複数のスレッドで同時に変更すると、予期せぬ動作を引き起こす可能性があります。
  3. デバッグが難しい:並列処理は順序が不定のため、バグの原因を特定するのが難しい場合があります。

演習問題

以下の演習を通じて、並列処理の理解を深めましょう。

演習問題 1: 画像ファイルのリサイズを並列で実行する

指定されたフォルダにある画像ファイルをすべて、小さなサムネイルにリサイズするスクリプトを作成してください。

  • フォルダのパス: C:\Images
  • すべての画像を 100×100ピクセル にリサイズすること。
  • 並列処理を使って、すべての画像を効率的に処理すること。

解答例

演習問題 1 の解答例

以下は、System.Drawing ライブラリを使用して、画像ファイルを並列処理でリサイズする例です。

Add-Type -AssemblyName System.Drawing

$images = Get-ChildItem -Path "C:\Images" -Filter *.jpg

$images | ForEach-Object -Parallel {
    param($image)

    $img = [System.Drawing.Image]::FromFile($image.FullName)
    $thumb = $img.GetThumbnailImage(100, 100, $null, [System.IntPtr]::Zero)

    $thumbnailPath = "C:\Images\Thumbnails\$($image.Name)"
    $thumb.Save($thumbnailPath)

    $img.Dispose()
    $thumb.Dispose()
    "Processed $($image.Name)"
} -ArgumentList $_

まとめ

本記事では、PowerShellの並列処理の基本と具体的な応用例について紹介しました。

ForEach-Object -Parallel を使うことで、複数のタスクを同時に実行し、作業時間を短縮できます。

並列処理は、特に大量のデータ処理やネットワークリクエストの自動化に有効です。

ただし、並列化のしすぎによるリソースの消費や、スレッド間の競合には注意が必要です。

今回の演習問題で学んだように、効率的にPowerShellの並列処理を活用することで、スクリプトのパフォーマンスを大きく向上させましょう。


これで、「PowerShellの並列処理」の基本と応用について理解が深まったはずです。

次のステップとして、より複雑なシナリオでの並列処理にも挑戦してみてください!