System.YieldProcessor
Delphi
procedure YieldProcessor;
プロパティ
種類 | 可視性 | ソース | ユニット | 親 |
---|---|---|---|---|
procedure | public | System.pas | System | System |
説明
現在のコードがスピン ループに入っていることを示すヒントをプロセッサに提供します。
YieldProcessor ルーチンにより、現在のコードがスピン ループに入っていることを示すヒントがプロセッサに提供されることで、スピン ループのパフォーマンスが向上します。
スピン ループは、スレッドの制御を OS に任せずにスレッドの実行を遅らせる手段で、その結果、OS はスケジューラを起動し、実行する別のスレッドを選択します。OS がスケジューラを起動する場合、結果としてコンテキスト スイッチが発生します。これは以下の処理を伴います。
- スレッドのコンテキスト(CPU レジスタの状態など)の保存
- ユーザー モードからカーネル モードへのカーネル遷移
- 実行する新しいスレッドの選択とそのコンテキストのロード
- カーネル モードからユーザー モードへのカーネル遷移
- CPU キャッシュ内のあらゆる状態、分岐予測バッファ(分岐履歴テーブルとも呼ばれます)、仮想メモリ ページのマッピングをキャッシュするための TLB(Translation Lookaside Buffer)などは、現在のスレッド内のコードを "ホット" にしてその実行速度を高めるのに役立ちましたが、これらは、新しいスレッドが(おそらく別のプロセスで)そっくり処理を再開すると失われます。
スレッドの想定される遅延がスレッド スライス(ミリ秒のオーダー)より小さい場合は、コンテキスト スイッチのコストを避けて、(Win32 関数の Sleep() を 0 を引数として呼び出すなど)スレッドを明け渡すのではなくスピン ループを使って待機する方が理にかなっている可能性があります。
このようなケースは、いわゆるロックフリー手法や同期プリミティブを用いたときに起こります。たとえば、InterlockedCompareExchange などのアトミックな条件判定および設定用のオペレーションでユーザーモード同期プリミティブが実装されることがあります。スレッド間で共有される変数(変数の新しい状態は何らかの形で前の状態に依存している)の状態を正確かつ確実に変更するには、OS 提供の同期プリミティブかループ内でのアトミックな条件判定および設定のどちらかを使用する必要があります。OS 提供の同期プリミティブを使用すると、輻輳の場合にコンテキスト スイッチが引き起こされます。ループ内でのアトミックな条件判定および設定は輻輳が発生するたびに失敗するだけなので、反復処理してもう一度試みます。しかし、あまり早く再試行した場合は、競合する他のスレッド(複数の場合あり)がまだビジーなので、時間つぶしをすることになる可能性があります。そのため、十分長い間待機して、他のスレッドがビジーでなくなっている可能性を高める必要があります。そこで、スピン ループが登場するのです。
警告: スピン ループとロックフリー手法を用いてパフォーマンスを向上させようとすると、パフォーマンス向上の可能性が中程度ある代わりに、エラーの危険性がかなり高まる場合があります。