< 目次

マルチコアのパフォーマンスを管理

スレッドを処理するコアを固定することで、マルチコア・プロセッサーのシステムで最良のパフォーマンスを得ることができます。それには、スレッドにアフィニティー・マスクを設定し、スレッドと CPU コアをバインドします。以下のいずれかのオプションを使用します。

以下のパフォーマンス問題について考えてみます。

この問題を解決するには、インテル® oneAPI マス・カーネル・ライブラリー (インテル® oneMKL) を呼び出す前に、KMP_AFFINITY 環境変数や sched_setaffinity システム関数を使用して、OpenMP* スレッドのアフィニティー・マスクを設定します。以下のコードサンプルは、オペレーティング・システムでアフィニティー・マスクを設定してこの問題を解決する方法を示しています。コードは関数 sched_setaffinity を呼び出して、スレッドを異なるソケット上のコアにバインドします。次に、インテル® oneAPI マス・カーネル・ライブラリー (インテル® oneMKL) の FFT 関数が呼び出されます。

#define _GNU_SOURCE // GNU CPU アフィニティーを使用
// (適切なカーネルと glibc で動作) 
// アフィニティーを設定 
#include <sched.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <omp.h> 
int main(void) { 
    int NCPUs = sysconf(_SC_NPROCESSORS_CONF); 
    printf("Using thread affinity on %i NCPUs\n", NCPUs); 
#pragma omp parallel default(shared) 
    { 
        cpu_set_t new_mask; 
        cpu_set_t was_mask; 
        int tid = omp_get_thread_num(); 

        CPU_ZERO(&new_mask); 

        // 2 パッケージ x 2 コア/パッケージ x 1 スレッド/コア (合計 4 コア) 
        CPU_SET(tid==0 ? 0 : 2, &new_mask); 

        if (sched_getaffinity(0, sizeof(was_mask), &was_mask) == -1) { 
            printf("Error: sched_getaffinity(%d, sizeof(was_mask), &was_mask)\n", tid); 
        } 
        if (sched_setaffinity(0, sizeof(new_mask), &new_mask) == -1) { 
            printf("Error: sched_setaffinity(%d, sizeof(new_mask), &new_mask)\n", tid); 
        } 
        printf("tid=%d new_mask=%08X was_mask=%08X\n", tid, 
                *(unsigned int*)(&new_mask), *(unsigned int*)(&was_mask)); 
    } 
    // oneMKL FFT関数を呼び出す 
    return 0; 
}  

インテル® コンパイラーで、以下のコマンドを使用してアプリケーションをコンパイルします。

icx test_application.c -openmp 

test_application.c は、アプリケーションのソースファイル名です。

アプリケーションをビルドします。例えば、次のように環境変数にスレッド数を設定し、ビルドしたアプリケーションを 2 スレッドで実行します。

env OMP_NUM_THREADS=2 ./a.out

上記の例で使用されている sched_setaffinity 関数の詳細については、Linux プログラマーズ・マニュアル (man ページ形式) を参照してください。

製品および性能に関する情報

性能は、使用状況、構成、およびその他の要因によって異なります。詳細については、www.Intel.com/PerformanceIndex (英語) をご覧ください。

改訂 #20201201