API ガイド > マルチスレッド化プラグイン >

# OpenMP

OpenMP の概要

OpenMP は、主にデータの並列処理用に設計された高レベルのスレッド抽象であり、fior ループに適用されます。これは、VS2005 とすべてのプラットフォームの Intel コンパイラでサポートされます。OSX 版と Linux 版の Maya で必要な gcc のバージョンは、OpenMP をサポートしていません。

OpenMP はコンパイラ プラグマを介して実装されます。ネイティブ スレッドと比較すると、非常にシンプルなインタフェースです。スレッドの作成と管理のすべてとデータ パーティション作成の大部分は、ユーザに対して表示されません。OpenMP は、初めて並列領域が発生したときに作成されるスレッド プールを使用します(このため、OpenMP コードのプロファイル時にアプリケーションで最初のループ トラバースを無視することが重要です)。

以下に、スレッド化ループの簡単な例を示します。

    #pragma omp parallel for
    for(int i=0; i<imax; i++) {
        doThreadsafeWork(i);
    }

このコードは、コンパイラによって変換され、複数スレッド(既定では論理プロセッサごとに 1 スレッド)によって並列で実行される関数になります。最初のプロセッサはループの最初の(imax/numThreads)要素を取り、2 番目のプロセッサは次の同等サイズのチャンク、というふうに続きます。これにより、優れたキャッシュ アフィニティが実現し、プロセッサ通常は隣接するデータ要素を処理するため、キャッシュ ミスを最小限に抑ることができます。

以下に、より複雑な例を示します。

    #pragma omp parallel for schedule(guided) if(imax>1000)
    for(int i=0; i<imax; i++) {
        doThreadsafeWork(i);
        #pragma omp critical
        doNonThreadsafeWork(i);
    }

このコードもループをチャンクに分割しますが、guided スケジュール設定オプションによってサイズ(imax/numThreads)よりも小さいチャンクが使用され、既存のチャンクが完了すると新しいチャンクが各スレッドに送られます。これにより、ループの繰り返し間で作業負荷が異なる場合に、実行時に追加チャンクが早期に完了するスレッドに割り当てられるため、負荷のバランスが改善されます。critical プラグマは、後続ラインにロックを配置しています。

メイン プラグマの if 条件によって、トリップ数(ループの繰り返し回数)が指定した値を超えた場合にのみ、ループは並列で実行されます。並列領域のコールにはオーバーヘッドがあるため、トリップ数が小さすぎるときに評価を並列にしても意味はありません。有用な経験則として、並列領域の開始と終了に 1 万クロック サイクルのオーバーヘッドを想定し、カットオフ トリップ数がこの処理を上回るようにすることをお勧めします。これは特に Maya のようなアプリケーションで重要です。Maya では、単一の非常に複雑なオブジェクトでも多数の非常に単純なオブジェクトでも同じアルゴリズムが実行される場合があります。後者の場合、数千もの非常に短いスレッド化評価のため余計な起動時オーバーヘッドが生じてスレッド化の利点がすべて帳消しになり、カットオフのないスレッド化コードで大幅に処理速度が低下する可能性があります。スレッド化が条件によって中断されない場合でも、ループ内部のコードはコンパイラによって個別の関数に抽出されるため、関数コールの影響を受けます。

OpenMP の利点と欠点

OpenMP の利点は、クロスプラットフォームのサポート、実装と削除が容易であることです。プラグマを無効にするだけでコードは順次形式に戻るため、動作が同じであることをすばやく確認することができます。上記の例のような非常に単純な OpenMP プラグマを使用すると、非常に大量なコードのスレッド化が可能です。異なるスレッド化ライブラリを使用して最終実装を行う場合でも、スレッド化の利点の迅速なプロトタイピングや評価に非常に便利です。

欠点は、アルゴリズムの適用に制約があり、実装間に互換性がないことです。VS2005 と Intel OpenMP ライブラリは併用できますが、相互の実装は認識されません。したがって、Intel コンパイラでコンパイルした関数をコールする VC2005 でコンパイルしたスレッド化ループでは、Intel コンパイラで定義した OpenMP ロックはすべて無視されます。

OpenMP では、ネストされたスレッド化にも問題があります。この場合、より高レベルのスレッドが生成され、それ自体がより低レベルにスレッド化されるコードを呼び出します。これにより、システムのコアよりも多くのスレッドがアクティブになります。これは、オーバーサブスクリプションと呼ばれ、パフォーマンスの低下を引き起こします。アプリケーションにスレッド化が追加されるにつれて、オーバーサブスクリプションの問題は大きくなります。これは、並列でコールされている関数自体がスレッド化されていることに開発者が気付いていない場合があるためです。

OpenMP と Maya

流体ソルバ、ヘア衝突、多数のデフォーマなど Maya の多くのアルゴリズムは、OpenMP を使用してスレッド化されます。Maya では、すべてのプラットフォームで OpenMP に Intel コンパイラが使用されます。

OpenMP のベンダ固有の問題

一部の OpenMP 実装には、パフォーマンスと正確性に関する問題がいくつかあります。詳細については、ベンダ固有の OpenMP の課題を参照してください。