support

以下の説明は、qsubコマンド(Altair Grid Engine v.8.6.19) manページの-bindingオプションに関する翻訳です。人の目によるチェックはしていますが、機械翻訳をベースしていますので予めご承知ください。

-binding [ binding_instance ] binding_strategy

ジョブはこのパラメータで特定のプロセッサコアバインディング(プロセッサアフィニティ)を要求することができます。 このリクエストはバージョン8.1以降、ハードリソースリクエストとして扱われます。つまり、ジョブはリクエストを満たすことができるホストにのみディスパッチされます。 以前のバージョンとは対照的に、リクエストは Altair Grid Engine のスケジューラコンポーネントで処理されるようになりました。

Altair Grid Engine に特定のハードウェアアーキテクチャを選択させるには、complex属性の m_topology と共に -l スイッチを使用してください。

binding_instance はオプションのパラメータです。 バインディングのコアとなるジョブをどのインスタンスで実行するかによって、env、pe、set のいずれかが指定されます。 binding_instanceの値が指定されない場合、setが使用されます。

envは、環境変数SGE_BINDINGのみがジョブの環境へエクスポートされることを意味します。 この変数には、選択されたオペレーティングシステムの内部プロセッサ番号が含まれています。 SMT や CMT がある場合、各コアは複数のプロセッサ識別子で表現されるため、選択されたコアより多くなる可能性があります。 プロセッサ番号はスペースで区切られます。 この変数は、set または pe が要求されたときに、実コアバインディングの場合にも利用可能です。

pe は、選択されたコアに関する情報が pe_hostfile の 4 列目に表示されることを意味します。 ここでは、論理コアとソケットの番号がコロンで区切られたペアで表示されます (0から始まり、穴はありません) (例: 0,0:1,0 はソケット 0 のコア 0、ソケット 1 のコア 0 を意味します)。 pe_hostfile についてのより詳しい情報は sge_pe_(5) を参照してください。

set (何も指定されていない場合のデフォルト)。 bind strategy は、Altair Grid Engine によって適用されます。 これがどのように実現されるかは、投入されたジョブが開始される実行ホストの基本的なオペレーティングシステムに依存します。

Solaris 10ホストでは、ジョブが排他的に実行できるプロセッサセットが作成されます。 オペレーティングシステムの制限により、少なくとも1つのコアは結合されないままでなければなりません。 もちろん、このリソースは未結合のジョブによって使用される可能性があります。

Linux (lx-amd64 または lx-x86) ホストでは、プロセッサアフィニティマスクが設定され、選択されたコアのみでジョブが実行されるように制限されます。 オペレーティングシステムは、他の未バインドプロセスがこれらのコアを使用することを許可します。 Linuxでは、バインディングはLinuxカーネルバージョン2.6.16以降を必要とすることに注意してください。 これより低いバージョンのカーネルを使用することも可能かもしれませんが、その場合は追加のカーネルパッチを適用する必要があります。 utilbinディレクトリにあるloadcheckツールを使って、ホストの能力をチェックすることができます。また、qconf(1) コマンドの -sep と -cb の組み合わせで、Altair Grid Engine がハードウェアトポロジーを認識できるかどうかを確認することができます。

PE-jobsとコアバインディング バージョン 8.6 で、バインドするコア数の指定が、PE-task ごとのコア数に変更されました。 シーケンシャルジョブ(-pe指定なし)は1つのタスクとしてカウントされます。 バージョン 8.6 以前では、 はホスト単位で、そのホスト上のタスクの数とは関係ありませんでした。 例 バージョン 8.6 以降の “qsub -pe mype 7-9 -binding linear:2” は、各ホスト上でスケジュールされた各タスクに対して 2 コアをバインドすることを意味します (タスクの総数やホストの数は、指定範囲のため、投入時には不明です)。 これにより、ハイブリッド並列ジョブ、つまりマルチスレッド化された分散ジョブ(MPI + OpenMPなど)を高速に利用することができます。

bind_strategy に指定可能な値は以下の通り。

linear:<amount>[:<socket>,<core>]
linear_per_task:<amount>
striding:<amount>:<n>[:<socket>,<core>]
striding_per_task:<amount>:<n>
explicit:[<socket>,<core>:…]<socket>,<core>
explicit_per_task:[<socket>,<core>:…]<socket>,<core>
balance_sockets:<amount>
pack_sockets:<amount>
one_socket_balanced:<amount>
one_socket_per_task:<amount>

binding strategyのlinearとstridingでは、オプションでsocketとcoreのペアがセットされます。 これらは、最初にバインドするコアの開始点を示します。 linear_per_task, striding_per_task, balance_sockets, pack_sockets, one_socket_balanced, one_socket_per_task では、この開始点を指定することはできません。 per_task のサフィックスが付かないstrategyは全てホスト単位を意味し、各ホスト上の全てのタスクがbinding strategyに従わなければなりません。 つまり、タスクは他のすべてのタスクから独立して、個別にstrategyに従わなければならなりません。 これはあまり厳密ではなく、通常、より多くのタスクがホストに収まるようになります。 例えば linear を使う場合、ホスト上の全てのタスクは「隣り合わせ」でなければなりません。一方 linear_per_task を使う場合、タスク間に隙間があっても構いませんが、各タスクの全てのコアが「隣り合わせ」でなければなりません。 詳細は後述します。

以下のセクションで、いくつかの例を示します。 これらの例の表記は以下の通りです。空のサンプルホストには8スロットと8コアがあります。 ここで、コアのトポロジーは「SCCCC SCCCC」と表示され、「S」はソケット、「C」は空きコア、小さな「c」はすでに占有されているコア、小さな太字の「c」は例のジョブによって新たに占有されたコアを表します。

linear / linear_per_task は、Altair Grid Engine がタスクごとに連続したコアにジョブをバインドしようとすることを意味します。linear は “per host” 戦略で、与えられたホスト上ですべてのタスクのすべてのコアが線形でなければならないことを意味します。

Example:

(Host) SCCCC SCCCC (tasks: 0)
qsub -pe mype 1-3 -binding linear:2
(Host) Scccc SccCC (tasks: 3)

On two hosts with already occupied cores:
(Host 1) SCCCC SCcCC (tasks: 0)
(Host 2) SCcCC SCCCC (tasks: 0)
qsub -pe mype 4-6 -binding linear:2 would lead to:
(Host 1) Scccc SCcCC (tasks: 2)
(Host 2) SCccc Scccc (tasks: 3)
5 tasks are scheduled and all cores of these tasks are linear.

On the other hand, if one uses linear_per_task, one would get:
(Host 1) SCCCC SCcCC (tasks: 0)
(Host 2) SCcCC SCCCC (tasks: 0)
qsub -pe mype 4-6 -binding linear_per_task:2 would lead to:
(Host 1) Scccc SCccc (tasks: 3)
(Host 2) SCccc Scccc (tasks: 3)
leading to a total of 6 tasks, each task having 2 linear cores.

striding / striding_per_task は、Altair Grid Engine があるオフセットでコアを探そうとすることを意味します。 タスクごとに n -1 個のコアのオフセットを持つ空のコアを選択します。 探索アルゴリズムの始点はソケット 0 コア 0 であり、コア数が見つかればすぐにジョブバインディングに使用されます。 十分な空きコアがない場合、または正しいオフセットが得られない場合は、バインディングは行われません。

Example:

(Host) SCCCC SCCCC (tasks: 0)
qsub -pe mype 1-3 -binding striding:2:2
(Host) ScCcC ScCcC (tasks: 2)

これは、このホストでストライドできるタスクの最大量です。

すでにコアが占有されている2台のホストでは、以下の通りです。

(Host 1) SCCCC ScCCC (tasks: 0)
(Host 2) SCcCC SCCCC (tasks: 0)
qsub -pe mype 4-6 -binding striding:2 would lead to:
(Host 1) SCcCc SccCc (tasks: 2)
(Host 2) ScccC ScCcC (tasks: 2)

4つのタスクがスケジュールされており、残りの空きコアはホストごとのストライドに違反するため、このジョブでは使用できません。ホストごとのストライディングに反するためです。

一方、striding_per_taskを使うと、次のようになります。

(Host 1) SCCCC ScCCC (tasks: 0)
(Host 2) SCcCC SCCCC (tasks: 0)
qsub -pe mype 4-6 -binding striding_per_task:2
(Host 1) Scccc SccCc (tasks: 3)
(Host 2) ScccC Scccc (tasks: 3)

合計6つのタスクがスケジュールされることになります(striddenタスクはインターリーブできるため)。

explicit / explicit_per_task 指定されたソケット/コアのリストに記載されたソケットとコアを結合します。 各ソケット/コアのペアは一度だけ指定する必要があります。 ソケット/コアのペアがすでに別のジョブで使用されている場合、このホストはスキップされます。 explicit の場合、コア数を指定できないため、1タスクあたり1コアを使用します。 explicit_per_task は、各タスクがソケット/コアペアの数と同じだけコアを取得することを意味します。 また、各タスクは各ホストで一度だけ存在できるバインディングを持たなければならないので、ホストあたり一つのタスクしかスケジュールできないことを意味します。

Example:

(Host 1) SCCCC SCCCC (tasks: 0)
(Host 2) SCCCC SCCCC (tasks: 0)
qsub -pe mype 2-7 -binding explicit:0,1:0,2:1,0:1,3
(Host 1) SCccC ScCCc (tasks: 4)
(Host 2) SCccC ScCCC (tasks: 3)

各タスクは1つのコアを取得します。 ホスト2には別のタスクが存在する可能性がありますが、要求されるタスクは7つまでです。7タスクまでしか要求されません。

一方、explicit_per_taskを使用すると、次のようになります。

(Host 1) SCCCC SCCCC (tasks: 0)
(Host 2) SCCCC SCCCC (tasks: 0)
qsub -pe mype 2-7 -binding explicit_per_task:0,1:0,2:1,0:1,3
(Host 1) SCccC ScCCc (tasks: 1)
(Host 2) SCccC ScCCc (tasks: 1)

各タスクは4コアを取得します。

balance_sockets は、Altair Grid Engine によって最もコア数の少ないソケットから、[amount]個のフリーコアを結合します。 そのホストにタスクが配置できなくなるか、要求されたタスクがすべて配置されるまで、すべてのソケットを繰り返し、その都度、最も少ない結合コアのソケットを満たします。 ホストには、フリーコアを[amount]で割った数だけタスクが配置できます。

Example:

(Host 1) SCCCC SCCCC (tasks: 0)
(Host 2) SCCCC SCCCC (tasks: 0)
qsub -pe mype 2-7 -binding balance_sockets:3
(Host 1) ScccC ScccC (tasks: 2)
(Host 2) ScccC ScccC (tasks: 2)

ソケット 0 には占有コアがないので、そこにタスクが配置されます。ソケット1には占有コアがなく、ソケット0には3つあるので、次のタスクはソケット1が選ばれます。ソケット1が選ばれ、次のタスクが実行されます。 空いているコアは2つだけです。2つのコアしか残っておらず、他のタスクを実行するには十分ではありません。

すでにコアが占有されている2台のホストでは以下の通り。

(Host 1) SCCCC ScCCC (tasks: 0)
(Host 2) SCcCC SCCCC (tasks: 0)
qsub -pe mype 2-7 -binding balance_sockets:3 would lead to:
(Host 1) ScccC Scccc (tasks: 2)
(Host 2) Scccc ScccC (tasks: 2)

pack_sockets は、Altair Grid Engine によって既に結合されているコアの数が最も多いソケット、つまり空きコアの数が最も少ないソケットから、空きコアを [amount] 個結合します。 そのホストにタスクが配置できなくなるか、要求されたタスクがすべて配置されるまで、すべてのソケットを繰り返し、その都度、最も多くのコアがバインドされたソケットを満たします。 一つのホストには、空きコアを [amount] で割った数のタスクを置くことができます。

Example:

(Host 1) SCCCC SCCCC (tasks: 0)
(Host 2) SCCCC SCCCC (tasks: 0)_
qsub -pe mype 2-7 -binding pack_sockets:2
(Host 1) Scccc Scccc (tasks: 4)
(Host 2) Scccc SccCC (tasks: 3)

次のタスクもソケット0に配置されます。ソケット0は最も多くのコアが結合されており、他のタスクのために十分な空きコアがあるからです。 これで、ソケット0は満杯になりました。ソケット1もホスト2と同じように満タンになります。

すでにコアが占有されている2台のホストでは以下の通り。

(Host 1) SccCC ScCCC (tasks: 0)
(Host 2) SCccC SCCcC (tasks: 0)
qsub -pe mype 2-7 -binding pack_sockets:2 would lead to:
(Host 1) Scccc ScccC (tasks: 2)
(Host 2) Scccc ScccC (tasks: 2)

ここでは、まずソケット0が満たされます。 次にソケット1です。 ソケット1には1つのコアしか残っていませんが、これはタスクには十分ではありません。 そのため、ホスト1が満杯になりました。 ホスト2も同じように満杯になります。

one_socket_balanced / one_socket_per_task は、1ホストまたは1タスクにつき、1つのソケットのみをバインドします。 one_socket_balanced は最も多くのフリーコアを持つソケットを、 one_socket_per_task は左から右へ、タスクが配置可能なソケットをそれぞれ取ります。

Example:

(Host 1) SCCCC SCCCC (tasks: 0)
(Host 2) SCCCC SCCCC (tasks: 0)
qsub -pe mype 2-7 -binding one_socket_balanced:2
(Host 1) Scccc SCCCC (tasks: 2)
(Host 2) Scccc SCCCC (tasks: 2)
There can only be one socket per host, and therefore 4 tasks
can be scheduled in total.

With one_socket_per_task on the other hand, one would get
(Host 1) SCCCC SCCCC (tasks: 0)
(Host 2) SCCCC SCCCC (tasks: 0)
qsub -pe mype 2-7 -binding one_socket_per_task:2
(Host 1) SccCC SccCC (tasks: 2)
(Host 2) SccCC SccCC (tasks: 2)
Again, 4 tasks can be scheduled, but now they are distributed across
4 sockets.

qalterでは、ジョブの実行中であってもこのオプションを変更することができます。 ただし、変更したパラメータが有効になるのは、ジョブの再起動や移行を行った後です。

このオプションまたはqmonの対応する値が指定されると、これらの値はbinding_strategy, binding_type, binding_amount, binding_step, binding_socket, binding_core, binding_exp_n,binding_exp_socket[id], binding_exp_core という名前のパラメータとして定義済みJSVインスタンスに渡される。

なお、明示的バインディングのソケット/コア値リストの長さは、binding_exp_n として報告される。 [id] は、明示的なリスト内のソケット/コアのペアの位置に置き換えられる (0 <= id < binding_exp_n)。 explicit バインディングの最初のソケット/コアのペアを binding_exp_socket0, binding_exp_core0 というパラメータ名で報告する。

binding_strategy には以下の値を指定できる: linear_automatic, linear, striding, striding_automatic, linear_per_task, striding_per_task, explicit, explicit_per_task. linear_automaticは、コマンドラインの-binding linear:に対応する。 したがって、binding_amountは、要求されたコアの量に設定されなければなりません。 linear は、コマンドラインから “-binding linear:[N]:[socket],[core]” と指定した場合に対応します。 binding_amount に加えて、開始ソケット (binding_socket) と開始コア (binding_core) を設定する必要があります。 さもなければ、”-binding linear::0,0 “として扱われ、”-binding linear:”とは異なる。 striding_automaticとstridingには同じルールが適用される。 自動の場合はスケジューラ自身が空いているコアを探すが、自動でない場合は bind_socket と binding_core で指定された位置のコアを可能であれば埋め始める(そうでなければホストをスキップする)。

指定されたバインディングに適用されない値は、JSVに報告されません。 例
バインディングが明示的に指定されている場合、binding_stepはstridingバインディングに対してのみ報告され、すべてのbinding_exp_*の値はJSVに渡されます。

JSVでバインディング戦略を変更する場合、選択したバインディング戦略に属さないパラメータをすべて0に設定し、拒否される可能性のある組み合わせを避けることが重要である。 たとえば、コマンドラインでストライドを要求しているジョブをリニアに変更する場合、JSVはbinding_strategyの変更に加えてbinding_stepと場合によってはbinding_exp_nをゼロに設定しなければなりません(下記の-jsvオプション参照、あるいはsge_jsv(5)においてJSVに関するより詳しい情報を見つけることが可能です)。

もし、あるホストの一部のコアだけをコアバインディングに利用したい場合(例えば、このホストが Altair Grid Engine 以外のプロセスを実行している場合)、ロードセンサーを利用できます(sge_execd(8) を参照)。 この負荷センサーは、ホストのトポロジーを “m_topology_inuse” として返す必要がありますが、マスクするコアは小文字の “c” でマークされます。

Example:

A host with a topology like
examplehost: SCCCCSCCCC
should never bind its last two cores, as these are reserved for processes
outside of Altair Grid Engine.

Then a load sensor has to be configured on this host, returning
examplehost:m_topology_inuse:SCCCSCCcc