PowerShell 7.0.0 Preview3新機能 ForEach-Object並列処理 (2)

【連載】

PowerShell Core入門 - 基本コマンドの使い方

【第67回】PowerShell 7.0.0 Preview3新機能 ForEach-Object並列処理 (2)

[2019/10/04 07:30]後藤大地 ブックマーク ブックマーク

  • サーバ/ストレージ

サーバ/ストレージ

ForEach-Object -Parallelが効果を発揮するパターン

前回はPowerShell 7.0.0 Preview 3に新しく追加されたForEach-Objectコマンドレットの並列処理機能(-Parallel)について紹介した。今回はこの機能の利点や欠点についてもうちょっと突っ込んで説明しておこう。

※ (編集部注)掲載時点の最新版はPowerShell 7.0.0 Preview4です。こちらは追ってご紹介します。

ForEach-Object -Parallelは、シンプルな記述が可能で、スクリプトブロックを並列処理する方法として強力な機能であることに間違いはないのだが、並列ごとに実行空間コンテキストの生成が行われるという重い処理が発生することになる。

そのため、この機能はパフォーマンス的に万能というものではなく、効果が発揮できるシーンと発揮できないシーンがはっきりとわかれている。

性能が発揮できる主なシーンは次の2つ。

マルチコアまたはマルチプロセッサの実行環境で、並列処理の対象となるスクリプトが長い時間をかけて計算を行う類のもの
ForEach-Object -Parallelが実行空間コンテキストを生成および初期化する処理が重いものの、それを超える長い時間処理が継続するようなものであれば、並列化することで得られるメリットの方が大きくなる。ただし、マルチコアまたはマルチプロセッサのマシンであるという前提が必要になる。シングルコアのマシンまたは実行環境でForEach-Object -Parallelを使うとまるで意味がなく、逆に遅くなる。また、-ThrottleLimitで指定する値はコアの総数まで。それ以上増やしても効果が得られないどころか、パフォーマンスが低下する可能性が高い

待機処理が発生するスクリプトを並列化するパターン
たとえば前回サンプルとして取り上げたコードにはsleepが含まれているが、これは待ちの処理であり、ForEach-Object -Parallelの効果が得やすい。ディスクI/Oも基本的には待ちの処理になるため効果が得やすい(高速なストレージなるほど効果が得にくくなる)。待ち時間が実行空間コンテキストの生成と初期化にかかる時間よりも長ければ効果が得られることになる。待ちの処理の場合にはシングルコアのマシンや環境でも効果を得ることが可能で、さらに-ThrottleLimitで指定する値はコアの数を超えて指定しても効果が得られる。どの程度の数を指定するかは環境によって異なるため、実際に実行してもっともパフォーマンスが高くなる値を指定するようにすればよい

カーネル側の動作に明るい方は、この動きも理解しやすいだろう。ForEach-Object -Parallelを使用する場合、並列するときに必ず重い処理が発生するということを覚えておいてほしい。その処理を含めても高速化が可能かどうかが、この機能を利用するかどうかのひとつの基準になる。

ForEach-Object -Parallelを使ってはいけないパターン

ForEach-Object -Parallelは並列化ごとに実行空間コンテキストの生成と初期化を行うため、スクリプトブロックの中の処理が短く、実行空間コンテキストの生成&初期化処理よりも短い場合、パフォーマンスが大きく悪化する。すぐに終わるような処理で-Parallelを使用すると逆にすごく遅くなるということだ。

次のスクリーンショットはそのサンプルだ。10,000回処理を行っているのだが、最初のスクリーンショットは並列化しないで、2つ目のスクリーンショットでは5並列で処理を行っている。

10,000回処理を実施

10,000回行う処理を5並列で実施

結果は次のとおりだ。

  • 並列なし: 0.87秒
  • 並列あり: 204.141秒


並列化した方が230倍ほど遅くなっている。このように、軽めの処理はForEach-Object -Parallelで並列化すると性能が悪化する。

ForEach-Object -Parallelで並列化するときは、高速化が可能だという確信があるとき、ということになるだろう。高速になるかどうかわからないときは、とりあえず実行して時間を測定してみることをお薦めしたい。それほど変わらないならやらない方がよいだろう。

並列とスレッド間通信

ForEach-Object -Parallelで並列処理ごとに実行空間コンテキストをコピー…というか生成しているのは、PowerShell Coreの規約に準拠するためだ。PowerShell Coreの仕様を満たしつつ、並列処理を実現するには、実行空間コンテキストを生成してそこで処理を走らせる必要がある。今後高速化の余地はあるとは思うが、現在の実装だと生成時の負荷に対してそこまで劇的な高速化は見込めないだろう。

また、実行空間コンテキストはスクリプトを実行するためのひとつの分離単位になっており、基本的にこれらコンテキスト間で通信を行ったりデータを共有することはできない仕組みになっている。ただし、$usingを使えばデータ共有じみたことはできてしまうものの、その方法はスレッドセーフではないので、安全に処理を行うことはできないとされている。

UNIXシェルであればプロセス間通信を使うことで同時に動作するプロセス間でデータをやり取りすることができる。名前付きパイプやファイルシステムを使うというのもひとつの方法だ。

PowerShell Coreの並列機能はまだそこまで簡単に並列処理を実現できるというものではないようだ。しかし、これはあくまでも最初の段階だ。今後登場する機能で並列処理に関してはさらに便利な機能が追加される可能性もある。今後のリリースに注目しておきたいところだ。

参考資料

※ 本記事は掲載時点の情報であり、最新のものとは異なる場合がございます。予めご了承ください。

一覧はこちら

連載目次

もっと知りたい!こちらもオススメ

【連載】RPA入門 - ツールで学ぶ活用シーン

【連載】RPA入門 - ツールで学ぶ活用シーン

AIには、ルールベース、機械学習、深層学習(ディープラーニング)の3つのレベルがあり、レベルが上がるに連れてより高度な人工知能を実現しますが、AIのスピンオフという位置付けで、Digital Labor(仮想知的労働者)によるホワイトカラー業務の自動化を実現するRPAが注目されています。

関連リンク

この記事に興味を持ったら"いいね!"を Click
Facebook で IT Search+ の人気記事をお届けします

会員登録(無料)

注目の特集/連載
[解説動画] Googleアナリティクス分析&活用講座 - Webサイト改善の正しい考え方
[解説動画] 個人の業務効率化術 - 短時間集中はこうして作る
知りたい! カナコさん 皆で話そうAIのコト
教えてカナコさん! これならわかるAI入門
対話システムをつくろう! Python超入門
Kubernetes入門
AWSで作るクラウドネイティブアプリケーションの基本
PowerShell Core入門
徹底研究! ハイブリッドクラウド
マイナビニュース スペシャルセミナー 講演レポート/当日講演資料 まとめ
セキュリティアワード特設ページ

一覧はこちら

今注目のIT用語の意味を事典でチェック!

一覧はこちら

ページの先頭に戻る