並列化すべき個所を自動診断する新ツール「インテル Parallel Advisor」を使ってみよう 3ページ

指定した個所が並列化に適しているかを調査する

 Survey Analysisでは実行に時間のかかっている個所を調査できるが、その部分を並列化したからといって必ずしもパフォーマンスが向上するとは限らない。プログラムによってはオーバーヘッドなどにより、並列化すると逆にパフォーマンスが低下する場合もあるからだ。

 Parallel AdvisorのSuitability Analysisでは、実際にプログラムを並列化することなしに、指定した個所が並列化に向いているかどうか、また並列化によってどの程度のパフォーマンス向上が見込めるかを診断できる。作業としては、Survery Analysisで発見したホットスポットに対し、Suitability Analysisで並列化の効果を診断する、という流れとなる。

ソースコードにAnnotationを付加する

 Suitability Analysisでは、コード中に「Annotation」と呼ばれる追跡用マクロを挿入することで調査対象となる個所を指定する。AnnotationはParallel Advisorに付属する「advisor-annotate.h」で定義されているマクロで、Suitability AnalysisやCorrectness Analysisはこのマクロで指定された個所を対象に分析を実行する。

 Annotationは「ANNOTATE_<Anotation名>_BEGIN(<パラメータ>)」と「ANNOTATE_<Anotation名>_END(<パラメータ>)」のペアになっており、この2つを対象とする関数呼び出しやループの前後に挿入していく。

Annotationに使用するコード

 Parallel Advisorでは目的やコードに合わせてさまざまなAnnotationが用意されているが、そのなかでもよく使用すると思われる基本的なものは表5の3つだ。

表5 よく使われると思われるAnnotation
Annotation 説明
ANNOTATE_SITE_BEGIN(sitename); 分析対象サイト(ブロック)の開始
ANNOTATE_SITE_END(sitename); 分析対象サイト(ブロック)の終了
ANNOTATE_TASK_BEGIN(taskname); 分析対象タスクの開始
ANNOTATE_TASK_END(taskname); 分析対象タスクの終了
ANNOTATE_LOCK_ACQUIRE(address); ロックの開始。addressにはロック対象となる変数のアドレスを指定する
ANNOTATE_LOCK_RELEASE(address); ロックの終了。addressにはロック対象となる変数のアドレスを指定する

 Parallel Advisorではサイト(もしくはループ)内で実行される処理を「タスク」と呼ぶ。基本的にはSurvey Analysisで検出された、処理に時間がかかっているサイトの前後に「ANNOTATE_SITE_BEGIN」および「ANNOTATE_SITE_END」を、サイト内で実行している処理それぞれの前後に「ANNOTATE_TASK_BEGIN」および「ANNOTATE_TASK_END」を挿入する、という形となる。

 また、並列実行した際に複数のスレッドから同時に実行されると問題となる個所の前後には「ANNOTATE_LOCK_ACQUIRE」および「ANNOTATE_LOCK_RELEASE」を挿入する。なお、「sitename」および「taskname」はそのAnnotationを区別するための名称で、半角英数字およびアンダースコア(_)が使用できる。

#include "advisor-annotate.h"

Annotationをコードに挿入する

 今回、多くの処理時間を消費している個所は前述のとおり「main.cxx」内129行目からのループとなり、このなかで実行されている「generate」関数がタスクに相当する。そこで次のようにforループの前後に「ANNOTATE_SITE_BEGIN」および「ANNOTATE_SITE_END」を、generate関数の前後に「ANNOTATE_TASK_BEGIN」および「ANNOTATE_TASK_END」を挿入し、調査対象とする。

int main()
{
    Grid::initialize();
    ANNOTATE_SITE_BEGIN(main_loop);
    for (int i = 0; i != 100; ++i) {
        ANNOTATE_TASK_BEGIN(main_generate);
        generate(Solver::METHOD_BOX_LINE);
        ANNOTATE_TASK_END(main_generate);
    }
    ANNOTATE_SITE_END(main_loop);
    return 0;
}

 なお、Visual Studioのコードエディタを利用している場合、対象を選択した状態でコンテキストメニューの「Intel Parallel Advisor 2011」?「Annotate Site」などでコードを挿入することが可能だ(図8)。

図8 Visual StudioのコードエディタではコンテキストメニューからAnnotationを挿入できる
図8 Visual StudioのコードエディタではコンテキストメニューからAnnotationを挿入できる

 また、同時にAnnotationを定義している「advisor-annotate.h」をincludeするよう設定しておく。今回は共通して呼び出されている「solver.h」内に「#include “advisor-annotate.h”」を追加した。このファイルは「$(ADVISOR_2011_DIR)\include」というディレクトリに格納されているので、インクルードファイルの探索パスにこのディレクトリを追加しておく。最後にプロジェクトをリビルドすれば作業は完了だ。

Suitability Analysisを実行する

 Suitability Analysisは、Advisor Workflowウィンドウ内の「3. Check Suitability」から実行できる。「Start」ボタンをクリックするとプログラムが開始され、実行終了後にデータ集計が行われて結果が「Suitability Report」として表示される(図9)。

図9 Suitability Analysisの実行結果は「Suitability Report」画面に表示される
図9 Suitability Analysisの実行結果は「Suitability Report」画面に表示される

 「Suitability Report」画面では、Annotationで指定した個所を並列化することでどの程度パフォーマンスが向上するかを確認できる。パフォーマンス向上倍率はCPU数や使用する並列化技術ごとに推定でき、たとえば「インテル スレッディング・ビルディング・ブロック(TBB)を用いて並列化を実装し8コアのマシンで実行するとパフォーマンスが7.63倍向上する」など、具体的な数字で効果を確認できる。

 また、画面下には指定したサイトごとに、CPU数に応じたパフォーマンス向上度がグラフで表示される。今回問題となっている個所では、16コア程度まではほぼCPU数に比例してパフォーマンスが向上することが分かる。また、グラフ横には問題とする個所を並列化することによるオーバーヘッドの大小も表示される。

 なお、今回の例ではソースコードの変更を行わずとも並列化の効果がある、という診断結果が得られているが、プログラムによってはそのままでは並列化を行ってもパフォーマンスが得られない、という場合がある。このような場合、Selected Site画面右側に表示される「変更を加えるとどれだけパフォーマンスが変化するか」という情報を確認するととよい。

 ここでは行う変更(Type of Change)として5つの項目が用意されており(表6)、それぞれにチェックを入れることでその効果がグラフにも反映される。

表6 提案されている変更(Type of Change)
Type of Change 説明
Reduce Site Overhead サイトを実行する際のオーバーヘッドを少なくする
Reduce Task Overhead タスクを実行する際のオーバーヘッドを少なくする
Reduce Lock Overhead ロックを実行する際のオーバーヘッドを少なくする
Reduce Lock Contention ロック内で実行される処理を少なくする
Enable Task Chunking サイト内で実行する処理を分割する