OpenCL*: ヘテロジニアスによるアプローチの優位性
この記事は、インテル® デベロッパー・ゾーンに掲載されている「OpenCL*: the advantages of heterogeneous approach」の日本語参考訳です。
はじめに
GPGPU (GPU による汎目的計算) の台頭に伴い、GPU 自体が固定機能のラスタライズ・エンジンから汎用プロセッサーへと急速に進化しています。外付け GPU は通常、PCI Express* (PCIe) バスを介して CPU に接続されるため、デバイス間のデータ転送レートが大幅に制限されます。また、異なるメモリー空間/階層の明示的な境界とレイテンシーの大きなデバイス間の同期により、かなり粗粒度の抽象化がもたらされます。ほとんどの OpenCL* ワークロードは GPU のみをターゲットとしており、スケジューリング、ファイルおよびネットワーク I/O、その他の「ホスト」関連処理を CPU に任せています。この場合、タスクが小さく GPU の実行速度によって相殺できないと、PCIe 転送コストが非常に高くつきます。
従来のデスクトップ、ラップトップ、そして最近の Ultrabook™ デバイスでは、CPU と GPU のより緊密な統合が進み、これらが同じダイ上に配置されるだけでなく、CPU と GPU コアがユニファイド・メモリー階層を (ある程度) 共有する傾向にあります。そのため、動的な電圧や周波数のスケーリングなどの電力効率の良い設計により、CPU と GPU のどちらにも対応できるヘテロジニアス・アプローチが魅力的になりつつあります。
ここでは、実際の利点が並列ワークの割合、データ依存性、同期の必要性などのアプリケーションの特性にいかに依存するかを解析します。また、別の課題である、ヘテロジニアス抽象化 (例えば、CPU と GPU 間の自動タスク・スケジューリングで使用される「共有キュー」の概念) のサポートに必要なランタイムシステムの複雑さについても取り上げます。ヘテロジニアス・アプローチの 1 つの利点として次のものが挙げられます:
OpenCL* などの API を利用することで、ソフトウェアは CPU と GPU デバイスを同一のものとして見ることができます。
この記事では、SoC アーキテクチャー上の高度に統合されたシステム向けに最適化されたソフトウェアの可能性について述べます。ここでは、API として OpenCL* を使用します。また、同じ実行コンテキストで CPU とオンダイ GPU を利用するヘテロジニアス・アプローチのパフォーマンスについても評価します。業界ベンチマークを用いてヘテロジニアス・アプローチの影響を示し、OpenCL* を用いて CPU とインテル® HD グラフィックス・デバイスの両方で実行する方法を説明します。実際の結果はケースごとに異なります。ヘテロジニアス・アプローチによる優位性は、アプリケーションの並列領域の計算処理と全般的なワークフローに依存します。インテル® SDK for OpenCL* Applications にヘテロジニアス・コードのサンプルが含まれているので、参考にしてください。
インテル® SDK for OpenCL* Applications
インテル SDK for OpenCL Applications は、OpenCL* アプリケーション向けの統合ソフトウェア開発環境です。2013 バージョンでは、第 4 世代インテル® Core™ プロセッサーおよび互換プロセッサー・ベースの Windows* 7 および Windows 8 システム向けに OpenCL* 1.2 がサポートされています。この記事では、特定のベンチマーク、SDK ツール、サンプルを使用して解析します。
インテル® SDK for OpenCL Applications 2013 の詳細については、
https://www.izzz.us/article/intel-software-dev-products/intel-opencl/ を参照してください。
OpenCL* によるヘテロジニアス実行サポートの基本
OpenCL* は、「ホスト」 (OpenCL* を利用するアプリケーション) が 1 つ以上のデバイスにワークを送る、マスタースレーブ方式を実装します。カーネルに実行が送られると、n 次元のインデックス空間が定義されます。実行コンテキストもアプリケーションが定義します。各コンテキストには、ターゲットデバイス、関連付けられているコマンドキュー、デバイスがアクセス可能なメモリーのリストが含まれます。アプリケーションは、カーネル実行、メモリー・オブジェクト操作、イベント同期のコマンドをキューに追加できます。
OpenCL* を利用してアプリケーションは CPU または GPU にタスクを送れますが、ターゲットデバイスを明示的に指定する必要があります。そのため、デバイス間のロードバランスは、アプリケーション・レベルで実装されます。
同じ OpenCL* 実行コンテキストにおける CPU および GPU の使用
OpenCL* では、1 つのコンテキストに対してデバイスのリストを指定できます。ただし、キューは共有されないため、デバイスごとに個別のキューを作成する必要があります。適切な OpenCL* デバイスキューにタスクを送るのは、アプリケーションの責任です。
リソースの共有と同期は、OpenCL* 仕様の要件に従うべきです。コンテキスト・レベルで割り当てられたオブジェクトは、コンテキストにおいてデバイス間で共有されます。そのため、例えば、CPU と GPU で同じカーネル・オブジェクトを利用することができます。さらに、通常の clCreateBuffer/clCreateImage API 呼び出しで作成されるバッファーとイメージは、デフォルトで共有されます。インテル® SDK for OpenCL* Applications により提供されるランタイムは、メモリー・オブジェクトの作成時に CL_MEM_USE_HOST_PTR フラグが使用されると、ゼロコピーになります。(詳細は、最適化ガイド (http://software.intel.com/sites/products/documentation/ioclsdk/2013/OG/hh_goto.htm# Mapping_Memory_Objects_(USE_HOST_PTR).htm (英語)) を参照してください。) 共有メモリー・オブジェクトを使用する場合は、アプリケーションで特定のメモリー・アライメント要件を満たさなければいけません。
また、デバイスがほかのデバイスのタスク完了を待機する時間を最小限に抑えることが重要です。これは、データ並列アプローチでは、ジョブの分配の粒度を上げることで対応できる場合があります。タスク並列アプローチでは、生産タスクと消費タスク間で固定サイズのプールを作成し、デバイスが互いに協調して処理を進めると良いかもしれません。そうすることで、プールが一杯になり、1 つ目のデバイスが 2 つ目のデバイスからの結果を待機するためブロックされた場合、1 つ目のデバイスは、アイドル状態で待機する代わりに別のタスク (2 つ目のデバイスによって処理されるのを待機しているタスク) に取り掛かることができます。これらのアプローチについては、次の節で詳しく述べます。結果を待機する前に、clFlush でキューをフラッシュすることも重要です。キューをフラッシュすることで、GPU および CPU が並列に実行されます。(http://software.intel.com/sites/products/documentation/ioclsdk/2013/OG/hh_goto.htm# Synchronization_Caveats.htm (英語) のサンプルを参照してください。)
OpenCL* 仕様では、共有メモリー・オブジェクトのコンテンツを変更するコマンドが、そのメモリー・オブジェクトが別のコマンドキューによって使用される前にコマンドキューを終了するように、アプリケーションで保証する必要があるとしています。これを行う 1 つの方法は、イベントによってアクセスを保護することです。あるいは、オーバーラップせず適切にアライメントされたサブバッファーを使って、2 つのデバイスが同時に同じバッファーにデータ (またはカーネルの結果) を書き込むことができます。(詳細は、http://software.intel.com/sites/products/documentation/ioclsdk/2013/OG/hh_goto.htm# Writing_to_a_Shared_Resource.htm (英語) を参照してください。)
デバイス間のワークの分割
複数のデバイスを使用する場合、デバイスごとに個別のキューを作成する必要があります。ここでは、複数のデバイスのコマンドキュー間でワークを分割する方法について説明します。
静的に決定された相対的なデバイス速度に応じて静的にワークを割り当てると、全体的なパフォーマンスが低下する可能性があります。デバイス速度は、OS/ドライバーのスケジューリングや動的な周波数のスケーリングに影響されます。より良い方法は、現在のデバイスの負荷と速度を考慮して、動的にワークを割り当てることです。
動的スケジューリングにはいくつかのアプローチがあります。
- CPU および GPU 間の粗粒度のワーク分割
-
ビデオフレームや複数のイメージファイルなど、独立したデータは別々のデバイスに分配して処理すると良いでしょう。このアプローチは、スケジューリング・オーバーヘッドを最小限に抑えます。ただし、優れたロードバランスを達成するには、十分な量のデータが必要です。このアプローチは、OpenCL* ベンチマークの SiSoftware Sandra* で採用されています。(後述の「業界ベンチマーク」の節を参照してください。) このアプローチは、共有 LLC、メモリー帯域幅 (特にメモリーにより制限されるカーネル) などの共有システムリソースの負荷を増やす傾向があります。
-
処理されるデータが複数のデバイスによって分割される場合は、「フレーム内」のロードバランス・アプローチを取ることができます。例えば、入力イメージの場合、CPU で最初の半分を処理し、GPU で残りを処理することができます。実際のデータ分割は、デバイスがタスクを完了する速度に基づいて動的に調整されるべきです。1 つの方法として、以前の「フレーム」のパフォーマンスを記録しておきます。このアプローチは、インテルによる NBody デモのロードバランスの実装で採用されています。(詳細は、後述の「ヘテロジニアス SDK サンプル」の節を参照してください。)
-
- 細粒度の分割
-
このアプローチは、「共有キュー」を模したワークプールからデバイスの要求に応じてデータを小さく分割します。高速なデバイスはより短時間で新しい入力を要求するため、自動的にロードバランスが取られます。粒度は、追加のスケジューリングとカーネルへの送信に伴うオーバーヘッドを相殺できるように十分な大きさでなければいけません。このアプローチは、LuxMark* ベンチマークで採用されています。(後述の「業界ベンチマーク」の節を参照してください。)
-
デバイス間のデータの分割方法を決定する場合、アプリケーションは各デバイスの推奨されるローカル/グローバル粒度を考慮すべきです。
また、タスク並列スケジューラーを利用することもできます。これは、タスクとデバイス性能に関する深い知識を要するカスタムアプローチです。例えば、マルチカーネル・パイプラインで、特定の種類のカーネルは常に GPU で実行するようにスケジュールすることができます。GPU のハードウェア・テクスチャー機能を利用する「イメージ」 OpenCL* メモリー・オブジェクトを使用するカーネルは常に GPU で実行し、ほかのカーネルは CPU あるいはどちらにもスケジュールされるようにできます。そうすることで、異なるカーネル・パイプライン・ステージを異なるデバイスに割り当てられます。マシンの学習機能により各種カーネルに最適なデバイスを判断する研究が行われていますが、これらは通常ドメイン固有か、複雑なヒューリスティック/スタティック・カーネル解析に基づきます。
周波数/電圧に関する基本的な考慮事項
デバイスのパフォーマンスは、動的な周波数のスケーリングに影響されます。例えば、両方のデバイスで同時に処理時間の長いカーネルを実行すると、一方または両方のデバイスがターボブーストにより消費電力と発熱量を管理できなくなります。これは、全体的なパフォーマンスの低下につながり、場合によっては、ヘテロジニアスでないシングルデバイスよりもパフォーマンスが低下することがあります。
同様に、GPU を使用する場合、割り込みやホストとの同期が頻繁に発生すると CPU の周波数が上がり、統合 GPU の周波数が下がります。インオーダー・キューのセマンティクスでは、ホスト-デバイス間で同期を必要としない一連の実行を指定できるため、インオーダー・キューによりこの問題を回避できます。
ヘテロジニアス SDK サンプル
インテル® SDK for OpenCL の基本サンプル「HDR Tone Mapping for Post Processing using OpenCL* – Multi-Device Version」には、ヘテロジニアス OpenCL* アプリケーション・ロジックの主要な設計原則が用いられています: http://software.intel.com/en-us/articles/vcsource-samples-hdr-tone-mapping-multi-device (英語)。
インテルは、Siggraph 2012 で NBody アプリケーションのヘテロジニアス・バージョンのデモを行いました: http://software.intel.com/file/m/45639 (英語)。デモのソースコードは、http://software.intel.com/en-us/vcsource/samples/opencl-cross-devices-nbody-simulation-sample (英語) から入手できます。このサンプル・アプリケーションには、CPU、GPU、CPU+GPU 構成があり、GUI を使って自動またはスタティック・ロード・バランスを選択できます。
パフォーマンス測定結果
テスト環境のセットアップ
この節では、CPU と GPU が統合された 3 つのプロセッサーのパフォーマンスを解析します。異なる技術の相違点を比較するため、デスクトップ向けプロセッサー (インテル® Core™ i7-3770K プロセッサー)、低周波数のモバイル向けプロセッサー (インテル® Core™ i7-3720QM プロセッサー)、低電力のモバイル向けプロセッサー (インテル® Core™ i7-3667U プロセッサー) の 3 つを使用し、これらのプロセッサーを搭載した 64 ビット版の Windows 7 マシンでテストを行いました。
インテル® Core™ i7-3770K プロセッサー | インテル® Core™ i7-3720QM プロセッサー | インテル® Core™ i7-3667U プロセッサー | |
---|---|---|---|
市場セグメント | デスクトップ | モバイル (ラップトップ) | モバイル (Ultrabook™ デバイス) |
CPU ベース (ターボ) 周波数 (MHz) | 3500 (3900) | 2600 (3600) | 2000 (3000) |
CPU コア/スレッド | 4/8 | 4/8 | 2/4 |
統合 GPU | インテル® HD グラフィックス 4000 | インテル® HD グラフィックス 4000 | インテル® HD グラフィックス 4000 |
GPU ベース (ターボ) 周波数 (MHz) | 650 (1150) | 650 (1250) | 350 (1150) |
熱設計電力 (ワット) | 77 | 45 | 17 |
ここでは、ヘテロジニアス (「プラットフォーム」) パフォーマンスに注目するため、各マイクロアーキテクチャーの詳細については触れません。ここで重要なのは、CPU、GPU、CPU+GPU を使用した場合の各プロセッサーの全体的なパフォーマンスの相違です。
テストには、インテル® SDK for OpenCL Applications 2013 Gold とグラフィックス・ドライバー 9.18.10.3063 (http://software.intel.com/en-us/vcsource/tools/opencl-sdk-2013 (英語)) を使用しました。
業界ベンチマーク
CPU と GPU で同時に実行する「プラットフォーム」モードのテストをサポートする、2 つの業界ベンチマークでパフォーマンスを評価します。1 つ目の LuxMark* (http://www.luxrender.net/wiki/LuxMark (英語)) は、OpenCL* を使用するレイトレーシング・ベンチマークです。細粒度のタスク分割により、CPU と GPU 間のロードバランスを取ります。テストに使用した LuxMark* 2.0 には、複雑さ (および実際の光線発散) が異なる 5 つのシナリオがあります。ここでは、2 つのシナリオの結果のみ紹介します。ほかのシナリオの結果も、この 2 つのシナリオの結果に似ています。
2 つ目は、SiSoftware (http://www.sisoftware.net/ (英語)) の有名な Sandra* (バージョン 2012 SP5) ベンチマークです。LuxMark* とは対照的に、暗号化 (整数演算を多用する) テストから浮動小数点演算を多用するテストまで、広範なドメインにわたるテストを提供します。計算負荷の高いワークロード (複数のデバイスを使用することで最も多くの利点が得られる) のスケーラビリティーに注目するため、解析ではいくつかのテストを除外しています。例えば、GPU 上で倍精度はエミュレートされ、エミュレートされた場合のみプラットフォーム・スコアが得られるため、倍精度テストは除外しています。これは、CPU (シングルデバイス・モードでの) 実行のほうが適しているタスクの良い例です。CPU では、倍精度に対してネイティブサポートを提供しているため、CPU のほうが倍精度テストには適しています。また、メモリー帯域幅テストも除外しています。メモリー帯域幅は、デバイスの数に応じてスケーリングしないためです。メモリー帯域幅テストは、あるデバイスにおいて、あるいは特定のデバイスとホスト間でメモリー転送を行う API を呼び出すだけなので、ほかのデバイスの「助け」を借りること (つまり、ワークが分割されること) はありません。
Ultrabook™、ラップトップ、デスクトップのプラットフォーム・スコアの相違点
ヘテロジニアス・アプローチのパフォーマンス上の優位性を検証するため、前述のベンチマークを用いて CPU、GPU、プラットフォーム (CPU+GPU) のパフォーマンスを測定しました。個々のベンチマーク・テストの結果については、後続の節で述べます。以下に、プロセッサーごとのすべてのテストの幾何平均 n を示します。
図 1. インテル® Core™ i7-3667U プロセッサー、インテル® Core™ i7-3720QM プロセッサー、インテル® Core™ i7-3770K プロセッサーにおける、CPU-のみおよび GPU-のみのケースと比較したプラットフォーム (CPU+GPU) のパフォーマンス。Sandra*/LuxMark* テストの幾何平均。“1.0” 上の緑の点線は、特定のシングルデバイス・ケースのパフォーマンスを示す。
性能に関するテストに使用されるソフトウェアとワークロードは、性能がインテル® マイクロプロセッサー用に最適化されていることがあります。SYSmark* や MobileMark* などの性能テストは、特定のコンピューター・システム、コンポーネント、ソフトウェア、操作、機能に基づいて行ったものです。結果はこれらの要因によって異なります。製品の購入を検討される場合は、他の製品と組み合わせた場合の本製品の性能など、ほかの情報や性能テストも参考にして、パフォーマンスを総合的に評価することをお勧めします。 |
最初に、プラットフォーム・モードでは、シングルデバイス・アプローチよりも 1.6 ~ 2.8 倍のパフォーマンス向上が得られることが分かります。プロセッサーごとに (CPU と GPU の相対速度に依存して) パフォーマンスの向上幅は異なりますが、3 つのケース (CPU のみ、GPU のみ、CPU+GPU) の中ではヘテロジニアス・アプローチが最良のパフォーマンスを達成しています。つまり、各デバイスの利用をハードコードする場合と比べて、ヘテロジニアス・アプローチはエンドユーザー向けプロセッサーの違いに最も良く適合しています。
各プロセッサーのプラットフォーム・スコアに対する CPU と統合 GPU の影響を理解するため、次の 2 つの極端なケースについて考えてみましょう: 強力なCPU を搭載したデスクトップ・プロセッサーと通常 Ultrabook™ デバイスに搭載されている低周波数/省電力のプロセッサー (詳細は前述の表を参照してください)。
図 2. 3 つのプロセッサーの CPU+GPU プラットフォームに対する CPU と GPU の影響。インテル® Core™ i7-3667U プロセッサー (Ultrabook™ デバイス [上])、インテル® Core™ i7-3720QM プロセッサー (モバイル・ラップトップ [中央])、インテル® Core™ i7-3770K プロセッサー (デスクトップ [下])。グラフ中の “1” は、プラットフォーム・パフォーマンスを示す。
性能に関するテストに使用されるソフトウェアとワークロードは、性能がインテル® マイクロプロセッサー用に最適化されていることがあります。SYSmark* や MobileMark* などの性能テストは、特定のコンピューター・システム、コンポーネント、ソフトウェア、操作、機能に基づいて行ったものです。結果はこれらの要因によって異なります。製品の購入を検討される場合は、他の製品と組み合わせた場合の本製品の性能など、ほかの情報や性能テストも参考にして、パフォーマンスを総合的に評価することをお勧めします。 |
インテル® Core™ i7-3770K プロセッサー (デスクトップ) では、より多くのコア数、高い動作周波数、大きなパワー特性により、一般に CPU が統合 GPU を上回っています。そのため、プラットフォーム・スコア全体に最も貢献しているのは、OpenCL* を実行する CPU です。インテル® Core™ i7-3667U プロセッサー (Ultrabook™ デバイス) では、プラットフォーム・モードのパフォーマンスはより安定しています。これらのテストのプラットフォーム・スコア全体に最も貢献しているのは、ほとんどの場合 GPU です。インテル® Core™ i7-3720QM プロセッサー (モバイル・ラップトップ) の結果は、インテル® Core™ i7-3667U プロセッサーとインテル® Core™ i7-3770K プロセッサーの中間と言えます。
ヘテロジニアス・アプローチに関する今後の研究では、「最小電力」と「最大パフォーマンス」、あるいはより複雑な相違点を検証してみると良いでしょう。
まとめ
通常、OpenCL* は GPU のパフォーマンスのみを引き出す API と考えられていますが、実際には違います。CPU と GPU が同じダイ上にあるだけでなく、メモリー階層も共有する統合設計では、CPU とGPU を利用して同時に効率良く実行することができます。これにより、大幅なパフォーマンス向上がもたらされます。また、ヘテロジニアス・アプリケーションを設計することで (CPU と GPU を同時にバランス良く実行できるため)、各種プラットフォーム間のデバイス性能の違いに、より自動的に対応することができます。1 種類のデバイスのパフォーマンスに依存するのではなく、適切な動的ロードバランス・ロジックによって、より高速なデバイスにより多くのワークを分配できます。同様に、あるデバイスがほかのワークの処理を行っている場合、GPU が付加の高いレンダリング処理を行っている場合、CPU がファイル I/O 処理を行っている場合など、必要に応じてデバイス間のバランスを再調整することができます。
アプリケーションのヘテロジニアス実行に強固で使いやすいランタイムシステムを提供する 1 つの方法は、今日のプログラミング・モデルにマルチデバイス実行サポートを加えることです。例えば、(同じプラットフォーム上の複数のデバイスで利用される) 共有キューなどにより、複雑なカスタム基盤を回避できます。優れたパフォーマンスをもたらすこのアプローチは、ラップトップや Ultrabook™ デバイスなどの大きな市場セグメントにおいて、真のヘテロジニアス・プログラミングとして急速に普及することでしょう。
さらに詳しい情報は、https://www.izzz.us/article/intel-software-dev-products/intel-opencl/ を参照してください。
著者紹介
Maxim Shevtsov
インテル コーポレーションの OpenCL* パフォーマンス・チームのソフトウェア・アーキテクト。2003 年にコンピューター・サイエンスの修士号を取得し、2005 年にインテルに入社する前はコンピューター・グラフィックスに関するさまざまな学術研究に従事していました。
Intel、インテル、Intel ロゴ、Intel Core は、アメリカ合衆国および / またはその他の国における Intel Corporation の商標です。
© 2013 Intel Corporation. 無断での引用、転載を禁じます。
* その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。
OpenCL および OpenCL ロゴは、Apple Inc. の商標であり、Khronos の使用許諾を受けて使用しています。
コンパイラーの最適化に関する詳細は、最適化に関する注意事項を参照してください。