スレッド化されたインテル ® MKL をマルチスレッド・アプリケーションで使用する

同カテゴリーの次の記事

小さな問題サイズにおけるインテル® MKL パフォーマンスの向上: MKL_DIRECT_CALL の使用

この記事は、インテル® デベロッパー・ゾーンに掲載されている「Using Threaded Intel® MKL in Multi-Thread Application」の日本語参考訳です。


はじめに

インテル® マス・カーネル・ライブラリー (インテル® MKL) は、OpenMP* によるスレッド化で広範囲に並列化されています。そのため、スレッド化されたインテル® MKL ライブラリーにリンクすると、マルチコアシステムで自動的にプログラムが並列化されます。デフォルトでは、インテル® MKL は、OpenMP* によりスレッド数を設定し、スレッドを管理しています。しかし、ほかの手法 (例えば Linux* の Pthreads* など) でプログラムがスレッド化されている場合は、複数のスレッドを過度に使用しないように、シーケンシャル・ライブラリーを使うか、MKL_NUM_THREADS または OMP_NUM_THREADS =1 を設定して、インテル® MKL によるスレッド化を無効にすることを推奨します。あらゆる手法でアプリケーションの並列化を進めるにしたがって、いくつかの疑問が生じるでしょう。例えば、マルチスレッド・アプリケーションでインテル® MKL によるスレッド化を利用することはできるのか? ユーザースレッドとインテル® MKL スレッドは同時に実行できるのか?   また、どのようにしたらインテル® MKL スレッドを特定のコアにバインドできるのか? などです。フォーラムにも、U404745 How to set affinity while using MKL (インテル® MKL を使用する際のアフィニティーの設定)U38468 Problem with calling MKL gemm with pthread (Pthreads* でインテル® MKL の gemm を呼び出す際の問題) といった投稿があります。手短に言えば、インテル® MKL スレッドをマルチスレッド・アプリケーションで使用し、必要に応じてユーザーがインテル® MKL スレッド・アフィニティーを制御することは可能です。

この記事では、これらの疑問を取り上げます。すでにスレッド化されたアプリケーションで、スレッド化されたインテル® MKL を呼び出すケースに注目し、サンプルを例にインテル® MKL スレッドをプロセッサーにバインドする方法を説明します。

Q1:すでにマルチスレッド化されているアプリケーションで インテル® MKL スレッドを使用することはできますか?

多数の行列演算を実行する マルチスレッド・アプリケーションで、個別のスレッドにより各行列の演算を行うとします。(出典: フォーラム 475357)

テストシステムは、2 プロセッサー、プロセッサーごとに 4 コア、コアごとに 2 スレッド (インテル® ハイパースレッディング・テクノロジーが有効で、合計 8 物理コア、16 論理コア) と仮定します。行列乗算を同時に実行するスレッドを 2 つ生成し、それぞれで 4 つのインテル® MKL スレッドを開始することは可能でしょうか?

はい、マルチスレッド・アプリケーションでインテル® MKL スレッドを使用することは可能です (関連情報 [1] を参照)。次に簡単な例を示します。

#define NUM_PTHREADS 2
#define NUM_OMP_THREADS 4

mklTest(){
    mkl_set_num_threads_local(NUM_OMP_THREADS);
    mklcall();
}

// threadFunction;
void *threadfunc(void *pArg){
    mklTest()
}

int main(void){
    // Pthreads* を 2 つ生成する
    pthread_create(&tThreads[i], NULL, threadfunc, &idThreads[i]);
}

詳細は、添付の PDF ファイル (英語) を参照してください。

Q2: どのようにしたらインテル® MKL スレッドを特定のコアに明示的にバインドできますか?

2.1 グローバルにインテル® MKL スレッド・アフィニティーを設定する

複雑な状況では、スレッドを特定のプロセッサー・コアに明示的にバインドしなければいけないことがあるでしょう。インテル® MKL は、インテル® コンパイラーの OpenMP* ランタイム・ライブラリーをベースにしているため、OpenMP* スレッドを物理処理ユニットにバインドして、コンパイラーの OpenMP* と同じ方法でインテル® MKL スレッド・アフィニティーを制御することができます。一般に、2 つの方法があります。

詳細は、添付の PDF ファイル (英語) の 2-1 節を参照してください。

2.2 Pthreads* でインテル® MKL スレッド・アフィニティーを設定する

前述の方法は、グローバル・アフィニティーに基づいています。しかし、Pthreads* 内でスレッド・アフィニティーの制御が必要になることもあります。インテル® MKL スレッドには、Pthreads* プログラムの並列領域内かどうかが分かりません。そのため、インテル® MKL スレッド・アフィニティーを考慮して、生成する各 POSIX* スレッドのバインドするコード位置で set_affinity を追加し、OpenMP* ランタイム・ライブラリーから POSIX* スレッドを見えるようにし、AFFINITY 設定に応じてバインドされるようにします。

コード例と詳細は、添付の PDF ファイル (英語) の 2-2 節を参照してください。

2.3 Pthreads* で KMP アフィニティー関数を用いてインテル® MKL スレッド・アフィニティーを設定する

インテル® MKL スレッドを特定のプロセッサーにバインドするには、KMP アフィニティー関数を使用します。

omp_set_num_threads(NUM_OMP_THREADS);
    #pragma omp parallel default(shared)
    {
        // スレッド数を取得する
        int ompTid = omp_get_thread_num();

        // omp マスクを作成する
        kmp_affinity_mask_t new_omp_mask;
        kmp_create_affinity_mask(&new_omp_mask);

        // omp スレッドを偶数コアにバインドする
        kmp_set_affinity_mask_proc(ompTid*2+ thread_id* runprocs, &new_omp_mask);

        if (kmp_set_affinity(&new_omp_mask) != 0)
            printf("thread_id=%d Error: kmp_set_affinity(%d, &new_omp_mask)\n", thread_id, ompTid);

        printf("thread_id=%d, omp_tid=%d, new_mask=%08X \n", thread_id,ompTid, *(unsigned int*)(&new_omp_mask) );
    }

2.4 Pthreads* のアフィニティーを設定した場合のインテル® MKL スレッドの動作

Pthreads* スレッドでインテル® MKL スレッドを特定のプロセッサーにバインドする場合、最初に Pthreads* をバインドしてからインテル® MKL スレッドをバインドします。しかし、前述のとおり、インテル® MKL スレッドはインテルの OpenMP* ライブラリーによって管理されています。インテル® MKL スレッドには、Pthreads* の並列領域内かどうか、そしてどの Pthreads* が呼び出しているかが分かりません。ここでよくある問題は、インテル® MKL スレッドが Pthreads* のアフィニティーに従わないことです。そのため、例えば pthread_setaffinity_np() を使用して、Pthread 1 を CPU 0-7 に、Pthread 2 を CPU 8-15 にバインドします。

詳細は、添付の PDF ファイル (英語) の 2-4 節を参照してください。

まとめ

スレッド・アフィニティーは、スレッドを CPU コアにバインドします。マシンのトポロジーにより、スレッド・アフィニティーはプログラムの実行速度に大きな影響を与えます。インテル® MKL は OpenMP* によってスレッド化されているため、インテル® MKL スレッドは OpenMP* の手法によって制御することができます。高レベルのマルチスレッド・プログラムには、スレッド化されたインテル® MKL の使用を推奨しませんが、適切なアフィニティー設定を用いて十分注意して使用することはできます。この記事では、Pthreads* で KMP 環境変数と OS アフィニティー関数 sched_setaffinity を利用してグローバルにアフィニティーを設定するケース、Pthreads* 内部で OS アフィニティー関数と kmp_set_affinity 関数を利用するケース、pthread_getaffinity_np で Pthreads* のアフィニティーを設定する際のインテル® MKL スレッドの動作について説明しました。基本的な概念が得られたかと思います。

  1. Pthreads* と OpenMP* スレッドが同時に実行する場合、一般に最近の OS スケジューラーは上手く振る舞うことができるでしょう。ほとんどの場合、各 Pthreads* のタスクが均等であれば、スレッド・アフィニティーは必要ありません (ただし、必ずそうであるとは限りません)。

  2. OpenMP* スレッドと Pthreads* は互いを認識しませんが、ほとんどの場合スレッドの動作には影響しません (ただし、必ずそうであるとは限りません)。そのため、環境変数や OS アフィニティー関数によってグローバルにアフィニティーを設定することができます。

  3. OpenMP* スレッドと Pthreads* は互いを認識しませんが、バインドする位置に set_affinity 関数を追加することで OpenMP* スレッドのアフィニティーを制御できます。ここでは、OpenMP* スレッドと Pthreads* の関連付けを示すため、Pthreads* の番号を渡しました。

  4. マルチスレッドはランダムに実行されるため、アウト・オブ・オーダー実行によりいくつかの問題が生じます。例えば、OpenMP* スレッドは現在実行中の Pthreads* を予測できないため、インテル® MKL スレッドは Pthreads* のアフィニティーに従いません。

関連情報

  1. Using Intel® MKL with Threaded Applications (インテル® MKL とスレッド化アプリケーションの使用) (英語)
  2. マルチスレッド・アプリケーションからインテル® MKL ルーチンを呼び出す場合の推奨設定
  3. Setting thread affinity on SMT or HT enabled systems for better performance (SMT または HT 対応システムで優れたパフォーマンスを得るためのスレッド・アフィニティーの設定) (英語)
  4. インテル® マス・カーネル・ライブラリー・リファレンス・マニュアル (英語)
  5. How to set affinity while using MKL (インテル® MKL を使用する場合のアフィニティーの設定) (英語)
  6. Problem with calling MKL gemm with pthread (Pthreads* でインテル® MKL の gemm を呼び出す場合の問題) (英語)
  7. How to set affinity of threads spawned by MKL? (インテル® MKL によってスポーンされたスレッドのアフィニティーの設定) (英語)
添付ファイル サイズ
mkl-affinity.pdf 214.96KB

コンパイラーの最適化に関する詳細は、最適化に関する注意事項を参照してください。

関連記事

  • OpenMP* スレッド・アフィニティーの制御OpenMP* スレッド・アフィニティーの制御 この記事は、インテル® ソフトウェア・サイトに掲載されている「OpenMP* Thread Affinity Control」(2013年2月時点) の日本語参考訳です。 はじめに インテルの OpenMP* ランタイム・ライブラリーには、OpenMP* […]
  • マルチスレッド・アプリケーションからインテル® MKL ルーチンを呼び出す場合の推奨設定マルチスレッド・アプリケーションからインテル® MKL ルーチンを呼び出す場合の推奨設定 この記事は、インテル® ソフトウェア・ネットワークに掲載されている「Recommended settings for calling Intel MKL routines from multi-threaded applications」の日本語参考訳です。 マルチスレッド・アプリケーション1 […]
  • インテル® MKL 10.3 で追加された新機能インテル® MKL 10.3 で追加された新機能 この記事は、インテル® ソフトウェア・ネットワークに掲載されている「What's new in Intel® MKL?」の日本語参考訳 (一部編集含む) です。 インテル® MKL 10.3 では主に次の機能が追加されました。 インテル® アドバンスト・ベクトル・エクステンション (インテル® AVX) […]
  • HPL 向けアプリケーション・ノートHPL 向けアプリケーション・ノート この記事は、インテル® ソフトウェア・ネットワークに掲載されている「HPL application note」の日本語参考訳です。 ステップ 1 - 概要 このガイドは、現在 HPL を使用しているユーザーが、より優れたベンチマーク結果を得られるように、インテル® マス・カーネル・ライブラリー (インテル® MKL) の […]
  • サマリー統計ライブラリーの概要サマリー統計ライブラリーの概要 この記事は、インテル® ソフトウェア・ネットワークに掲載されているブログ「Statistical Summary Library Overview」の日本語参考訳です。 統計的計算の精度とパフォーマンスが強化された最新のアルゴリズムを提供する、最適化された並列ライブラリーがインテル® MKL 10.3 […]