グランドセントラル派遣
Grand Central Dispatch ( GCD )は、マルチコアプロセッサおよびその他の対称型マルチプロセッシングシステムを備えたシステムのアプリケーションサポートを最適化するためにApple Inc.によって開発された技術です。これは、スレッドプールパターンに基づくタスクの並列処理の実装です。基本的な考え方は、スレッドプールの管理を開発者の手から、オペレーティングシステムに近づけることです。開発者は、プールのアーキテクチャを意識せずに「作業パッケージ」をプールに注入します。このモデルにより、シンプルさ、移植性、パフォーマンスが向上します。
GCDはMac OS X 10.6で最初にリリースされ、iOS 4以降でも利用可能です。 「Grand Central Dispatch」という名前は、Grand Central Terminalへの参照です。
GCDのサービスの実装libdispatchを提供するライブラリのソースコードは、2009年9月10日にAppleによってApacheライセンスでリリースされました。FreeBSD8.1.MidnightBSD 0.3-CURRENTを含むFreeBSDオペレーティングシステムに移植されましたブロックをサポートしない「libdispatch」。 LinuxおよびSolarisのサポートは、アップストリームトランク内で提供されます。 Windowsのサポートを開発するために、現在2つのフォークがopensource.mlba-team.deとGitHubにあります。 Appleには、SafariおよびiTunesに同梱されているWindows用のlibdispatch.dllの独自のポートがありますが、SDKは提供されていません。
設計
GCDは、並行して実行できるプログラム内の特定のタスクを実行キューに入れ、処理リソースの可用性に応じて、利用可能なプロセッサコアで実行するようにスケジューリングすることにより機能します(アップルでは「ルーティング」と呼ばれます) )。
タスクは、関数または「ブロック」として表現できます。ブロックは、C、C ++、およびObjective-Cプログラミング言語の構文の拡張機能であり、クロージャーに似た方法でコードとデータを単一のオブジェクトにカプセル化します。 GCDは、ブロックが使用できない環境でも引き続き使用できます。
Grand Central Dispatchは依然として低レベルでスレッドを使用しますが、多くの詳細に関心を持つ必要のないプログラマーからスレッドを抽象化します。 GCDのタスクは、作成およびキューイングが簡単です。 Appleは、GCDのワークユニットをキューに入れるには15の命令が必要であると述べていますが、従来のスレッドを作成するには数百の命令が簡単に必要になる場合があります。
Grand Central Dispatchのタスクを使用して、キューに配置される作業項目を作成するか、イベント項目に割り当てることができます。タスクがイベントソースに割り当てられている場合、イベントがトリガーされると、ブロックまたは関数からワークユニットが作成され、ワークユニットは適切なキューに配置されます。これは、単一のイベントのトリガーで待機することを唯一の目的とするスレッドを作成するよりも効率的であるとAppleによって説明されています。
特徴
ディスパッチフレームワークは、いくつかのデータ型と関数を宣言して、それらを作成および操作します。
- ディスパッチキューは、匿名コードブロックまたは関数のいずれかのタスクのキューを維持し、これらのタスクを順番に実行するオブジェクトです。ライブラリは、複数のタスクを同時に実行するさまざまな優先度レベルを持つ複数のキューを自動的に作成し、オペレーティング環境に基づいて実行する最適なタスク数を選択します。ライブラリのクライアントは、任意の数のシリアルキューを作成することもできます。シリアルキューは、送信された順にタスクを1つずつ実行します。シリアルキューは一度に1つのタスクしか実行できないため、キューに送信された各タスクはキュー上の他のタスクに関して重要であり、競合リソースのロックの代わりにシリアルキューを使用できます。
- ディスパッチソースは、ソケットまたはファイル記述子の読み取りまたは書き込みの準備ができている、またはPOSIX信号などのシステムイベントで非同期に実行するブロックまたは関数をクライアントが登録できるようにするオブジェクトです。
- ディスパッチグループは、後で参加するためにいくつかのタスクをグループ化できるオブジェクトです。タスクをグループのメンバーとしてキューに追加すると、クライアントはグループオブジェクトを使用して、そのグループ内のすべてのタスクが完了するまで待機できます。
- ディスパッチセマフォは、クライアントが特定の数のタスクのみを同時に実行できるようにするオブジェクトです。
例
この記事は、マニュアルやガイドブックのように書かれています。説明的で中立的な観点からこの記事を書き直し、アドバイスや指示を削除してください。 (2010年6月) (このテンプレートメッセージを削除する方法とタイミングをご覧ください) |
Grand Central Dispatchの使用を示す2つの例は、John SiracusaのArs Technica Snow Leopardレビューにあります。最初に、ドキュメントベースのアプリケーションには、ドキュメント内の単語と段落の数を数えるような何かをするanalyzeDocumentと呼ばれるメソッドがあります。通常、これはクイックプロセスであり、ユーザーがボタンを押してから結果が表示されるまでの遅延に気付くことなく、メインスレッドで実行できます。
ドキュメントが大きく、分析の実行に時間がかかる場合、メインスレッドは関数の終了を待ちます。十分な時間がかかると、ユーザーは気付くでしょうし、アプリケーションは「ビーチボール」でさえあります。解決策は次のとおりです。
ここで、への呼び出しはブロック内に配置され、グローバルな同時キューのいずれかに配置されます。実行が終了すると、新しいブロックがメインキュー(アプリケーションのメインスレッドが実行される)に配置され、GUIが更新されます(GUIはメインスレッドによってのみ更新できるため、これが必要です)。これら2つの小さな変更を行うことにより、開発者はユーザーから見たアプリケーションの停止を回避し、アプリケーションがハードウェアリソースをより有効に活用できるようにしました。
2番目の例は、forループの並列化です。
このコードは、do_work関数をcount回実行し、i番目の結果を配列の結果のi番目の要素に割り当て、ループが終了すると配列でsummaryを呼び出します。残念なことに、作業は連続して計算されるため、必要のない場合があります。 do_workが他の呼び出しの結果に依存しないと仮定すると、これらの呼び出しを同時に行うことができない理由はありません。これは、GCDでこれを行う方法です。
ここで、dispatch_applyは渡されたブロックを実行し、回数をカウントし、各呼び出しをグローバルキューに入れ、各ブロック呼び出しに0からcount-1までの異なる番号を渡します。これにより、OSは適切に作業を分散し、現在のハードウェアとシステムの負荷に対して実行する最適なスレッド数を選択できます。 dispatch_applyは、指定されたキューに配置されたすべてのブロックの実行が完了するまで戻りません。そのため、summerを呼び出す前に、元のループ内のすべての作業が完了したことが保証されます。
プログラマは、シリアルで実行する必要があることがわかっているが、別のスレッドで実行できるタスク用に独自のシリアルキューを作成できます。新しいキューは次のように作成されます。
これはデッドロックが保証されているため、キュー上のディスパッチされたブロックが同じキューに別のブロックを同期的に配置しないように注意する必要があります。このようなコードは次のことを実行できます。
用途
GCDはmacOS全体(10.6 Snow Leopard以降)で使用されており、AppleはmacOSアプリケーション開発者による採用を奨励しています。 FreeBSD開発者Robert Watsonは、プログラミングモデルとその方法を説明するために、Apache GCD MPM(マルチプロセッシングモジュール)を介してGCDを使用するための主要なオープンソースアプリケーションであるApache HTTPサーバーの最初の適応を発表しました。 GCDを既存の大規模なマルチスレッドアプリケーションに統合します。彼の発表によると、GCD MPMには他のスレッドMPMの3分の1から2分の1の行数があります。
内部
GCDはlibdispatchによって実装され、Appleが開発したpthreads非POSIX拡張機能からのサポートがあります。 Appleは、GCD(10.6)、Mountain Lion(10.8)、および最近のMavericks(10.9)の公式リリースを通じて、そのインターフェース(OS X 10.5)からインターフェースを変更しました。最新の変更では、ユーザーモードとカーネルの両方でpthreadをサポートするコードをプライベートにします(カーネルpthreadのサポートはshimのみに削減され、実際の実装は別のカーネル拡張に移動しました)。