スレッドのスケジューリング

スレッドをスケジュールすることができます。スレッド・ライブラリーには、 スレッドのスケジューリングの操作と制御のための機能がいくつかあります。

また、mutex のロックのような同期操作中のスレッドのスケジューリングを制御する機能もあります。 それぞれのスレッドには、独自のスケジューリング・パラメーターの集合があります。 これらのパラメーターは、スレッド作成の前に、スレッド属性オブジェクトを使用して設定することができます。 また、これらのパラメーターは、スレッドの実行中に動的に設定することもできます。

スレッドのスケジューリングの制御は、複雑なタスクになる場合があります。 スケジューラーはシステム全体のすべてのスレッドを扱っているため、 スレッドのスケジューリング・パラメーターは、 プロセス内および他のプロセス内の他のすべてのスレッドのスケジューリング・パラメーターと相互に作用し合います。 次の機能は、スレッドのスケジューリングを制御する場合、最初に使用する機能です。

スレッド・ライブラリーによって、プログラマーは次の方法でスレッドの実行スケジューリングを制御することができます。
  • スレッドを作成するときに、スケジューリング属性を設定する
  • 作成済みスレッドのスケジューリング属性を動的に変更する
  • mutex を作成するときに、スレッドのスケジューリングに対する mutex の影響を定義する (同期スケジューリング と呼ばれます)
  • 同期操作中にスレッドのスケジューリングを動的に変更する (同期スケジューリング と呼ばれます)

スケジューリング・パラメーター

スレッドには、次のスケジューリング・パラメーターがあります。

パラメーター 説明
有効範囲 スレッドのコンテンション有効範囲は、スレッド・ライブラリーで使用されるスレッド・モデルによって定義されます。
ポリシー スレッドのスケジューリング・ポリシーは、 スケジューラーが、CPU の制御を獲得した後、 スレッドをどのように取り扱うかを定義します。
優先順位 スレッドのスケジューリング優先順位は、 それぞれのスレッドによって実行される作業の相対的重要性を定義します。

スケジューリング・パラメーターは、スレッドの作成前またはスレッドの実行時に設定することができます。 一般に、スレッドのスケジューリング・パラメーターの制御が重要なのは、CPU 集中のスレッドの場合だけです。 したがって、 スレッド・ライブラリーは、ほとんどの場合に十分なデフォルト値を提供します。

inheritsched 属性の使用

スレッド属性の inheritsched 属性は、 スレッドのスケジューリング属性の定義方法を指定します。 次の値が有効です。

説明
PTHREAD_INHERIT_SCHED 新規スレッドがそれを作成したスレッドのスケジューリング属性 (schedpolicy 属性および schedparam 属性) を取得することを示します。 属性オブジェクトに定義されているスケジューリング属性は無視されます。
PTHREAD_EXPLICIT_SCHED 新規スレッドが、この属性オブジェクトに定義されているスケジューリング属性を取得することを示します。

inheritsched 属性のデフォルト値は、PTHREAD_INHERIT_SCHED です。 この属性は、pthread_attr_setinheritsched サブルーチンを呼び出して設定します。属性の現行値は、 pthread_attr_getinheritsched サブルーチンを呼び出して戻します。

スレッド属性オブジェクト内のスレッドのスケジューリング属性を設定するには、 最初に inheritsched を PTHREAD_EXPLICIT_SCHED に設定する必要があります。 設定していない場合、属性オブジェクトのスケジューリング属性は無視されます。

スケジューリング・ポリシーと優先順位

スレッド・ライブラリーには、次のスケジューリング・ポリシーが用意されています。

ライブラリー 説明
SCHED_FIFO 先入れ先出し (FIFO) スケジューリング。 各スレッドには固定された優先順位があり、 複数のスレッドが同じ優先順位レベルにある場合、FIFO の順序で完了するまで実行します。
SCHED_RR 周期的 (RR) スケジューリング。 各スレッドには固定された優先順位があり、複数のスレッドが同じ優先順位レベルにある場合、FIFO の順序で固定されたタイム・スライス分だけ実行します。
SCHED_OTHER デフォルト AIX® スケジューリング。 各スレッドには初期優先順位があり、 スレッドのアクティビティーに従ってスケジューラーによって動的に変更されます。 スレッドの実行は、タイム・スライスで行われます。 他のシステムでは、 このスケジューリング・ポリシーとは異なる場合があります。

AIX 5.3 以前のバージョンでは、スケジューリング・ポリシーを SCHED_OTHER に設定する場合のスレッド優先順位の変更は許可されていません。 この場合、カーネルは直接優先順位を管理し、 pthread_setschedparam サブルーチンに受け渡される 唯一の正当な値は DEFAULT_PRIO の値です。DEFAULT_PRIO の 値は pthread.h ファイル上で 1 として定義され、受け渡された他のいかなる値も無視されます。

AIX 5.3 から、スケジューリング・ポリシーを SCHED_OTHER に設定する場合に、スレッドの優先順位を変更できます。 pthread_setschedparam サブルーチンに受け渡せる 正当な値は 40 から 80 の範囲ですが、特権ユーザーだけは優先順位を 60 より大きく設定できます。 優先順位が 1 から 39 の範囲内にあると、優先順位が 40 と同じです。優先順位が 81 から 127 の範囲内 にあると、優先順位が 80 と同じです。

注: AIX では、カーネルによって優先順位が逆転します。 AIX カーネルに関しては、優先順位が 0 から 127 の範囲内にあり、ここでは 0 が最 も優先され、127 が最も優先されません。 ps コマンドなどのコマンドによって、 カーネル優先順位が報告されます。
スレッド・ライブラリーは、sys/sched.h ヘッダー・ファイルに定義されている sched_param 構造体を使用して優先順位を扱います。 この構造体には以下のフィールドがあります。
フィールド 説明
sched_priority 優先順位を指定する。
sched_policy このフィールドはスレッド・ライブラリーによって無視されます。 使用しないでください。

作成時のスケジューリング・ポリシーと優先順位の設定

スケジューリング・ポリシーは、 スレッド作成時にスレッド属性オブジェクトの schedpolicy 属性を設定することによって、設定することができます。 pthread_attr_setschedpolicy サブルーチンは、 スケジューリング・ポリシーを事前定義の スケジューリング・ポリシーの 1 つに設定することができます。 スレッド属性オブジェクトの schedpolicy 属性の現行値は、pthread_attr_getschedpolicy サブルーチンを使用して取得できます。

スケジューリング優先順位は、 スレッド作成時にスレッド属性オブジェクトの schedparam 属性を設定することによって、設定することができます。 pthread_attr_setschedparam サブルーチンは、 指定された構造体の値をコピーして、schedparam 属性の値を設定します。 pthread_attr_getschedparam サブルーチンは、schedparam 属性を取得します。

次のコード・フラグメントでは、優先順位 3 を使用して、 周期的スケジューリング・ポリシーでスレッドが作成されます。

sched_param schedparam;

schedparam.sched_priority = 3;

pthread_attr_init(&attr);
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&attr, SCHED_RR);
pthread_attr_setschedparam(&attr, &schedparam);

pthread_create(&thread, &attr, &start_routine, &args);
pthread_attr_destroy(&attr);
inheritsched 属性について詳しくは、inheritsched 属性の使用を参照してください。

実行時のスケジューリング属性の設定

pthread_getschedparam サブルーチンは、スレッドの schedpolicy および schedparam 属性を戻します。 これらの属性は、pthread_setschedparam サブルーチンを呼び出すことによって設定することができます。ターゲット・スレッドが、現在プロセッサー上で実行されている場合、 新規のスケジューリング・ポリシーと優先順位は、 次にスレッドがスケジュールされるときにインプリメントされます。 ターゲット・スレッドが実行中でない場合、サブルーチン呼び出しが終了すると、 すぐにスケジュールすることができます。

例えば、周期的ポリシーで現在スレッド T を実行している時に、T の schedpolicy 属性が FIFO に変更された場合を考えてみましょう。 T はそのタイム・スライスの終わりまで実行し続け、そのときにスケジューリング属性を再評価します。 優先順位がそれより高いスレッドがない場合、T はスケジュールを変更され、 同じ優先順位を持つ他のスレッドより前に実行されます。 低優先順位のスレッドが実行されていない、2 番目の例を考えてみます。 このスレッドの優先順位が pthread_setschedparam サブルーチン を呼び出している他のスレッドによってあげられ、 ターゲット・スレッドが実行可能スレッドで最高優先順位の場合、すぐにスケジュールされます。

注: 両方のサブルーチンとも policy パラメーターおよび sched_param 構造体を使用します。この構造体には sched_policy フィールドが入っていますが、 プログラムはこれを使用することはできません。 サブルーチンは、policy パラメーターを使用してスケジューリング・ポリシーを渡し、sched_policy フィールドを無視します。

スケジューリング・ポリシーに関する考慮事項

アプリケーションは、 特定のアプリケーションが固定優先順位のスケジューリング・ポリシーを使用する必要がある場合を除いて、 デフォルト・スケジューリング・ポリシーを使用しなければなりません。 デフォルト以外のポリシーの使用については、次の点を考慮してください。
  • 周期的ポリシーを使用すると、同じ優先順位レベルのスレッドは、 アクティビティーとは無関係に、すべて等しくスケジュールすることができます。 このことは、 スレッドがセンサーを読むかまたはアクチュエーターを書く必要があるプログラムでは、 役立つ可能性があります。
  • FIFO ポリシーを使用する際は、十分に注意を払う必要があります。 FIFO ポリシーで実行しているスレッドは、入出力操作の実行などの、 何らかのコールによってブロックされないかぎり、完了まで実行します。 高優先順位の FIFO スレッドを優先使用することはできず、 システムのグローバル・パフォーマンスに影響する場合があります。 例えば、大きいマトリックスの反転などの集中的計算を行うスレッドは、 絶対に FIFO ポリシーでは実行すべきではありません。

スケジューリング・ポリシーと優先順位の設定は、 スレッドのコンテンション有効範囲にも影響されます。 FIFO ポリシーまたは周期的ポリシーの使用は、いつも許可されるわけではありません。

sched_yield サブルーチン

sched_yield サブルーチンは、 yield サブルーチンのスレッド版に相当します。 sched_yield サブルーチンは、コール側のスレッドに、そのプロセッサーの使用を強制的にやめさせ、他のスレッドにスケジューリングの機会を与えます。 次にスケジュールされるスレッドは、コール側のスレッドと同じプロセスに属していても、 別のプロセスに属していても構いません。 マルチスレッド・プログラムでは yield サブルーチンを使用しないでください。

インターフェース pthread_yield サブルーチンは、 Single UNIX Specification, Version 2 では使用できません。