HPC/並列プログラミングポータルでは、HPC(High Performance Computing)プログラミングや並列プログラミングに関する情報を集積・発信しています。

新着トピックス

「タスク」という概念が追加されたOpenMP 3.0のサポート

 インテル コンパイラ 11.1では、並列プログラミングAPIであるOpenMPの最新版であるOpenMP 3.0に対応している。OpenMPはさまざまなプラットフォームで利用できる並列プログラミングの技術基盤であり、対応コンパイラおよびライブラリを組み合わせることで、比較的手軽にプログラムを並列化できる。

 以下ではOpen MP 3.0で追加された特徴などについて解説するが、OpenMPの概要やインテル コンパイラーでの利用法・利用例については「ソフトウェア高速化の鍵は「並列化」:いま注目される並列化技術を知る」や「並列アプリケーションを作ってみよう」といった以前の記事でも紹介しているので、そちらも参照して欲しい。

 最新のOpenMP 3.0は2008年5月にリリースされており、2005年リリースのOpenMP 2.5から下記のような変更が加えられている。

  • 「タスク」の概念が追加され、これにより新たな並列化パターン「task」が利用できるようになった
  • 「omp_set_schedule」および「omp_get_schedule」、「omp_get_level」、「omp_get_ancestor_thread_num」、「omp_get_team_size」といった新たなランタイムライブラリ関数の追加
  • 内部変数「thread-limit-var」および「max-active-levels-var」、「stack-size-var」、「wait-policy-var」の追加。これらおよび関連する環境変数を利用することで、OpenMPプログラムが使用する最大スレッド数やスレッドのスタックサイズ、待ち状態のスレッドの振る舞いなどを制御できる
  • スレッドの実行/割り当てルールが若干変更された

 この中で、OpenMPの新機能として特に注目されているのが「タスク」の概念である。OpenMP 3.0以前の場合、並列化の実装には「Folk-Joinモデル」というモデルが想定されていた。これは、プログラム中の特定の個所で複数のスレッドを生成して処理を実行させ(Folk)、それぞれのスレッドに割り当てられた処理が全て完了したら単一のスレッドで続きを実行する(Join)、というモデルである(図2)。

74fc64fa1addd28b89cdf5af6c6c9f09.png
図2 OpenMPのFolk-Joinモデル

 しかし、OpenMP 2.5以前のFolk-JoinモデルではFolk時にしかスレッドが生成されず、処理途中で新たにスレッドを追加できない、という制限があった(Folkで生成されたスレッド中で再度Folk-Joinを行う、といった、ネストされた構造は可能)。そのため、たとえばforループで一定回数同じ処理を繰り返す、といった処理については簡単に実装できるものの、whileループのように、実行してみないとループが何回実行されるか分からない繰り返し処理については、そのままではOpenMPによる並列化が行えないという不都合があった。この問題を解決するべく考案されたのが、「タスク」の概念である。

 OpenMP 3.0では、処理すべきコードブロックを「タスク」という単位で管理するようになった。タスクは「omp parallel for」演算子などで生成されるほか、「omp task」演算子を利用して動的にも生成できる。たとえば次のリスト5は、whileループを「omp task」演算子を利用して並列する例である。このコードは、リンクドリストに対する繰り返し処理を行うものだ。

リスト5 「omp task」演算子を利用した並列コードの例
struct linked_list {
    struct linked_buffer* next;
    int data1;
      :
      :
};
  :
struct linked_list* ptr_next;
  :
ptr_next = ptr_start;
#pragma omp parallel
{
    #pragma omp single nowait
    {
        while(ptr_next) {
            #pragma omp task firstprivate(ptr_next)
            {
                foobar2(ptr_next);
            }
        ptr_next = ptr_next-next ;
    }
}

 このように「omp task」演算子を利用することで、リンクドリストなど「omp for」演算子では並列化できなかったデータに対する処理を、容易に並列化することが可能になる。

 なお、インテル コンパイラー11.1では、これらのOpenMP 3.0サポートに加え、新たに並列化ソースコードの解析やデバッグに便利な機能が追加されている。まず1つは、「Parallel Debugger Extension」という機能で、これはプログラム中で並列化された部分を、ソースコードの再コンパイルを行うことなしに非並列にステップ実行するものだ。これにより、並列化されたプログラムでも容易に実行されるコードを追跡できるようになる。

 またParallel Lint機能という、OpenMPによる並列化コードを分析し、メモリリークやデッドロックなどの問題を診断する機能も追加されている。

 並列化されたプログラムで問題が発生した場合、手作業によるデバッグでは問題の発生している個所を見つけにくいことも多い。このような並列プログラム向けの機能は、問題発生時に非常に有用だ。