フルスロットル :*OpenMP 4.0

インテル® Cluster Studio XE 2013 SP1

の新機能

Issue

16
2013

目次
編集者からのメッセージ
ハイパフォーマンスが身近なものに

3James Reinders

インテル® Cluster Studio XE 2013 SP1 の新機能

4James Tullos

注目記事インテル® Cluster Studio XE 2013 SP1 の新機能の概要を説明します。この HPC ソフトウェア開発ツール・スイートには、分散型メモリープログラムのより高速かつ効率良い実行を支援する、最新のインテル® MPI ライブラリー
およびインテル® Trace Analyzer & Collector が含まれます。

フルスロットル : OpenMP* 4.0

6Michael Klemm、Christian Terboven
OpenMP* は、OpenMP* タスク、SIMD 命令、そしてアプリケーション・コード、サードパーティーのライブラリー、
ハードウェアの効率良い組み合わをサポートする新しい機能により、飛躍的な進歩を遂げました。

MPI 通信のプロファイリング ̶ ハイパフォーマンスのためのテクニック

17

James Tullos
インテル® Cluster Studio XE SP1 に含まれるパフォーマンス解析ツール、インテル® Trace Analyzer & Collector (ITAC)の使用例を説明します。ITAC を用いて MPI アプリケーションをプロファイルおよび解析することにより、パフォー
マンスが向上する可能性のある場所を特定できます。

インテル® Parallel Studio XE によるビデオ会議ソフトの高速化
Stephen Blair-Chappell
Pexip 社が、どのようにして処理能力を備えコスト効率に優れたシステムを設計し、従来の会議システムのパフォー
マンスを超えることができたのかを説明します。

Ⓒ 2013 Intel Corporation. 無断での引用、転載を禁じます。Intel、インテル、Intel ロゴ、Intel Core、MMX、Pentium、Xeon、Intel Xeon Phi、Cilk、VTune は、アメリカ合衆国および / またはその他の国における Intel
Corporation の商標です。* その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

llllllllllllllllllllllllllllllllllllllllll

30

The Parallel Universe

3

編集者からのメッセージJames Reinders インテル コーポレーションの並列プログラミング・エバンジェリスト兼ディレクター。
Morgan Kaufmann から出版された 2 冊の新しい書籍、『Intel® Xeon Phi™ Coprocessor High Performance Programming』(2013、
日本語 『: インテル® Xeon Phi™ コプロセッサー ハイパフォーマンス・プログラミング』) および『Structured Parallel Programming』(2012、日本語 『: 構造化並列プログラミング』) の共著者。このほかに、『Intel® Threading Building Blocks: Outfitting C++ for
Multicore Processor Parallelism』(O' Reilly Media、2007、日本語 『: インテル スレッディング・ビルディング・ブロック ―マル
チコア時代の C++ 並列プログラミング』、中国語、韓国語の翻訳版があります ) や『VTune™ Performance Analyzer Essentials』( Intel Press, 2005) などの文献を発表しています。

ハイパフォーマンスが身近なものにハイパフォーマンス・コンピューティング (HPC) は、もはや研究クラスターや高速株取引の世界に限られたものではありません。現在では、ビッグデータの競争優位性やあらゆるリアルタイムのパフォーマンスの可能性を探るべ
く、広範囲な業界およびグローバル企業で HPC に対する需要が高まっています。この号では、開発者とソフトウェ
ア業界の意思決定者にとって役立つ、HPC ソフトウェア・ツールのさまざまな機能とプログラミング・モデルについて取り上げます。
注目記事である「フルスロットル : OpenMP* 4.0」では、科学研究分野を越えて適用可能な、タスクベースのヘテ
ロジニアス・プログラミング・モデルをサポートする、OpenMP* 機能の飛躍的進歩について解説します。
「インテル® Cluster Studio XE 2013 SP1 の新機能」では、この HPC ソフトウェア開発ツール・スイートの新機能の概要を説明します。インテル® Xeon Phi™ コプロセッサーのパフォーマンスを最大限に引き出しながら、分散型メモ
リーおよび MPI プログラミングの機能を InfiniBand* ファブリックの拡張サポートに適用する方法をご覧ください。
「MPI 通信のプロファイリング̶ハイパフォーマンスのためのテクニック」では、MPI アプリケーションのパフォー
マンスを向上する最適化手法として、HPC アプリケーションのボトルネックとインバランスを検出して修正する手法について詳しく説明します。
「インテル® Parallel Studio XE によるビデオ会議ソフトの高速化」では、企業を対象とする生産性ツールの最適化に関するケーススタディーを紹介します。現在シスコファミリーの一員であるタンバーグ社の元社員によって設立された革新的な企業である Pexip 社は、製品の差別化とリアルタイム・データ処理のサポートに、インテル® ソフ
トウェア・ツールを利用してパフォーマンス向上を実現しました。
新しい NASA の探査計画を立てたり、解析アルゴリズムを作成したり、ビデオ会議のようなビジネス生産性ツー
ルを改良したりと、状況は異なっても、パフォーマンスが重要な世界で役立つ手法を読者の皆さんが見つけ出せることを願っています。

James Reinders
2013 年 11 月

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

4

インテル® Cluster Studio XE 2013 SP1の新機能
James Tullos

インテル コーポレーション テクニカル・コンサルティング・エンジニア
インテル® Cluster Studio XE 2013 SP1 は、インテル® Parallel Studio XE 2013 SP1 のすべての機能に加えて、分散メモリー型プログラミングである MPI プログラミングをサポートしています。このツール・スイートには、分散型
メモリープログラムのより高速かつ効率良い実行を支援する、最新のインテル® MPI ライブラリーおよびインテル®
Trace Analyzer & Collector が含まれています。詳細については、http://software.intel.com/en-us/articles/intelparallel-studio-xe-2013-sp1-release-notes (英語 ) (日本語版はこちら ) を参照してください。
インテル® MPI ライブラリーの最新バージョンには、すべての InfiniBand* ファブリックへのサポートが拡張されています。具体的には、DAPL プロバイダーを自動的に選択するプロセスが改善され、OFA のスケーラビリティーが向上し、インテル® Xeon Phi™ コプロセッサーを使用したときの TMI のサポートが追加され、Microsoft* Network
Direct のサポートが追加されました。
インテル® Xeon Phi™ コプロセッサーのネイティブモデルまたはシンメトリック・モデルのいずれかで MPI ジョブを実行する場合、さまざまな状況に備えて最大 3 つの DAPL プロバイダーが用意されています。1 つ目の DAPL プ
ロバイダーは小規模なメッセージ、2 つ目は単一物理ノード内 (同じノード内の異なるインテル® Xeon Phi™ コプロ
セッサー間を含む) の大規模なメッセージ、3 つ目は複数の物理ノードを含む大規模なメッセージにそれぞれ使用されます。I_MPI_DAPL_PROVIDER_LIST を用いて、使用する DAPL プロバイダーのカンマ区切りのリストを定義します。

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

5

また、InfiniBand* の改良に加えて、次にようにピニングおよびジョブ管理機能が強化されました。チェックポイ
ント再開機能を使用する場合は、I_MPI_RESTART=1 を設定して保存したチェックポイントからアプリケーショ
ンを再開できるようにします。従来のシステムと不均等メモリーアクセス (NUMA) システムの両方で、強化された
ピニングのサポートが追加されました。Windows* では、革新的なスケーラブル・プロセス・マネージャーとしてHydra が追加されました。Hydra を使用する場合は、mpiexec の代わりに mpiexec.hydra を使用してアプリ
ケーションを起動してください。インテル® Xeon Phi™ コプロセッサーのオフロードモデルは、Windows* ホストシステムでも利用できるようになりました。
インテル® Trace Analyzer & Collector の最新バージョンは大幅に拡張されました。ズームしても大規模なデータセッ
トを確認できるように、常に全体の実行時間を表示するトレースマップがグラフィカル・ユーザー・インターフェイ
ス (GUI) に追加されました。トレースマップは、指定された時間に MPI 呼び出しを行っているランクの数もビジュア
ルに表現します。タイムライン設定を利用して、どのようにトレースを開き、表示するかをカスタマイズできるようになりました。また、ボタンが含まれる GUI の任意の場所から状況依存ヘルプを直接使用できるようになりました。
インテル® Cluster Studio XE 2013 SP1 およびスイートのコンポーネントに関する詳細は www.intel.com/go/clustertools (英語) を、新機能の詳細は http://software. intel.com/en-us/articles/intel-cluster-studio-xe2013-sp1-release-notes (英語) 日本語版はこちら ) を参照してください。レジストレーション・センターで登録を行い、評価版を入手して、新しい機能がアプリケーションに役立つかどうかをぜひ試してみてください。

BLOG HIGHLIGHTS

一般的なベクトル化のヒント

WENDY DOERNER »インテル® メニー・インテグレーテッド・コア( インテル® MIC) アーキテクチャー向けのコンパイラー手法__declspec(vector(uniform(a),linear(i:1)))

ベクトルループ内のユーザー定義の関数呼び出しを制御する}

ﬂoat foo(ﬂoat *a, int i){return a[i]++;__declspec(vector(linear(a:1)))

ユーザー定義の関数呼び出しを含むループをベクトル化 ﬂoat foo1(ﬂoat *a){
するには、コードを再構成して関数呼び出しをベクトル要 return (*a)++;素関数にします。
}

要素関数内のユニットストライド方式のアクセスを指定する

SIMD 対応の関数でユニットストライド方式のメモリーアク
セスを行うには、次の 2 つの方法があります。

ベクトルループ内のメモリーの一義化を制御する

簡単なループをベクトル化する例について考えてみます。

> linear 整数でインデックスされた
uniform ポインター> linear ポインター

この記事の続きはこちらでご覧になれます。

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

6

フルスロットル : OpenMP* 4.0
Michael Klemm

インテル コーポレーション シニア・アプリケーション・エンジニア

Christian Terboven

アーヘン工科大学 HPC グループ副長

はじめに「マルチコアは広く普及している。」これは、アプリケーション開発者の状況と彼らが直面しているハード
ウェアの変革を正確に表しています。最初のデュアルコア CPU の登場以来、コアの数は増加の一途を辿っています。インテル® Xeon Phi™ コプロセッサーの登場は、我々をメニーコアの世界へと導きました。最大 61 コア、コアごとに 4 スレッドというハードウェアの能力を引き出すには、アプリケーションの並列化に新しい要件が課されます。
アプリケーションでより多くの並列化が必要な理由は、コアの数が増え続けているためだけではありません。
この数年で、SIMD (Single Instruction Multiple Data) レジスターの幅も数倍に増えました。インテル® MMX®
テクノロジーの初期の SIMD (Single Instruction Multiple Data) 命令では 64 ビットのレジスターを使用していましたが、最新のインテル® アドバンスト・ベクトル・エクステンション 512 (インテル® AVX-512) では、512 ビットのレジスターを使用しています。16 の単精度浮動小数点数または 8 つの倍精度浮動小数点数を一度に計算できる能力は驚異的なものです。つまり、アプリケーションでこれらの SIMD 機能を利用しなければ、CPU のパフォーマンスは 16 分の 1 または 8 分の 1 になってしまいます。
インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe7

コア数と SIMD 機能の両方の点でハードウェアの発展に遅れないようについて行くことがアプリケーション開発者にとって重要になります。アプリケーションは、現在および将来の CPU の計算能力を活用できるように、
複数レベルの並列化を行う必要があります。
マルチスレッド化だけではスケーリングし続けられないでしょう。
また、並列化を考慮して記述されたプラグインやライブラリーをアプリケーションで利用する機会も増えています。このため、アプリケーション・コード、サードパーティーのライブラリー、ハードウェアを組み合わせた効率良いソリューションが求められます。
1 つのソリューションとして、独立して実行できる並行タスクへアプリケーションを分割する方法を示す、
タスクベースのプログラミング・モデルがあります。従来のスレッドベースのプログラミングとは対照的に、
アプリケーション・タスクと実行ユニットのマッピングが柔軟になり、コンポーネント間の対話がより簡単になります。各コンポーネントがタスクを作成するとほかのタスクと自動的にミックスされます。インテル®
Cilk™ Plus、インテル® スレッディング・ビルディング・ブロック (インテル® TBB)、C++11 の async 機能のようなプログラミング・モデルは良い例です。

OpenMP* の登場

OpenMP* API は、1997 年の登場以来、共有メモリー並列プログラミングのデファクト・スタンダードとなっています。技術計算や科学的計算に焦点を当てており、C、C++、Fortran をサポートしています。
OpenMP* 対応コンパイラーは、すべての主要プラットフォームに対して提供されています。OpenMP* は、ライセンス料を支払うことなく誰でも仕様の一部またはすべてを実装できる、「オープン」な規格です。
OpenMP* は、OpenMP* 対応コンパイラーにコードをどのように並列化するかを指示する宣言子で構成され、コードのランタイム動作を制御する API と環境変数を定義します。宣言子は、C/C++ ではプラグマとして、Fortran では特別なコメントとして実装されます。このため、プラグマ / コメントを無視してOpenMP* コードをコンパイルすると、シーケンシャル・バージョンを生成することができます。OpenMP*
は、コードの計算を多用する部分に注目して、既存のコードに並列処理を段階的に追加できます。
OpenMP* の重要な部分は、マスタースレッドが複数のワーカースレッドと連結する並列領域です。並列領域の外では、コードはマスタースレッドによりシーケンシャルに実行されます。ワークシェアリング構
文は、複数のスレッドで構成されるチームに対してワークを配分する手段を提供します ( 図 1)。この例

1 const int N = 1000000;
2 double A[N], B[N], C[N];3 // A、B、C を初期化
4 // ...
5
6 #pragma omp parallel for
7 for (int i = 0; i < N; i++) {8
A[i] = B[i] + C[i];9}1インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

for ループのワークシェア
リングを含む単純な並列領域の例

The Parallel Universe

8

では、for ループが同じサイズのチャンクに分けられ、チームのスレッドに割り当てられています。この
静的分散でロード・インバランスが発生する場合は、schedule 節を使用してデフォルトの分散スキーム
を変更します。例えば、schedule(dynamic,c) は、サイズ c のチャンクを作成し、アイドルスレッ
ドは利用可能な次のチャンクを取得します。
() も提供します。共OpenMP* は、スレッドに対するデータの有効範囲を表現するメカニズム 「スコープ」
有メモリー領域に残すデータと個々のスレッドでプライベートにするデータを OpenMP* 対応コンパイラーに伝えることは重要です。OpenMP* は、変数のスコープを制御するために宣言子に追加する節を定義します。shared 節は共有空間で変数を維持し、private 節はスレッドプライベートな変数のコピーを作成します。並列領域の外で宣言された変数はデフォルトで共有スコープとなります。図 1 では、変数 A、
B、C および定数 N が共有スコープとなります。プライベート変数は、例のループカウンター i のように、それぞれのスレッドに異なった値を格納することができます。プライベート・コピーはデフォルトでは初期化されずに作成されます。ﬁrstprivate は並列領域外の変数値を初期値として割り当てるために使用できます。
OpenMP* API 仕様の最新バージョン 4.0 は、既存の機能に対するマイナーな不具合の修正や改良が含まれるだけでなく、Fortran 2003 で追加された機能をサポートしています。OpenMP* アフィニティー
は、ハードウェアの実行ユニットに対してスレッド・アフィニティーを表現する一般的な方法を定義します。
バージョン 4.0 では、大幅な機能拡張も行われています。その一部については、この後でより詳しく説明します。タスクグループは、タスクセットの同期処理を記述するより優れた手段や、並列実行の中断を許可するキャンセルを提供することにより、タスク処理を向上します。ユーザー定義のリダクションはプ
ログラマーが任意のリダクション操作を指定しますが、SIMD プラグマはスレッド並列実行をデータ並列
SIMD 機械語命令に拡張します。OpenMP* の最も重要な拡張機能は、コプロセッサー・デバイスへの計
算のオフロードのサポートでしょう。

OpenMP* とタスク

コア (スレッド) 数の増加に伴い、従来の並列ループ用のワークシェアリング構文でコアを完全に利用することはますます困難になっています。再帰やグラフ走査のような不規則なアルゴリズムの並列化には、全く異なるアプローチが必要です。タスクベースのモデルは、はるかに柔軟な方法でタスクを作成できるため、これらのアルゴリズムの要件に適しているでしょう。
OpenMP* タスクは、実行されるコードの一部と実行に必要なすべてのデータで構成される小さなパッケージとして扱われます。OpenMP* タスクは #pragma omp task 宣言子により作成され、並行実行するコードとデータを定義します。OpenMP* ランタイムシステムは、作成されたタスクを並列領域のスレッ
ドにマッピングします。そして、タスクをタスクキューに追加して遅延実行するか、タスクを直ちに実行します。
図 2 は、単純な総当り数独 * ソルバーのタスク並列バージョンです。アルゴリズムは次のようになります。
1.

数字のない空のフィールドを探す。

2. 数字を挿入する。
3. ボードを確認する。
4. ソリューションが無効である場合、次の可能な数字を試す。
5. ソリューションが有効である場合、次のフィールドに移動して同じ処理を行う。

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

9

1 void main() {2 // データ構造をセットアップ
3 // ...
4 #pragma omp parallel// 並列領域を開始
5{
6 #pragma omp single// 1 つのスレッドに制限
7{
8 #pragma omp taskgroup// すべてのタスクをグループ化
9{10
solve_parallel(0, 0, sudoku);
11
}
12
}
13 }
// omp parallel を終了
14 }15
16 void solve_parallel(int x, int y, CSudokuBoard* sudoku, CSudokuBoard* & solution) {17 if (x == sudoku->getFieldSize()) {// sudoku 行を終了
18
y++;x = 0;
19
if(y == sudoku->getFieldSize())// sudoku フィールドを終了
20
return true;
21 }22
23 if (sudoku->get(y, x) > 0) {// フィールドはすでにセット済み
24
return solve_parallel(x+1, y, sudoku);// 次のフィールドに取り組む
25 }26
27 for (int i = 1; i <= sudoku->getFieldSize(); i++) {// すべての可能な数字を試す
28
if (!sudoku->check(x, y, i)) {29 #pragma omp task ﬁrstprivate(i,x,y,sudoku)// 新しいソルバータスクを作成
30{
31
CSudokuBoard* new_sudoku = new CSudokuBoard(*sudoku);
32
new_sudoku->set(y, x, i);// 数字が有効な場合はセット
33
if (solve_parallel(x+1, y, new_sudoku)) {// 次のフィールドに取り組む
34 #pragma omp critical// sudoku ソリューションを保護
35
if (!solution) {// 新しいソリューションの場合は保存
36solution = new_sudoku;
37 #pragma omp cancel taskgroup// キャンセルをリクエスト
38
}
39
}
40
delete new_sudoku;// クリーンアップ
41
}
42
}
43 }
44 #pragma omp taskwait// 子タスクの完了を待つ
45
46
sudoku->set(y, x, 0);// ソリューションなし、
フィールドをリセット
47 }OpenMP* タスクとキャンセルを使用した数独 * ソルバーの例

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

2

The Parallel Universe

10

タスクを実行するには、最初に並列領域でスレッドのチームを作成します。この例では、1 つのスレッド
が sudoku アルゴリズムを開始し、アルゴリズムがタスクの生成を開始します。アルゴリズムは、上記のステップ 4 でタスクを生成します。そして、あるフィールドの複数の数字に対して並列処理 (各タスクで異なる数字を試し、ソリューションが有効かどうかを確認) を行い、sudoku ボードを解きます。
この例により、C++ クラスと OpenMP* がいかに簡単に組み合わせられるかが分かるでしょう。変数
sudoku は CSudokuBoard クラスのインスタンスへのポインターで、ﬁrstprivate は各タスクがそのポインターのプライベート・コピーを受け取ったことを示します。その後、タスクはコピー・コンストラクターを起動してインスタンスのコピーを作成します。
チーム内のすべてのスレッドは、タスクキューにあるタスクの実行を行います。スレッドがバリアまたはほかの同期構文に直面すると、タスクの有無を確認し実行します。OpenMP* では、供給不足のスレッドが供給過多のスレッドからタスクをスチールすることが明示的に許可されています。
OpenMP* には、タスクの実行を同期する複数の同期構文が用意されています。バリアは、スレッドチー
ムがそのバリアを通過する際に、バリアに到達する前に作成されたタスクはすべて実行が完了していることを保証します。taskwait 構文は、親タスクで作成されたすべての子タスクの完了を待機します。
taskgroup 構文は、構文内で作成されたすべてのタスクを論理的にグループ化し、構文の最後でグ
ループのすべてのタスクに対して暗黙の taskwait を確立します。

処理の中止

実行を妨げる予期しない状況 (失敗やエラーなど) により並列処理を中止したいこともあるでしょう。あるいは、途中の計算結果から、実行を継続しても意味がないケースも考えられます ( 例えば、数値アルゴリズムや検索アルゴリズムなど )。OpenMP* 3.1 では、並列実行を開始した後の実行中止がサポートされていなかったため、プログラマーは OpenMP* でこれらのアルゴリズムを容易に実装できませんでした。ただし、一部の OpenMP* 構文には、回避方法がありました。例えば、for ワークシェアリング構
文を中止するには、if 文で for ループをそれ以上処理をせずに最後まで回る空のループにする方法がありました。ただし、この方法では、ループが終了まで実行されるため、時間とコストが浪費されます。
OpenMP* 4.0 では、明確に並列実行を中止する cancel 宣言子を追加することにより、この問題を解決しました。cancel 宣言子により現在の OpenMP* 領域の停止をリクエストすることができます。リクエ
ストしたスレッドは直ちに実行を中止して、終了のリクエストがあったことを残りのスレッドに通知します。
残りのスレッドは、通知を受け取ると、「キャンセルポイント」で実行を中止します。
cancel 宣言子は、parallel 領域、ワークシェアリング構文、タスクグループの終了をサポートしています。キャンセルポイントは、バリアおよび cancel 言子で自動的に挿入されます。プログラマーは、
cancellation point 宣言子を使用してコードにキャンセルポイントを追加することができます。キャンセルが発生したとき、OpenMP* ランタイムは割り当てられたメモリー、ロック、オープンしたファイルなどの取得したリソースを解放しません。キャンセルがリクエストされる前、またはスレッドがキャンセル
ポイントに達する前に、これらを解放することはプログラマーの責任です。

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

11

図 2 の例では、キャンセルによりボードのソリューションの検索を停止しています。ソルバータスクの 1
つが新しいソリューションを見つけると、ほかのタスクが別のソリューションをすでに見つけていないかどうかをまず確認します。最初に見つかったソリューションであれば、タスクはソリューションを保存してキャンセルをリクエストします。ソリューションの潜在的な競合状態を回避するため、また 2 つのタスクが同時にキャンセルをリクエストすることを避けるため、critical 領域を使用しています。
この例は、タスクキャンセルの動作に依存しています。実行を開始したすべてのタスクは、キャンセルポ
イントが含まれない限り、完了するまで実行され、中止されません。待機キューに送られたほかのすべてのタスクは破棄され、完了したと見なされます。各タスクがすでに見つかっているソリューションを常に確認するのはこのためです。タスクが実行を開始するかどうか事前に知ることはできません。このため、あるタスクがソリューションを見つけてキャンセルをリクエストした直後にタスクが実行された場合、重複するソリューションを格納しないようにする安全策が必要です。

SIMD 命令

OpenMP* 3.0 以前のバージョンは、主にマルチスレッド化に注目し、データ並列 SIMD 命令のようなほかの機能には対応していませんでした。プログラマーが最近のプロセッサーの SIMD 機能を利用するには、
コンパイラーの自動ベクトライザーにより適切な SIMD 命令が挿入されることを期待して任せる必要がありました。あるいは、移植が困難で、OpenMP* の並列化宣言子と組み合わせた際に問題が発生しやすい、
ベンダー固有の拡張機能を使用しなければなりませんでした。
OpenMP* 4.0 では、この状況を改善するため、移植性のある SIMD 命令の記述および並列化宣言子との組み合わせが可能な新しい構文が定義されました。このためのメイン・ビルディング・ブロックは、ルー
プをベクトル化する simd 構文 (図 3) であり、シリアルコードに適切な SIMD 命令を導入するようにコンパイラーに指示します。for simd および parallel for simd 構文は、このベクトル化とループレベルのスレッド並列化を組み合わせるもので、両方のパラダイムを同時に効率良く結合します。

1
2
3
4

#pragma omp declare simd aligned(a,b) notinbranch
ﬂoat min(ﬂoat a, ﬂoat b) {return a < b ? a : b;
}

5
6
7
8

#pragma omp declare simd aligned(x) uniform(y) notinbranch
ﬂoat distance(ﬂoat x, ﬂoat y) {return (x - y) * (x - y);}

9 void distance_update(ﬂoat *a, ﬂoat *b, ﬂoat *y, int vlen) {10 ﬂoat *ptr = b;
11 #pragma omp parallel for simd safelen(16) linear(ptr:1) aligned(a,b,y)
12 for (int i=0; i<vlen; i++) {13
y[i] = min(sqrt(distance(a[i], 1.0)), ptr);14
ptr += 1;
15 }
16 }

OpenMP* SIMD 宣言子を使用した関数とループのベクトル化

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

3The Parallel Universe

12

この新しい構文は、既存の OpenMP* ワークシェアリング構文と非常に似たシンタックスで、これまでの節 (private、reduction、collapse、その他) をサポートします。さらに、効率良い SIMD コー
ドを生成するようにコンパイラーを支援する新しい節もあります。safelen 節は、(例えば、特定のストライドでループ間の依存性が存在するときに) ループで使用可能な最大ベクトル長を定義します。同様に重要なものとして、ループカウンターに対する変数のリニア依存性を表現する linear
があります。
aligned 節は、コンパイラーが最適なロードおよびストア命令を選択できるように、デー
タのアライメントを指定します。
コードをベクトル化する際に課題となるのは、図 3 に示すように、ループ本体が関数呼び出しを含む場合です。関数 min および distance の SIMD バージョンがない場合、コンパイラーは SIMD 命令を生成できません。標準ライブラリーの多くのルーチンについては、最近のコンパイラーはすでにベクトル化されたバージョン (例えば、sqrt、sin、cos) を提供しています。ほかのすべての関数については、
プログラマーが支援する必要があります。図 3 の declare simd 構文は、スカラー引数をベクトルに昇格してベクトルバージョンのコードを追加生成するようにコンパイラーに指示します。必要に応じて、
uniform 節を用いて特定の引数の SIMD 昇格を回避できます。notinbranch 節は、関数が条件分岐( 例えば、if 文の本体) 内から呼び出されないことを保証して、さらなるコンパイラーの最適化を可能にします。inbranch 節は、この逆です。

レデューサー

スレッドのチームが協力して問題に取り組み、グローバルな単一の結果を生成しなければならない場合
は、リダクション操作が必要となります。各スレッドは、ローカルな中間結果を保存するため変数のプラ
イベート・コピーを取得します。並列実行が終了する直前に、OpenMP* ランタイムシステムは全スレッド
からすべての中間結果を収集して、グローバル結果にレデュース (集約 ) します。OpenMP* 4.0 より前のバージョンでは、基本言語のプリミティブ型 (int や ﬂoat など) における加算や最小値 / 最大値のように、事前定義されたリダクション操作のみがサポートされていたため、派生データ型やより複雑な操作を使う場合、プログラマーが独自のリダクション・コードを記述しなければなりませんでした。その結果、プログラマーは複雑なコードパターンを維持する必要がありました。
OpenMP* 4.0 では、ユーザー定義のリダクションがサポートされています。プログラマーは、任意の複雑なデータ型で任意のリダクション操作を定義できます。図 4 は、新しい機能を使用して 2D の雲の表
示領域 ( バウンディング・ボックス) を計算する並列アルゴリズムを実装しています。表示領域は、すべてのポイントを含む小さな長方形で、雲の左端と右端、および下端と上端を決定して 2D で計算されます。
これらの位置から、長方形の左下隅と右上隅が判明します。

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

13

1 #include <algorithm>
2
3 #pragma omp declare reduction(minp :Point2D :\4
omp_out.setX(std::min(omp_in.getX(), omp_out.getX())),
5
omp_out.setY(std::min(omp_in.getY(), omp_out.getY())) )6
initializer(omp_priv = Point2D(MAX_X, MAX_Y))
7 #pragma omp declare reduction(maxp :Point2D :\8
omp_out.setX(std::max(omp_in.getX(), omp_out.getX())),
9
omp_out.setY(std::max(omp_in.getY(), omp_out.getY())) )10
initializer(omp_priv = Point2D(MIN_X, MIN_Y))
11
12 Rectangle bounding_box(std::vector<Point2D> points) {13
Point2D lb(MAX_X, MAX_Y);
14
Point2D ub(MIN_X, MIN_Y);
15
std::vector<Point2D>::iterator it;
16 #pragma omp parallel for reduction(minp:lb) reduction(maxp:ub)17
for (it = points.begin(); it != points.end(); it++) {18
Point2D &p = *it;19
lb.setX(std::min(lb.getX(), p.getX()));
20
lb.setY(std::min(lb.getY(), p.getY()));
21
ub.setX(std::max(ub.getX(), p.getX()));
22
ub.setY(std::max(ub.getY(), p.getY()));
23}
24
return Rectangle(lb, ub);
25 }4

2D の雲の表示領域を計算するユーザー定義リダクション

図 4 には、2D ポイントの x 軸と y 軸を格納する単純なクラス Point2D と、2 つの 2D ポイントから構成される長方形を格納するクラス Rectangle が含まれます。declare reduction 宣言子は、新しいユーザー定義のリダクション操作を宣言します。コロンで区切られた部分は、リダクション操作の名前 (minp および maxp) とリダクション操作が有効なデータ型 (Point2D) を定義します。最後の部
分には、2 つのローカルな結果を新しい中間結果に組み合わせる方法を記述した C/C++ の式またはFortran の文が含まれます。この式 / 文は、すべての中間結果がグローバルな結果に組み合わされるまで繰り返し適用されます。initializer 節は、リダクション変数のスレッドプライベートなコピーの初期化方法を示します。
for ループは、雲のすべてのポイントを格納する std::vector の全要素を繰り返します。各ポイント
で、実行する最小 / 最大の x および y 座標を計算して最小表示領域の隅を見つけます。コードを並列化するため、parallel for 構文を用いてスレッドのチームにループを分散しています。このため、各スレッドは、自身に割り当てられたポイントのみを含むローカルな表示領域だけを計算します。ここで必要となる点は、
ローカルなすべての表示領域をどのように組み合わせてグローバルな表示領域にするかです。
parallel for 構文の reduction 節は、新しいリダクション操作 minp および maxp を適用することにより、この操作を実行します。集約式の omp_in および omp_out 変数は、リダクション式が適用されたときの左および右オペランドを指します。例では、これらのオペランドを最小 / 最大値操作に渡して、表示領域を拡大しています。

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

14

ハイスピードインテル® Xeon Phi™ コプロセッサーのような接続デバイスへの計算のオフロードサポートは、OpenMP*
4.0 の最も革新的な機能と言えるでしょう。OpenMP* 4.0 では、計算のオフロードをサポートするため、従来の共有メモリーによるスレッド化モデルを拡張した新しいデバイスモデルが採用されました。オフロード機能が OpenMP* 仕様に追加されたことにより、あらゆる点で OpenACC* の代わりとなる、業界全体にわたる優れたソリューションが提供されます。オフロードデバイスが制限される OpenACC* とは異なり、OpenMP* は多様なデバイスで利用することができます。使用するデバイスはすべて同じアーキ
テクチャーでなければなりませんが、OpenACC* とは違い、サポートされるデバイスの数に制限はありません。OpenMP* は、ホストとデバイス間の制御や、データ転送を行うための新しい構文と宣言子を定義します。
target 構文 (図 5 を参照) は、ホストスレッドからコプロセッサー・デバイスに制御を移し、ターゲッ
トデバイス上でコードを実行するために必要なすべてのデータを含むデバイスデータ環境を作成します。
target 構文の map 節は、データ環境におけるデータの割り当てとデータ転送の向きを制御します。図6 は、map でサポートされているさまざまな転送タイプです。例では、map(to:x[:N]) を使用して配列 xをホストからターゲットデバイスへ転送しています。構文 x[:N] は x[0:N] の短縮表記で、インデックス 0から始まる N 個の配列要素、つまり x のすべての配列要素を表します。

1 int n = 10240; ﬂoat a = 2.0f; ﬂoat b = 3.0f;
2 ﬂoat *x = (ﬂoat*) malloc(n * sizeof(ﬂoat));// init x
3 ﬂoat *y = (ﬂoat*) malloc(n * sizeof(ﬂoat));// init y4
5 #pragma omp target data map(to:x[:N])6 {7
int num_blcks = 61;
8
int num_thrds = 4;
9 #pragma omp target map(tofrom:y[:N])
10 #pragma omp teams num_teams(num_blcks) num_threads(num_thrds)
11 #pragma omp distribute12
for (int b = 0; b < n; b += num_blcks) {13 #pragma omp parallel for14for (int i = b; i < b + num_blcks; ++i){15y[i] = a*x[i] + y[i];
16
}
17
}
18
19 // y を使用した処理を実行
20 // ...
21
22 #pragma omp target map(tofrom:y[:N])
23 #pragma omp teams distribute parallel for \24
num_teams(num_blcks) num_threads(num_thrds)
25
for (int i = 0; i < n; ++i){26
y[i] = b*x[i] + y[i];27}28
29 free(x); free(y);ホストからコプロセッサー・デバイスへの計算のオフロード

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

5The Parallel Universe

6

15

各種 map 節の転送

コプロセッサーは PCI Express* バスを介してホストシステムと通信を行うため、不要なデータ転送を避けることが重要です。target data 構文はデバイスデータ環境を確立しますが、制御フローは転送しません。この構文を使用することで、プログラマーはデータをターゲットデバイスに転送して保持させながら、複数の target 構文を使用して制御フローの転送を行えます。データがデバイス上にす
でに存在することを target 構文が検出すると、データ転送は回避されます。ホストまたはデバイスのいずれかのデータが古い場合、target update 宣言子によりデータ交換を行えます。
では、図 5 の例を細分化して、それぞれの構文の動作を説明しましょう。この例は、よく知られている
SAXPY 演算 y = a*x + y を行っています。コードは演算を 2 回実行するため、それぞれの実行に対して x を安全に転送できるように、デバイスデータ環境を作成します。例の target 構文は、x がコプロ
セッサー上ですでに利用可能であることが分かっているため、y のデータ転送のみを行います。例の 2 つ目の target 構文も同様です。
これまでに説明した構文は、ホストとデバイス間の制御またはデータの転送のみを行います。これらの構文は転送されるコードを自動的に並列化しません。プログラマーは、OpenMP* の標準機能を利用してター
ゲットデバイス上で並列化を行う必要があります。この例では、単純な parallel for 構文を使用して
SAXPY ループを並列実行するスレッドのチームを作成しています。しかし、244 スレッドを備えたコプロセッ
サーのチーム作成と同期のオーバーヘッドは相当なものになるため、このソリューションは効率的ではありません。
ソリューションを効率良くするには、物理プロセッサー・コアごとに搭載される 4 つのハイパースレッドの階層アーキテクチャーを有効利用する必要があります。OpenMP* 4.0 では、これらの階層をプログラ
ムコードにマップする新しい構文を提供しています。

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

16> teams 構文は独立したスレッドチームを複数作成し、そのマスタースレッドがコードを実行します。

> distribute 構文は、複数のマスタースレッド間にループを分散する新しいワークシェアリング構文です。
distribute 構文の最後に暗黙的なバリアーはありません。
> 通常どおり、既存の parallel for 構造でスレッドチームにループを分散します。

SAXPY コードは、コプロセッサーの 61 の物理コアについてそれぞれ 1 つのスレッドチームを作成します。
最初のレベルの並列化として、作成したスレッドチーム間で b の外部ループを分散します。2 つ目のレベルの並列化は parallel for で構成され、物理コアの各ハイパースレッドについてそれぞれ 4 つのスレッドを作成します。SAXPY の 2 回目の起動は、コードを短くするため teams distribute parallel for
構文が組み合わされた糖衣構文として示されています。
ホストからデバイスへの制御の移行はブロッキング操作で、ホストスレッドはターゲット上の制御フローが終了してすべてのデータが転送されるまで待機します。ホストとデバイスの両方で並行タスクを実行する必要がある場合、プログラマーは既存の OpenMP* 機能を利用できます。例えば、target または target
update 構文を OpenMP* タスク内に配置し、これらの構文を別の OpenMP* スレッドで実行できます。

まとめ

バージョン 4.0 で、OpenMP* は飛躍的な進歩を遂げました。新しく追加された機能は、ヘテロジニアス
・プログラミングの新しい扉を開くでしょう。OpenMP* 4.0 は、技術計算や科学的計算に限らずより広い
範囲の並列プログラミング・モデルとなる新しい機能を提供します。インテルは、並列プログラミング・
モデルである OpenMP* への取り組みをこれからも続けていきます。インテル® Composer XE 2013 は以前の OpenMP* API 仕様 3.1 をフルサポートしており、将来のバージョンでは、OpenMP* 4.0 のハイパ
フォーマンスな機能を実装する予定です。インテル® Composer XE 2013 SP1 では、C、C++、Fortranにおいて、OpenMP* target 構文、SIMD 宣言子、OpenMP* アフィニティー機能など、OpenMP* 4.0 の新機能のサブセットをサポートしました。インテル® Composer XE の将来のバージョンでは、ユーザー
定義リダクション、タスク依存性、キャンセルがサポートされる予定です。OpenMP* バージョン 4.1 そして 5.0 への取り組みは、OpenMP* Architecture Review Board (ARB) によりすでに開始されており、インテルはこれらの新しい OpenMP* の開発に協力しています。

最先端のツールで確認
評価版のダウンロード
最新のインテル® Parallel Studio XE およびインテル® Cluster Studio XE (英語) >組込みおよびモバイルシステム開発者向けインテル® System Studio (英語) >インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

17

MPI 通信のプロファイリング̶
ハイパフォーマンスのためのテクニック
James Tullos

インテル コーポレーション テクニカル・コンサルティング・エンジニア

はじめに

メッセージ・パッシング・インターフェイス (MPI) は、アプリケーションの複数のインスタンス (ランク) 間でデータを渡すための API を提供します。MPI は高レベルの並列化を可能にしますが、優れたパフォーマンスが自動的に得られる訳ではありません。この記事では、次の 2 つの最適化に注目して、MPI アプリケーションのパフォーマンスを向上させる手法を紹介します。
> ボトルネック : 実行を遅らせるプログラム部分> ロード・インバランス : 一部の実行ユニットを待機させる、不均等なワークロード分散
ここでは、インテル® Cluster Studio XE に含まれるパフォーマンス解析ツール、インテル® Trace Analyzer &Collector (ITAC) の使用例を説明します。ITAC を用いて MPI アプリケーションをプロファイルおよび解析すること
により、パフォーマンスが向上する可能性のある場所を特定できます。

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

18

ITAC によるパフォーマンス・データの収集

ITAC は、インテル® Trace Collector (ITC) とインテル® Trace Analyzer (ITA) の 2 つのコンポーネントから構成されます。ITC はアプリケーションのデータを収集するライブラリーで、収集したデータは ITA で解析します。ITC の出
力 (トレース) には、ルーチンの入口と出口データ、MPI パラメーターのレコード、MPI の通信と待機時間が含まれます。
MPI アプリケーションで ITC を使用する最も簡単な方法は、実行時にライブラリーをロードすることです。インテル®
MPI ライブラリーを使用する場合、mpirun 引数に –trace を追加するだけです。アプリケーションを実行すると、ITCがトレースを生成し、ITA で生成したトレースを解析できます。

MPI におけるボトルネック

通信ボトルネックは、アプリケーションが通信ルーチンで待機するアイドル時間の原因となるため、全体的なパフォーマンスが低下します。ITAC は、アプリケーションが MPI 呼び出しの完了を待っている状態を示し、ボトルネックを特定できるように支援します。
ここでは、隣接するランク間でデータを交換する MPI_Sendrecv とランク間のデータを合計する MPI_Allreduceを実装したポアソンソルバーの例を使用しています。これらの通信はすべての反復で発生します。このサンプルコー
ドは ITC に付属しています。
トレースを収集する前に、いくつかの環境変数を設定する必要があります。次のコマンドでスクリプトを実行します。
source /opt/intel/impi/4.1.1.036/intel64/bin/mpivars.shsource /opt/intel/itac/8.1.3.037/intel64/bin/itacvars.sh
デフォルトでは、ITC はスケーラビリティーを高めるため収集したデータを複数の構造トレースファイル (stf) に分配します。実行規模が小さければ、データを単一のトレースファイルにまとめることもできます。
export VT_LOGFILE_FORMAT=singlestf
トレースを収集する準備ができたら、次のコマンドを実行します。
mpirun –f myhostﬁle –n 16 –ppn 4 –trace ./poisson.sendrecv
このコマンドは、ソルバーを 4 ノード (ノードごとに 4 ランク) 実行して、アプリケーションで行われたすべての MPI
呼び出しが含まれるトレースファイルを生成します。生成されたトレースファイルを ITA で開き、解析を開始します。
traceanalyzer ./poisson.sendrecv.single.stf

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

19

問題の兆候の調査
最初のビューにトレースマップと関数プロファイル・グラフが表示されます。[Flat Profile (フラット・プロファイル)]タブに移動すると、最初に 2 つのグループ、Group Application と Group MPI が表示されます。ここでは、MPI パ
フォーマンスの最適化に取り組むため、Group MPI を使用します。Group MPI 行を右クリックして Ungroup MPI を選択すると、グループ化されていた MPI 呼び出しが個々の MPI 呼び出しに分かれて表示されます。各 MPI 関数は
デフォルト色で表示されますが、この例では見やすいように色を変更しています。

1

フラット・プロファイル

フラット・プロファイルを見ると、2 つの MPI 関数、MPI_Sendrecv と MPI_Allreduce の実行に時間が費やされていることが分かるでしょう。これらの関数の実行には、ほぼ同じ時間がかかっています。[Load Balance (ロードバランス)] タブをクリックして詳細情報を確認すると、MPI_Sendrecv ではより高い番号のランクでより多くの時間が費やされ (図 2)、MPI_Allreduce ではより低い番号のランクでより多くの時間が費やされている (図 3) ことが分かります。通信はすべてのランクで均一になるべきであるため、これは潜在的なパフォーマンス問題を示しています。

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

20

2

MPI_Sendrecv のロードバランス

3

MPI_Allreduce のロードバランス

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

21

根本的な原因の特定
問 題 が 存 在して い ることが 判 明したら、 次 に 原 因 を 特 定しま す。[Charts (グラフ)] -> [Event Timeline(イベント・タイムライン)] メニューを選択して、イベント・タイムライン・グラフを開きます。このグラフは、アプリケー

ションの実行時間上における、各ランクの動作状況を示します。ここでも、デフォルトビューでは必要な情報が分かりづらいため、イベント・タイムラインをズーム (クリックしてドラッグ ) し、必要な情報を表示します。ズームすると、トレースマップを除くすべてのグラフは選択した時間範囲の情報のみを表示することに注意してください。トレー
スマップには常に全体の時間が表示されます (選択した範囲はハイライトされます)。

4

イベント・タイムライン

MPI_Sendrecv はブロッキング呼び出しであるため、交換が完了するまでリターンできません。ランク 1 と 2 を開始する前にランク 0 と 1 は交換を完了しなければならないため、ランク 2 は待機します。この影響はランクが高くなるにつれて大きくなり、MPI_Sendrecv でインバランスが発生します。この遅延により、先のランクは MPI_
Allreduce に早めに到達できるが、後のランクが完了するまでブロックされ、MPI_Allreduce でインバランスが引き起こされます。

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

22

ボトルネックの排除
このボトルネックは、改善するべきターゲットであると考えられます。ブロッキング通信をノンブロッキング通信に変更してみましょう。MPI_Sendrecv の呼び出しを MPI_Isend と MPI_Recv の呼び出しに変更して、前の通信にブロックされることなく、各ランクが隣接するランクにデータを送信できるようにします。変更したアプリケーションを実行して、ITA に新しいトレースをロードし、フラット・プロファイルを開きます。下の画面から分かるように、変更後のコードでは通信に費やされる時間が少なくなりました。

5

フラット・プロファイル、ノンブロッキング通信

最も時間が費やされている通信の Load Balance (ロードバランス) プロファイルを見ると、これらの関数のバランスがより適切になったことが分かります。

6

ロードバランス、ノンブロッキング通信

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

23

イベント・タイムラインの内容からパフォーマンス改善の様子が良く伺えます。シリアル通信がなくなり、通信が並列化されました。

7

イベント・タイムライン、ノンブロッキング通信[ View (ビュー)] -> [Compare (比較)] をクリックして新しいトレースとオリジナルのトレースを比較してください。
ナビゲーション・キーやマウスのズームを使用して、2 つのトレース間の時間スケールを合わせます。ソルバーが改良され、通信で待機するのではなく、実際の計算 (青の領域) に費やす時間の割合が多くなったことが一目で分かります。

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

824

トレースの比較

ロード・インバランスの特定

ロードバランスはアプリケーションでワークを分散する手法です。次は、ヘテロジニアス MPI ランク間のロード分散について見てみます。
次の例は、Sandia Labs の miniFE ベンチマークを使用しています。このベンチマークは、有限要素法ソルバーの 操 作 を シミュレ ートす る も の で、http://www.nersc.gov/systems/trinity-nersc-8-rfp/nersc-8-trinitybenchmarks/minife/ から入手できます。miniFE は、ストロング・スケーリングを利用してランク間でロードを分割します。この例では、インテル® Xeon Phi™ コプロセッサーを使用した、ヘテロジニアス・ノード間のロードバラ
ンスを示します。ジョブは、4 つのホストノード (各 16 MPI ランク)、4 つのコプロセッサー・ノード (さまざまなランク数)、256x512x512 の行列サイズを用います。
この例では、結果をランクではなくノードでグループ化しています。ノードでグループ化するには、ツールバーの[Process Aggregation (プロセス集約)] ボタンをクリックして、[Process Aggregation (プロセス集約)] ダイアログで[All_Nodes (すべてのノード)] を選択し、OK をクリックします。(下図参照)

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

25[Process Aggregation (プロセス集約)] ダイアログ

関数プロファイルのインバランス
最初の実行で、miniFE はホストごとに 16 ランク、コプロセッサーごとに 32 ランクの初期分散を行いました。
トレースを ITA で開き、Load Balance (ロードバランス) プロファイルを選択します。MPI 通信のバランスは取れていますが、ワークロードがコプロセッサー・ランクで高くなっていることが分かります。

ITAC は、インテル® Trace Collector (ITC) およびインテル®
Trace Analyzer (ITA) の 2 つのコンポーネントから構成されます。ITC はアプリケーションのデータを収集するライブラリーで、収集したデータは ITA で解析します。ITCの出力 (トレース) には、ルーチンの入口と出口データ、
MPI パラメーターのレコード、MPI の通信と待機時間が含まれます。

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

26

9

ロード・バランス・プロファイル、16 ホスト、ノードごとに 32 コプロセッサー・ランク

10

イベント・タイムライン、16 ホスト、ノードごとに 32 コプロセッサー・ランク

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

27

イベント・タイムラインもインバランスを示しています。各コプロセッサー・ノードは、対応するホストノードよりもアプリケーション・コードでより多くの時間を費やしています。
コプロセッサーごとのランク数を調整するだけでは、すべての MPI ランク間のバランスを完全に取ることはできません。スレッド数やランク分散のようなロードバランスに影響を与えるほかの要因も調整する必要があります。ただし、これはヘテロジニアス・システムであるため、コプロセッサーのランク数を調整することで、ある程度のパ
フォーマンス向上が期待できるでしょう。16 ホストランクおよび 18 コプロセッサー・ランクに変更した新しい分
散ではバランスが大幅に改善され、アプリケーションのパフォーマンスも向上しました。

11

ロード・バランス・プロファイル、16 ホスト、ノードごとに 18 コプロセッサー・ランク

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

1228

イベント・タイムライン、16 ホスト、ノードごとに 18 コプロセッサー

大規模なアプリケーションへの適用

これまで、インテル® Trace Analyzer & Collector を使用して単純なアプリケーションで 2 つの一般的な問題を特定する方法を説明しました。大規模なアプリケーションの場合は、問題があまり明白ではないでしょう。ただし、その場合でも、この記事で説明した方法を適用することができます。

トレースファイルのサイズ

アプリケーションが大きくなると、トレースファイルのサイズも比例して大きくなります。この潜在的な問題を緩和するため、ITC ではトレースファイルのサイズを管理するさまざまな手法が用意されています。必要なランクのみトレースしたり、特定の関数の結果に絞り込んだり、API を利用してトレース収集を直接制御することが可能です。
ITC のフィルタリングに関する詳細は、http://software.intel.com/en-us/articles/intel-trace-collector-filtering(英語) を参照してください。

まとめ
この記事では、MPI アプリケーションのボトルネックとインバランスを特定する方法について説明しました。次は、これらの方法を使って、皆さんの MPI アプリケーションのパフォーマンスを向上させる番です。インテル® Trace
Analyzer & Collector に関する詳細は、http://www.intel.com/go/itac (英語) を参照してください。

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

29

システム構成この記事の例はどちらも以下のクラスターを使用して実行されました。
ヘッドノード :インテル® サーバーボード S5520UR
インテル® Xeon® プロセッサー X5670
4GB メモリー
500GB HDD
計算ノード 0-3:
インテル® ワークステーション・ボード W2600CR2
ベータ SNB-EP (Sandy Bridge) プロセッサー (3.1GHz)
32GB メモリー
1TB HDD
インテル® Xeon Phi™ コプロセッサー 5120A (B1/C0 ステッピング )計算ノード 4:インテル® サーバーボード S2600GZ
インテル® Xeon® プロセッサー E5-2680
32GB メモリー
128GB SSD
インテル® Xeon Phi™ コプロセッサー 5120A (B1 ステッピング )CentOS* 6.3
Warewulf* 3.4 ベータ分散型システム
Mellanox Technologies MT25418
インテル® Composer XE Linux* 版 2013 Update 5
インテル® MPI ライブラリー Linux* 版 4.1 Update 1
インテル® Trace Analyzer & Collector Linux* 版 8.1 Update 1 (収集)インテル® Trace Analyzer & Collector Windows* 版 8.1 Update 3 ( 解析 )インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

30

インテル® Parallel Studio XE によるビデオ会議ソフトの高速化
Stephen Blair-Chappell

インテル コーポレーション テクニカル・コンサルティング・エンジニア

過去 18 か月間にわたり、Pexip 社のソフトウェア・エンジニアはインテル® Parallel Studio XE を利用して、ビデオ
会議ソフトウェア Pexip Infinity* の最適化に取り組んできました。この記事は、Pexip 社の主任最適化エンジニア、Lars Petter Endresen 氏へのインタビューを抜粋したものです。
世界中に多くのチームが分散している組織では、ビデオ会議を利用することで出張経費を抑え、生産性を損うことなくチームが一同に会して話し合うことができます。どのようなビデオコンテンツでも、適切な解像度で、大幅な遅延なく表示されることが快適なユーザー体験にとって重要です。データの質およびビデオ会議のリアルタイム
性はどちらも、ホストシステムに高い処理能力が求められることを意味します。
これまで、ビデオ会議サーバーを設計する場合、デジタル・シグナル・プロセッサー (DSP) ベースのシステムが当然のように選択されていました。このソリューションのマイナス面は、DSP ベースのシステムが非常に高価なことで、サーバー構成によっては数千万円になることもあります。

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

31

この記事では、現在シスコファミリーの一員であるタンバーグ社の元社員によって設立された革新的な企業である Pexip 社が、どのようにして DSP ベースのシステムから既製のインテル・ベースのサーバーで実行可能なソフト
ウェア・ソリューションへ移行することに成功したかを紹介します。Pexip 社は、処理能力の高いインテル® Core™
アーキテクチャー・ベースのシステムとインテル® Parallel Studio XE を使用することで、従来の会議システ
ムのパフォーマンスを超えることに成功しました。図 1 は、Pexip 社の代表製品 Pexip Infinity* を介してラップトップからビデオ会議セッションを行っている様子です。

1

Pexip Infinity* のビデオ会議セッション
出典 : pexip.com

解析と最適化Pexip 社の開発サイクルは、解析とインクリメンタル開発の繰り返しから成ります。
> インテル® VTune™ Amplifier XE を使用して hotspot を特定する。
> hotspot のコードを調べてアルゴリズムが向上する方法を探す。
> インテル® コンパイラーでコードをビルドする。
> 最適化バージョンとオリジナルバージョンを比較する。

開発作業はすべて、第 2 世代インテル® Core™ マイクロプロセッサー (開発コード名 : Sandy Bridge) を搭載した PC上で行われていました。
この作業に加えて、Pexip 社は、最もパフォーマンスが求められるコードの一部を抽出し、インテル® Architecture
Code Analyzer を利用して、第 3 世代 / 第 4 世代インテル® Core™ マイクロプロセッサー上でコードがどのように動作するかを解析しました ( 図 8)。

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

32

インテル® VTune™ Amplifier XE によるプロファイル

まず、インテル® VTune™ Amplifier を使用して高度な hotspot 解析を行い、その後、各 hotspot について最適化の可能性を探りました。
図 2 は、Pexip Infinity* の解析結果です。1 列目は、最上位から順に hotspot をリストしています。2 列目は各
hotspot のクロック数の比率、3 列目はリタイアした命令の比率です。リタイアした命令とは、CPU パイプラインでの処理が完了した命令のことです。

2

インテル® VTune™ Amplifier の高度な hotspot 解析

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

33

主な hotspot

解析で示された上位 5 つの hotspot は次のとおりです (図 3)。
hotspot

時間の比率

EncodeSlice

16.1

MotionSearch

9.9

FastDct

9.3

LoopFilter

8.3

Frame

7.5

3

上位 5 つの hotspot

hotspot はすべて、H.264 Advanced Video Coding (AVC) ビデオ圧縮規格を実装しているコードに含まれていました。
イメージは、処理するデータ量を減らすため、小さなマクロブロックに分割されます。そして、さまざまな圧縮および予測アルゴリズムが一連のマクロブロックに適用され、マクロブロック間の差分データとして処理されます。
圧縮されたイメージストリームを後で伸張するとき、再構築されたイメージにマクロブロックのアウトラインが表示される傾向があります。この欠点を克服するため、H.264 規格には、デブロッキングとして知られる、プロセスのブロックノイズを除去するループフィルターが含まれています。このフィルターは、hotspot 関数 LoopFilter で実装されています。
この特定のテストケースでは、hotspot は実行時間の 8% を費やしていたに過ぎませんが、デブロッキングはイメージデコードで最も時間のかかる部分の 1 つです (このタスクの合計 CPU 時間が 30% を超えることも珍しくありません)。
この後、LoopFilter のボトルネックについて説明しますが、これはほかの hotspot にも当てはまることです。

最新世代のインテル® Core™ アーキテクチャー用に最適化

インテル® コンパイラーの 2 つの最適化機能であるベクトル化と表現認識は、デブロッキング・フィルターのパフォーマンス向上に重要な役割を果たします。

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

34

ベクトル化

1997 年に、インテルは、1 つの命令で複数の計算を行う革新的なマルチメディア拡張命令、インテル® MMX®
テクノロジーを発表しました。これらの新しい SIMD (Single Instruction Multiple Data) 命令は、複数のデータ項
目やベクトルを保持できる広い 64 ビットのレジスターを利用していました。インテル® MMX® テクノロジーに続いて、1999 年には、インテル® Pentium® III プロセッサーにインテル® ストリーミング SIMD 拡張命令 (インテル®
SSE) が実装されました。現在までに行われた主要な改訂は 11 回にのぼり、改訂のたびに新しい機能と命令が追加されました。これらの改訂のうち 3 回では SIMD レジスターの幅が 2 倍になり、並列処理が可能なデータ量は大幅に増加しました。

ベクトル化コードの作成

インテル® コンパイラーは、コードをベクトル化するさまざまな方法を提供しています (図 4)。ベクトル化を実装する最も簡単な方法は、インテル® マス・カーネル・ライブラリー (インテル® MKL) やインテル® インテグレーテッド・
パフォーマンス・プリミティブ (インテル® IPP) のような最適化ライブラリーを利用することです。
逆に、最も困難な方法は、アセンブラーや組込み関数を含むコードを手動で記述することです。この方法にはアルゴリズムの最も詳細な部分を細かく制御できるという長所がありますが、命令セット・アーキテクチャーの深い理解と専門知識が必要です。このような低レベルコードを記述する場合の問題の 1 つは、CPU アーキテク
チャーが新しい世代になるたびにコードを書き直さなければならないことです。
Pexip 社の開発者たちは、
ハードコードによる実装を避け、一般的な C/C++ でコードを記述して、インテル® コンパイラーの自動ベクトル化を利用しました。

4

コードをベクトル化するさまざまな方法

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

35

コードは自動ベクトル化により暗黙でベクトル化することもできますが、最近では明示的なベクトル化がよく利用されるようになっています。明示的なベクトル化では、プログラマーは、命令を考慮したプログラミングを用いることなく、配列表記などのベクトル化プラグマや構文をコードに追加することができます。
図 5 は、配列表記を使用した例です。この例の詳細な説明とその他の例については、https://www.cilkplus.
org/tutorial-array-notation (英語) をご覧ください。
配列表記 (アレイ・ノーテーション)
C[:][:]= 12;

等価なスカラー C/C++ コード

5for (i = 0; i < 10; i++)for (j = 0; j < 10; j++)C[i][j] = 12;(a) 2 次元配列 C のすべての要素を 12 に設定
func (A[:]);for (i = 0; i < 10; i++)func (A[i]);(b) 関数 func() に 1 つずつ要素を渡す

if (5 == a[:])results[:]= “Matched”;
else
results[:]= “Not Matched”;

for (int i = 0; i < array_size; i++){if (5 == a[i])results[i] = “Matched”;
else
results[i] = “Not Matched”;}(c) 配列 A の各要素について、値が 5 の場合は Matched 、その他の場合は Not Matched と出力
配列表記を用いた例

ベクトル化の例 : デブロッキング・フィルター

LoopFilter コードは、イメージをデブロックする際、重み付けアルゴリズムを用いて各マクロブロッ
ク境界に normal フィルターと strong フィルターのどちらを適用するかを判断しています。図 6 のstrong.c ファイルには、strong フィルターの例が含まれています。

出典 : https://www.cilkplus.org/tutorial-array-notation ( 英語 )インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

36

1: //strong.c
2: #include <stdint.h>
3: #deﬁne abs(x) (((x)<0)?-(x):(x))
4: #deﬁne max(x,y) ((x)>(y)?(x):(y))
5: #deﬁne min(x,y) ((x)<(y)?(x):(y))
6: #deﬁne norm(x,y) ((uint8_t)abs(x-y))
7: #deﬁne sat(x) max(min((int16_t)x,255),0)8:
9: void strong(uint8_t *restrict m,
10: uint8_t Alpha,
11: uint8_t Beta,
12: uint8_t Gamma)
13: {
14:
for(int i=0;i<16;i++)
15:
{
16:
uint8_t L3=m[0*16+i];
17:
uint8_t L2=m[1*16+i];
18:
uint8_t L1=m[2*16+i];
19:
uint8_t L0=m[3*16+i];
20:
uint8_t R0=m[4*16+i];
21:
uint8_t R1=m[5*16+i];
22:
uint8_t R2=m[6*16+i];
23:
uint8_t R3=m[7*16+i];24:
if ((uint8_t)((norm(R0,L0)<Alpha)25:&(norm(R0,R1)<Beta)
26:&(norm(L0,L1)<Beta)))
27:
{
28:
m[3*16+i]=sat((2*L1+L0+R1+2)>>2);
29:
m[4*16+i]=sat((2*R1+R0+L1+2)>>2);30:
if (norm(R0,L0)<Gamma)
31:
{
32:
if(norm(L0,L2)<Beta)
33:
{
34:
m[1*16+i]=sat((2*(L3+L2)+L2+L1+L0+R0+4)>>3);35:m[2*16+i]=sat((L2+L1+L0+R0+2)>>2);
36:m[3*16+i]=sat((R1+2*(L1+L0+R0)+L2+4)>>3);
37:
}
38:
if(norm(R0,R2)<Beta)
39:
{
40:
m[4*16+i]=sat((L1+2*(R1+L0+R0)+R2+4)>>3);41:
m[5*16+i]=sat((R2+R0+L0+R1+2)>>2);
42:m[6*16+i]=sat((2*(R3+R2)+R2+R1+L0+R0+4)>>3);
43:
}
44:
}
45:
}
46:
}
47: }

strong フィルターのコード

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

6The Parallel Universe

37/Qvec-report オプションを指定してコードをコンパイルすると、インテル® コンパイラーは 14 行目のメイン for ループ
がベクトル化されたことをレポートします。

icl /QxAVX /O2 /Qstd=c99 /Qvec-report2 strong.c
Intel(R) C++ Intel(R) 64 Compiler XE for applications running onIntel(R) 64 ...
strong.cc:\strong.c(14):(列 3) リマーク: ループがベクトル化されました。
このコンパイルで特筆すべき点は、コンパイラーが、3 レベルの if 文と混在したデータ型 (符号なし 8 ビットおよび符号付き 16 ビット) を含むコードをベクトル化したという事実です。
–S オプションを指定してアセンブラー・コードを生成すると、コードは vpaddw、vpsraw、vmovups のようなパックド命令でベクトル化されます。

icl /QxAVX/O2 /Qstd=c99-S strong.c

vpaddwxmm15, xmm15, xmm6
vpsrawxmm12, xmm12, 3
vpaddwxmm15, xmm15, xmm2
vpsrawxmm15, xmm15, 3
vpackuswb xmm12, xmm12, xmm15
vpblendvb xmm4, xmm4, xmm12, xmm14
vmovups
XMMWORD PTR [16+rcx], xmm4

;34.21;34.21;34.21;34.21;34.21;34.11;34.11

名前に p が含まれる命令はパックド命令です。パックド命令とは、レジスターでフルセットのベクトルを利用して行われる命令です。各命令についての詳細は、『Intel® Architecture Instruction Set Extensions Programming(
Reference インテル® アーキテクチャー命令セット拡張プログラミング・リファレンス)』を参照してください。

表現認識インテル® コンパイラーは、さまざまな計算パターンや表現を自動的に認識し、パフォーマンス効率に優れたコードを生成します。表現認識はコンパイラーの初期バージョンからサポートされている機能で、コンパイラーのさまざ
まなフェーズで実装されています。コンパイラーのバージョンが新しくなるたびに、新しい表現が追加されています。
表現の一例は、インテル® コンパイラーのベクトル化フェーズに実装されている、絶対差の合計 (SAD) を計算するパターンです。図 7 は、ソースコードの 3 つの部分を抜粋したものです。最初の 7(a) は単純な C コードで、a と bの各要素の差の絶対値を加えて変数 sad に格納します。

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

38

7(b) は、配列表記を用いて実装された同じ SAD アルゴリズムです。リダクション演算子 __sec_reduce_add は、
最初に絶対差を計算して、配列 a および b の各要素に適用します。
図 7(c) は、図 7(a) からインテル® コンパイラーによって生成されたアセンブラー・コードを示しています。コン
パイラーは SAD 表現を認識できるため、(符号なしバイト整数の絶対差のパックド合計を計算する) psadbw 命令を使用しています。配列表記コードをコンパイルすると、コンパイラーは 7(c) とほぼ同じアセンブラー・コードを生成します。
このアセンブラー・コードを生成するには、–S オプションを指定します。
Windows*: icl -S /QxAVX sad.c
Linux*: icc –S –xAVX sad.c

7a// C の SAD の計算#deﬁne abs(a) (((a)<0)?-(a):(a))
uint8_t a[16],b[16];int sad=0;
for(int i=0;i<16;i++)sad+=abs(a[i]-b[i]);// 配列表記を使用した SAD の計算

7b#deﬁne abs(a) (((a)<0)?-(a):(a))
uint8_t a[16],b[16];int sad=0;
sad = __sec_reduce_add(abs(a[:]-b[:]));

7c;; コンパイラーは;; sad 表現を認識して;; psadbw 命令を使用
movdqapxor

xmm0, XMMWORD PTR []xmm3, xmm3

psadbw

xmm0, XMMWORD PTR []paddd
movdqapsrldqpaddd
movdqapsrldqpaddd
movd

xmm3, xmm0
xmm1, xmm3
xmm1, 8xmm3, xmm1
xmm2, xmm3
xmm2, 4
xmm3, xmm2
eax, xmm3

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

インテル® コンパイラーは
SAD 表現を認識

The Parallel Universe

39

インテル® Architecture Code Analyzer

インテル® Architecture Code Analyzer は、新しい ISA 拡張命令が実装されたプロセッサーが実際に利用可能になる前に、これらの拡張命令を迅速に解析できるツールです。このツールは異なるマイクロアーキテクチャー上におけるコードの相対的なパフォーマンスを比較するために使用できますが、絶対的なパフォーマンス値は提供しません。
インテル® Architecture Code Analyzer は、プログラマーが挿入した特別なマーカー間に含まれるコードのスタ
ティック解析を行います。図 8 は、アナライザーのサンプル出力です。詳細は、whatif.intel.com ( 英語) を参照してください。

8

インテル® Architecture Code Analyzer のサンプル出力

図 9 は、第 2 世代、第 3 世代、第 4 世代インテル® Core™ マイクロアーキテクチャー上で strong フィルターのコードを解析した結果を示しています。Sandy Bridge† と Ivy Bridge† は同じアーキテクチャー機能の多くを共有しているため、同じサイクルカウントになると予想できます。最も大きな違いは、製造プロセスの違い (Ivy Bridge† は22nm で、Sandy Bridge† は 32nm) です。

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

開発コード名†The Parallel Universe

40

インテル® Core™ マイクロアーキテクチャーの世代

開発コード名コンパイラー・オプション

アナライザー・オプション

ブロックスループット

第 2 世代Sandy Bridge/QxAVX-64 –arch SNB

83.50

第 3 世代Ivy Bridge/QxAVX-64 –arch IVB

83.50

第 4 世代Haswell/QxCORE-AVX2-64 –arch HSW

55.60

9

異なる世代のインテル® Core™ マイクロアーキテクチャーにおける strong フィルターのサイクル・スループット

Pexip 社では、インテル® Architecture Code Analyzer を利用することにより、実際のハードウェアを使う前に、コードのパフォーマンスが第 4 世代インテル® Core™ マイクロアーキテクチャーで向上することを確認できました。

結果

インテル® コンパイラーのベクトル化および表現認識機能を使用した結果、図 10 で示されているように、コードの主な hotspot のすべてでパフォーマンスが向上しました。
サイクル数 x 109
ベクトル化なし (/no-vec)

ベクトル化あり (/QxAVX)

スピード
アップ

FastDct

69.66

3.64

19.14

MotionSearch

33.16

6.16

5.38

LoopFilter

14.62

3.54

4.13

EncodeMacroblock

12.62

1.64

7.70

EncodeSlice

12.30

6.78

1.81

Interpolate

6.30

1.28

4.92

hotspot

10

異なる hotspot のスピードアップ

Pexip 社では、パフォーマンスが求められるコードをアセンブラーではなく C で記述するようにしていたため、コードを記述し直すことなく、アプリケーションを最新のインテル® Core™ アーキテクチャーに対応させることができました。
最適化プロセスの開始時点で、会議ソフトウェアは 1080p ビデオを 7 fps (frames per second) でエンコードできました。最適化完了後は、14 倍以上も高速化され、100 fps でも快適にエンコードできるようになりました。

関連資料 (英語)

Pexip 社の本社はノルウェーのオスロにあり、米国およびイギリスに支店があります。
詳細は、Pexip 社の Web サイト (www.pexip.com) を参照してください。
インテル® Architecture Code Analyzer は、whatif.intel.com からダウンロードできます。

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

The Parallel Universe

41

最適化に関する注意事項
インテル® コンパイラーは、互換マイクロプロセッサー向けには、インテル製マイクロプロセッサー向けと同等レベルの最適化が行われない可能性があります。これには、インテル® ストリーミング SIMD 拡張命令 2 (インテル® SSE2)、インテル® ストリーミング SIMD 拡
張命令 3 (インテル® SSE3)、ストリーミング SIMD 拡張命令 3 補足命令 (SSSE3) 命令セットに関連する最適化およびその他の最適化が含まれます。インテルでは、インテル製ではないマイクロプロセッサーに対して、最適化の提供、機能、効果を保証していません。
本製品のマイクロプロセッサー固有の最適化は、インテル製マイクロプロセッサーでの使用を目的としています。インテル® マイクロアー
キテクチャーに非固有の特定の最適化は、インテル製マイクロプロセッサー向けに予約されています。この注意事項の適用対象である特定の命令セットの詳細は、該当する製品のユーザー・リファレンス・ガイドを参照してください。
改訂 #20110804

BLOG HIGHLIGHTS
トランザクショナル・メモリーのサポート : speculative_spin_mutex
CHRISTOPHER HUS »インテルは、インテル® Transactional Synchronization
Extensions (インテル® TSX) が追加された第 4 世代
インテル® Core™ プロセッサーを最近リリースしました。インテル® TSX は、データ保護のためのロック
ベースの同期を使用するアプリケーションのパフォー
マンスを改善します。この機能により、競合が発生していないロック保護データへの変更処理が並列実行されます。
私はこの数年間で、粗粒度のロックを、複数の細粒度のロックに置き換えて、変更される構造を保護することが並列パフォーマンスを向上する最良の方法の 1
つであることを発見しました。ただし、パフォーマン
スの向上は得られますが、正しく置き換えることは困難であり、操作を行うために必要なロックの数は増えてしまいます。複数のロックが同じキャッシュラインを占有する場合、パフォーマンス問題が発生する可能性もあります。これは、変更そのものがオーバーラップするわけではありませんが、同じキャッシュラインの隣接するミューテックスをロックするとフォルス・シェ
アリングを引き起こす可能性があるためです。
トランザクショナル・メモリーは、複数のスレッドが保護されたデータにアクセスまたは更新でき、更新がほかのすべてのスレッドに対してアトミックに見えるように保証することで、この問題に対処します。ロックを置き換えることを除いて、コードに変更を加えることなく、細粒度ロックの利点を活かすことができます。
インテル® TSX には、Hardware Lock Elision (HLE) と
Restricted Transactional Memory (RTM) の 2 つのイン
ターフェイスがあります。

この記事の続きはこちら (英語) でご覧になれます。

インテル® ソフトウェア製品のパフォーマンスおよび最適化に関する注意事項については、
http://software.intel.com/en-us/articles/optimization-notice/#opt-jp を参照してください。

llllllllllllllllllllllllllllllllllllllllll

Ⓒ 2013 Intel Corporation. 無断での引用、転載を禁じます。Intel、インテル、Intel ロゴ、Intel Core、MMX、Pentium、Xeon、Intel Xeon Phi、Cilk、VTune は、
アメリカ合衆国および / またはその他の国における Intel Corporation の商標です。
* その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。