03. バッチ処理の並列化

【2016/11/24 original author KAMII】

z/OSでは、IMSやCICSなどのサブシステムを利用したオンライン・トランザクション処理やTSO配下でのISPFによる対話型処理を除けば、アプリケーションやユーティリティー・プログラムはジョブを定義して、その実行をスケジュール(サブミット)することでバッチ・ジョブとして実行されます。これは、バッチ処理と呼ばれるメインフレーム・コンピューターに於ける最も基本となる処理形態です。ジョブはJCLによって記述され、1つのジョブは実行するプログラムとそのプログラムが使用するデータを定義したジョブ・ステップで構成され、ジョブ内のジョブ・ステップは定義された順に1つずつ順番に実行されます。
同時に数多くのジョブが並行して処理されるz/OSオペレーティング・システムではJES(*1)を併用したジョブ管理が行われるのが基本で、特に、日本国内では大多数のz/OSユーザーがJESとしてJES2を利用しています。JES2に於いては、ジョブ内の各ステップは実行順序が保証されますが、各々のジョブ間では実行順序に依存性はなく(*2)、ジョブ・クラスに対応したイニシエーターが空き次第、次から次へと実行されます。JES2は、CPU(プログラムを実行するイニシエーター空間)(印刷出力を行うハードウェア装置としての)プリンターなどのシステム資源に無駄な遊休時間が生じぬよう、ジョブを次から次へと実行し、帳票データとしてのSYSOUTデータセットの内容を次から次へとプリンターから書き出す、というジョブ・スケジューリングを行います。


*1 Job Entry Subsystem:ジョブ入力サブシステムのこと。入力サブシステムとなっているが、実際にはジョブの入力から実行と出力までの一連のジョブ処理サイクルを効率良く管理しスケジュールする役割を担う。
*2 ジョブAが終わったらジョブBとジョブCを実行する、といった実行順序に基づく依存性の制御はJES2では行えなかった。

典型的なバッチ処理のジョブ・ステップ構成

縦列順のジョブ・ステップ構成

上図のフローで構成されるジョブがあるとします。z/OSにおける典型的なバッチ処理です。最初のステップ-1の出力データは、後続のステップ-2およびステップ-3の入力データになります。ステップ-2とステップ3は、それぞれステップ-1が作成したデータを元に別々の処理を行い、それぞれが処理結果のデータを出力します。ステップ-4は、ステップ-2とステップ3で作成されたデータを入力にして処理を行い、最終的な出力である印刷帳票を出力します。

「ジョブ内のジョブ・ステップは順番に実行される」という大原則があるので、先行する処理で作成されたデータを後続の処理で受け取りさらに別の処理を行う、といったデータの作成タイミングなどによる順序に基づく依存性については、同じジョブ内でジョブ・ステップを構成すれば解決されます。長年多くのバッチ処理がこの大原則に基づいてジョブが構成されて来ました。
しかしながら、メインフレーム・コンピューターで処理する業務データは年々増加し、いくらプロセッサーやストレージ装置などのハードウェア資源を高性能なものにしても、従来の順番通りに実行する処理構成では規定の時間内に処理しきれないほどのデータ量にまでなってきました。バッチ処理の並列化は、このような問題を解決する手段の1つになります。

ジョブ・ステップの並列化(z/OSとJES2の組み合わせでは実現できない…)

先程の例のジョブをよく見ると、先行ステップで作ったデータを後続ステップの入力にするというデータの依存性に影響を受けるのは、ステップ-1の出力を入力にするステップ-2とステップ-3、ステップ-2とステップ-3の出力を入力にするステップ-4です。ところが、ステップ-2とステップ-3は互いにデータを依存し合いません。したがって、本来ならステップ-2とステップ-3は、ステップ-1が終わってさえいれば並行して実行できるはずです。

縦列と並列順を組み合わせたジョブ・ステップ構成

しかしながら、z/OSではジョブ・ステップは定義された順に実行される、という大原則があるため、同時に実行できるステップ-2とステップ-3は同一ジョブ内では順番にしか実行できません。同時に実行するためには、ステップ-2かステップ-3のどちらか一方を別のジョブとして切り離さねばなりません。

並列化できるジョブ・ステップを別ジョブに分離(分離したジョブの実行開始タイミングを合わせられない…)

ところが、並行して同時に実行させるために別ジョブに分離してしまうと、分離したジョブの実行開始と分離したジョブの出力データを入力にしている元のジョブのジョブ・ステップの実行開始タイミングを合わせることができません。z/OSとJES2の組み合わせでは、ジョブ-Aのステップ-1の終了を待ってからジョブ-Bを開始させたり、ジョブ-Bのの終了を待ってからジョブ-Aのステップ-4を開始させたり、といった先行/後続関係に基づくジョブやジョブ・ステップの実行制御を行うことができません。

ジョブ分割されたジョブ・ステップ構成

ジョブに並列化したジョブ・ステップをジョブ・グループにまとめる

バッチ処理の並列化は、大量のデータを効率よく処理するための1つの対応策になりますが、ジョブ内のステップは並行して実行できない、ジョブが異なると実行タイミングを合わせられない、といった足枷があってz/OSとJES2の組み合わせだけでは簡単には実現できませんでした。しかしながら、JES2に追加実装されたジョブ・グループという概念によってz/OSとJES2だけの組み合わせでもバッチ処理の並列化が容易になりました。
JES2のJEC(ジョブ実行制御機能)によって、複数のジョブを1つのグループにまとめることができます。複数のジョブをまとめた単位がジョブ・グループです。従来のジョブ・ステップとジョブの関係に加え、ジョブとジョブ・グループという新たな関係を構築できます。JECの機能によって、ジョブ・グループ内のジョブの実行を先行/後続関係で制御することができます。順次で実行すべき処理はこれまで通りジョブ・ステップとして定義し、並行して実行可能なステップの前後でジョブに分離して、分離されたそれらのジョブを先行と後続の関係に基づいて実行を行わせることができます。

ジョブ・グループ化された複数ジョブ内のジョブ・ステップ構成

先程の例のジョブを、ジョブ・グループにまとめたものです。各ステップは、ジョブとして分割することになります(*3)。各ジョブののJCLは、予めJES2にサブミットされていますが、ジョブ-A以外は、先行/後続関係によってホールドされます。
ジョブ-B(ステップ-2)とジョブ-C(ステップ-3)は、ジョブ-A(ステップ-1)の終了を待って実行が開始されます。さらにジョブ-D(ステップ-4)は、ジョブ-B(ステップ-2)とジョブ-C(ステップ-3)の両方の終了を待って実行が開始されます。

JECの機能を利用すれば、これまでなら並列実行可能なステップがあっても後続ステップの関係で同じジョブ内で順番に実行せざるを得なかった処理や、大量のデータを複数ジョブに分割して実行したいが、そのプログラムの出力を入力にする後続処理があって単純に分割できなかった処理などが、JES2の機能だけでこれまで以上にバッチ処理のスループット(*4)を上げるような運用ができるようになりました。


*3 ジョブ・グループにするからといって全てのステップを単独ステップのジョブにしなければならないわけではない。この例では、元のステップ数が4つしかなく、並行できる中間の2ステップがそれぞれ先行ステップの出力を入力にし、自分の出力を後続がステップが入力にしている関係で結果として各ステップがジョブとして分離されることになっただけである。
*4 単位時間あたりの生産性もしくは処理能力のこと。バッチ処理ではスループットが重要視され、反対にオンライン処理では個々のトランザクション処理のレスポンス・タイムが重要視される。

「4.ジョブ・グループ」に続く。

【2016/11/24 original author KAMII】