Share via


同時実行ランタイムとその他の同時実行モデルの比較

更新 : 2010 年 7 月

ここでは、同時実行ランタイムの機能およびプログラミング モデルと他のテクノロジの相違点について説明します。 同時実行ランタイムのメリットと他のプログラミング モデルのメリットの違いを理解しておけば、アプリケーションの要件に最も適したテクノロジを選択できます。

現在、Windows スレッド プールや OpenMP などの別のプログラミング モデルを使用している場合は、状況に応じて同時実行ランタイムに移行すると効果的です。 たとえば、「OpenMP から同時実行ランタイムへの移行」では、OpenMP から同時実行ランタイムに移行するのが適した状況について説明しています。 ただし、アプリケーションのパフォーマンスと現在のデバッグ サポートに満足している場合、移行は不要です。

同時実行ランタイムの優れた機能と生産性向上を通じて、別の同時実行モデルを使用する既存のアプリケーションを補完できます。 同時実行ランタイムでは、複数のタスク スケジューラが同じコンピューティング リソースを求めて競合する場合に、負荷分散は保証されません。 ただし、作業負荷が重複しない場合、この影響はごくわずかです。

セクション

  • プリエンプティブ スケジューリングと協調スケジューリングの違い

  • 同時実行ランタイムと Windows API の違い

  • 同時実行ランタイムと OpenMP の違い

プリエンプティブ スケジューリングと協調スケジューリングの違い

プリエンプティブ モデルと協調スケジューリング モデルには、複数のタスク間でコンピューティング リソース (たとえば、プロセッサ、ハードウェア スレッド) を共有できるようにする一般的な方法として 2 つの方法があります。

プリエンプティブ スケジューリングと協調スケジューリング

プリエンプティブ スケジューリングは、ラウンド ロビン方式の優先順位ベースのメカニズムで、すべてのタスクに対し、コンピューティング リソースへの排他アクセス権を所定の時間だけ与え、その後別のタスクに切り替えます。 プリエンプティブ スケジューリングは、Windows などのマルチタスク オペレーティング システムで一般的に使用されています。協調スケジューリングは、タスクが終了するまで、またはタスクがリソースへのアクセス権を譲るまで、コンピューティング リソースへの排他アクセス権をすべてのタスクに与える機構です。 同時実行ランタイムは、協調スケジューリングとオペレーティング システムのプリエンプティブ スケジューラを併用して、処理リソースを最大限に活用します。

プリエンプティブ スケジューラと協調スケジューラの違い

プリエンプティブ スケジューラは、複数のスレッドに対し、コンピューティング リソースへの公平なアクセス権を付与しようとすることで、すべてのスレッドを進行させます。 多くのコンピューティング リソースのあるコンピューターでは、公平なアクセスを保証すると問題は減少しますが、リソースを効率的に使用することを保証すると問題が増えます。

プリエンプティブ カーネル モード スケジューラでは、スケジュールの決定をオペレーティング システムに依存するアプリケーション コードが必要になります。 これに対し、ユーザー モード協調スケジューラでは、アプリケーション コードで独自のスケジュールを決定できます。 協調スケジューリングにより、アプリケーションは多くのスケジュールの決定を実行できるため、カーネル モードの同期に関連するオーバーヘッドが大幅に減少します。 協調スケジューラは、スケジュールするその他の作業がない場合、通常はスケジュールの決定をオペレーティング システムのカーネルに委ねます。 また、カーネルに伝達されるブロック操作がある一方で、その操作がユーザー モード スケジューラに伝達されない場合にも、協調スケジューラはオペレーティング システムのスケジューラに従います。 ユーザー モード スケジュール可能 (UMS: User-Mode Schedulable) スレッドをサポートするオペレーティング システムでは、同時実行ランタイム スケジューラは、これらのブロック操作を協調ブロッキング操作に変換します。

協調スケジューリングと効率

プリエンプティブ スケジューラにとって、同じ優先順位を持つ作業はすべて同等です。 プリエンプティブ スケジューラは、通常、作成された順番にスレッドをスケジュールします。 さらに、プリエンプティブ スケジューラは、すべてのスレッドに対し、スレッド優先順位に基づきラウンド ロビン方式でタイム スライスを与えます。 このメカニズムは公平です (すべてのスレッドが進行します) が、ある程度効率が損なわれます。 たとえば、計算量が非常に多いアルゴリズムには、公平性は不要です。 代わりに、全体の時間を最小にして関連するタスクを終了させることが重要になってきます。 協調スケジューリングにより、アプリケーションはより効率的に作業をスケジュールできます。 たとえば、多数のスレッドを使用するアプリケーションを考えてみます。 リソースを共有しないスレッドが同時に実行されるようにスケジュールすると、同期のオーバーヘッドを減少させることができ、それにより効率を向上させることができます。 タスクをスケジュールするもう 1 つの効率的な方法は、同じプロセッサでタスクのパイプラインを実行する方法です。タスクのパイプラインでは、前のタスクの出力に基づき各タスクが実行され、各パイプライン ステージの入力がメモリ キャッシュ内に事前に読み込まれます。

プリエンプティブ スケジューリングと協調スケジューリングの併用

協調スケジューリングでは、スケジューリングのすべての問題は解決しません。 たとえば、他のタスクに公平に譲歩しないタスクが、使用できるすべてのコンピューティング リソースを占有し、それにより他のタスクの処理が妨げられる可能性があります。 同時実行ランタイムは、協調スケジューリングの効率面での利点を使用して、プリエンプティブ スケジューリングの公平性をより完全にします。 既定では、同時実行ランタイムには、ワーク スティーリング アルゴリズムを使用して複数のコンピューティング リソースに作業を効率的に分配する協調スケジューラが用意されています。 ただし、同時実行ランタイム スケジューラは、複数のアプリケーションにリソースを公平に分配するために、オペレーティング システムのプリエンプティブ スケジューラにも依存します。 また、アプリケーションでカスタム スケジューラおよびスケジューラ ポリシーを作成して、スレッドの実行を詳細に制御することもできます。

[ページのトップへ]

同時実行ランタイムと Windows API の違い

Microsoft Windows アプリケーション プログラミング インターフェイス (通常は Windows API と呼ばれます。以前は Win32 と呼ばれていました) は、アプリケーションで同時実行を可能にするプログラミング モデルを提供します。 同時実行ランタイムは、基になるオペレーティング システムから利用できない追加のプログラミング モデルを提供するために、Windows API を基に構築されています。

同時実行ランタイムは、並列処理を実行するために Windows API スレッド モデルを基に構築されています。 また、Windows API メモリ管理メカニズムおよびスレッド ローカル ストレージ メカニズムも使用します。 Windows 7 および Windows Server 2008 R2 では、ユーザー スケジュール可能スレッドに関する Windows API サポート、および 64 を超えるハードウェア スレッドのあるコンピューターに関する Windows API サポートを使用します。 同時実行ランタイムは、協調タスク スケジューラおよびワーク スティーリング アルゴリズムを提供してコンピューティング リソースを最大限に活用すること、および複数のスケジューラ インスタンスを同時に使用できるようにすることで、Windows API モデルを拡張します。

Windows API の詳細については、「Overview of the Windows API (Windows API の概要)」を参照してください。

プログラミング言語

Windows API は、プログラミング モデルを公開するために C プログラミング言語を使用しています。 同時実行ランタイムは、C++ 言語の最新機能を利用する C++ プログラミング インターフェイスを提供しています。 たとえば、ラムダ関数は、並列処理関数を定義するための簡潔なタイプ セーフ メカニズムを提供します。 同時実行ランタイムが使用する最新の C++ 機能の詳細については、「同時実行ランタイムの概要」を参照してください。

スレッドとスレッド プール

Windows API の中心となる同時実行メカニズムはスレッドです。 通常、CreateThread 関数を使用してスレッドを作成します。 スレッドは比較的簡単に作成して使用できますが、オペレーティング システムは、それらを管理するのに時間とその他のリソースを非常に多く割り当てます。 さらに、各スレッドには、同じ優先順位の他のスレッドと同じ実行時間が割り当てられることが保証されていますが、関連するオーバーヘッドのために、十分に大きいタスクを作成する必要があります。 小規模なタスクまたは詳細なタスクの場合、同時実行に関連するオーバーヘッドにより、並列にタスクを実行することの利点が打ち消される可能性があります。

スレッド プールは、スレッド管理のコストを削減する方法の 1 つです。 Windows API が提供しているカスタム スレッド プールとスレッド プール実装の 2 つは、小規模な作業項目を効率的に並列で実行できるようにします。 Windows スレッド プールは、先入れ先出し (FIFO: First In First Out) キューに作業項目を保持します。 各作業項目は、プールに追加された順番で開始されます。

同時実行ランタイムは、ワーク スティーリング アルゴリズムを実装することで、FIFO スケジューリング メカニズムを拡張しています。 このアルゴリズムは、まだ開始されていないタスクを、作業項目が不足しているスレッドに移動します。 ワーク スティーリング アルゴリズムでは、作業負荷のバランスを取ることができますが、作業項目の順番が変更される場合もあります。 この順番変更プロセスにより、送信された順番とは異なる順番で作業項目が開始される場合があります。 これは、より古いタスク間よりも、より新しいタスク間でデータが共有される機会が多い再帰的アルゴリズムで便利です。 新しい項目を取得して最初に実行すると、キャッシュ ミスが少なくなり、場合によってはページ フォールトも少なくなります。

オペレーティング システムの視点から見ると、ワーク スティーリングは不公平です。 ただし、タスクを並列に実行するためのアルゴリズムをアプリケーションが実装している場合、サブタスク間の公平性は通常は問題になりません。 問題となるのは、タスク全体をどの程度早く終了させることができるかです。 他のアルゴリズムでは、FIFO は適切なスケジューリング方法です。

さまざまなオペレーティング システムでの動作

Windows XP および Windows Vista では、同時実行ランタイムを使用するアプリケーションは同様に動作します。ただし、Windows Vista ではヒープのパフォーマンスが向上します。

Windows 7 および Windows Server 2008 R2 では、オペレーティング システムは同時実行とスケーラビリティをさらにサポートしています。 たとえば、これらのオペレーティング システムは、64 を超えるハードウェア スレッドのあるコンピューターをサポートしています。 Windows API を使用する既存のアプリケーションでこれらの新しい機能を利用するには、アプリケーションを変更する必要があります。 ただし、同時実行ランタイムを使用するアプリケーションは自動的にこれらの機能を使用するため、変更は必要ありません。

Windows 7 と Windows Server 2008 R2 の両方が、ユーザー モード スケジュール可能 (UMS) スレッドのサポートを追加しています。 UMS スレッドにより、ユーザー モード スケジューラおよびカーネルは、作業をより効率的にスケジュールできます。 UMS はプリエンプション (優先) を排除していませんが、カーネル遷移なしで協調スケジューリングをアプリケーションおよびライブラリで実行できるようにすることで、効率を向上させます。 また UMS は、カーネルでスレッドがブロックされると、アプリケーションに制御を戻します。このため、アプリケーションは、タイム スライスの残りの期間に追加の作業を実行できます。 オペレーティング システムが UMS スケジューリングをサポートしている場合は、同時実行ランタイムは UMS スケジューリングを自動的に使用します。 UMS の詳細については、「User-Mode Scheduling (ユーザー モード スケジューリング)」を参照してください。

[ページのトップへ]

同時実行ランタイムと OpenMP の違い

同時実行ランタイムでは、さまざまなプログラミング モデルを使用できます。 これらのモデルは、他のライブラリのモデルと重複する場合、または他のライブラリのモデルを補完する場合があります。 このセクションでは、同時実行ランタイムと OpenMP の違いについて説明します。

OpenMP プログラミング モデルは、オープン標準により定義されており、Fortran および C/C++ プログラミング言語に正しく準拠しています。 OpenMP バージョン 2.0 および 2.5 は、反復処理の並列アルゴリズムに適しています。つまり、これらは、データの配列を並列に反復処理します。 OpenMP は、並列化の度合いが事前に決定され、システムで使用可能なリソースと対応する場合に最も効果的です。 OpenMP モデルは、非常に大きい計算の問題が 1 台のコンピューターの処理リソース全体に分散される高パフォーマンスのコンピューティングに特に適しています。 このシナリオでは、ハードウェア環境が判明しており、このアルゴリズムが実行された場合、コンピューティング リソースへの排他アクセスがあることを、開発者は当然予測できます。

ただし、制約が少ないその他のコンピューティング環境は、OpenMP に適していない場合があります。 たとえば、再帰の問題 (クイックソート アルゴリズム、データ ツリーの検索など) を、OpenMP を使用して実装するのは比較的困難です。 同時実行ランタイムでは、並列パターン ライブラリ (PPL) や非同期エージェント ライブラリを使用して、OpenMP の機能を補うことができます。 同時実行ランタイムは、OpenMP と異なり、使用できるリソースに対応する動的スケジューラを提供しており、作業負荷の変化に応じて並列化の度合いを調整します。

同時実行ランタイムの機能の多くは拡張できます。 既存の機能を組み合わせて新しい機能を作成することもできます。 OpenMP はコンパイラ ディレクティブに依存しているため、簡単には拡張できません。

同時実行ランタイムと OpenMP の違い、および既存の OpenMP コードから同時実行ランタイムの使用に移行する方法の詳細については、「OpenMP から同時実行ランタイムへの移行」を参照してください。

[ページのトップへ]

参照

参照

Overview of the Windows API

概念

同時実行ランタイム

並列パターン ライブラリ (PPL)

非同期エージェント ライブラリ

その他の技術情報

同時実行ランタイムの概要

Visual C++ の OpenMP

履歴の変更

日付

履歴

理由

2010 年 7 月

移行と相互運用性に関する情報を追加。

情報の拡充