web-dev-qa-db-ja.com

スレッドを作成するときにCPUアフィニティを設定する

最初のコアで実行するC++ 11スレッドを作成したいと思います。それみつけたよ pthread_setaffinity_npおよびsched_setaffinityは、スレッドのCPUアフィニティを変更し、指定されたCPUに移行できます。ただし、このアフィニティ仕様は、スレッドの実行後に変更されます。

特定のCPUアフィニティを備えたC++ 11スレッドを作成するにはどうすればよいですか(cpu_set_tオブジェクト)?

C++ 11スレッドを初期化するときにアフィニティを指定できない場合は、pthread_t in C?

私の環境はUbuntuのG ++です。コードの一部をいただければ幸いです。

15
Peng Zhang

ここで「怪しい伝説」になって申し訳ありませんが、スレッドアフィニティの設定は非常に重要であり、私たち全員が使用するシステムが本質的にNUMA(Non-Uniform Memory Architecture)になるにつれて、その重要性はますます高まっています。最近の些細なデュアルソケットサーバーでさえ、RAMは各ソケットに個別に接続されており、ソケットから独自のメモリへのアクセスの違いRAM隣接するプロセッサソケット(リモートRAM)の容量はかなりのものです。近い将来、プロセッサは、コアの内部セット自体がNUMAである市場に出回っています(コアの個別のグループ用の個別のメモリコントローラなど)。必要はありません。ここで他の人の作業を繰り返すには、オンラインで「NUMAとスレッドの親和性」を探してください。他のエンジニアの長年の経験から学ぶことができます。

スレッドアフィニティを設定しないことは、OSスケジューラがスレッドアフィニティを正しく処理することを「期待する」ことと実質的に同じです。説明させてください:いくつかのNUMAノード(処理ドメインとメモリドメイン)を備えたシステムがあります。スレッドを開始すると、スレッドはメモリを使用していくつかの処理を実行します。いくつかのメモリをmallocしてから処理など。最近のOS(少なくともLinux、おそらく他のOSも)はこれまでのところうまく機能しています。デフォルトでは、メモリはスレッドが実行されているCPUの同じドメインから割り当てられます(利用可能な場合)。 。時が来れば、タイムシェアリングOS(すべての最新OS)はスレッドをスリープ状態にします。スレッドが実行状態に戻ると、システム内のコアのanyで実行可能になる可能性があり(アフィニティマスクを設定しなかったため)、システムが大きくなると、以前に割り当てまたは使用したメモリから離れたCPUで「ウェイクアップ」される可能性が高くなります。これで、すべてのメモリアクセスがリモートになります(これがアプリケーションのパフォーマンスにどのような影響を与えるかわからない場合は、オンラインのNUMAシステムでのリモートメモリアクセスの詳細を参照してください)

したがって、要約すると、アフィニティ設定インターフェイスは、重要なアーキテクチャを備えたシステムでコードを実行する場合に非常に重要です。これは、最近急速に「任意のシステム」になりつつあります。一部のスレッドランタイム環境/ライブラリでは、特定のプログラミングなしで実行時にこれを制御できます(たとえば、IntelのKMP_AFFINITY環境変数の実装でOpenMPを参照)。C++ 11実装者が同様のメカニズムをに含めるのは正しいことです。それらのランタイムライブラリと言語オプション(それまでは、コードがサーバーでの使用を目的としている場合は、コードにアフィニティ制御を実装することを強くお勧めします)

20
Benzi Galili

C++ 11では、スレッドの作成時にスレッドアフィニティを設定することはできませんが(スレッドで実行されている関数が独自に行う場合を除く)、スレッドが作成されると、使用しているネイティブインターフェイスを介してアフィニティを設定できます。スレッドのネイティブハンドル(thread.native_handle())を取得することにより、Linuxの場合は次の方法でpthreadIDを取得できます。

pthread_t my_thread_native = my_thread.native_handle();

次に、my_thread_nativeを渡す任意のpthread呼び出しを、pthreadスレッドIDが必要な場所で使用できます。

ほとんどのスレッド機能は実装固有であることに注意してください。つまり、pthread、windowsスレッド、他のOSのネイティブスレッドはすべて独自のインターフェイスとタイプを持っており、コードのこの部分はあまり移植性がありません。

2
diverscuba23

はい、それを作る方法があります。私はこのブログでこの方法に出くわしました リンク

そして、この質問に対する他のすべての回答には例がありません。コードの書き方は次のとおりです

  std::vector<std::thread> threads(num_threads);
  for (unsigned i = 0; i < num_threads; ++i) {
    threads[i] = std::thread([&iomutex, i] {
    std::this_thread::sleep_for(std::chrono::milliseconds(900));
      }
    });

    // Create a cpu_set_t object representing a set of CPUs. Clear it and mark
    // only CPU i as set.
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
    CPU_SET(i, &cpuset);
    int rc = pthread_setaffinity_np(threads[i].native_handle(),
                                    sizeof(cpu_set_t), &cpuset);
    if (rc != 0) {
      std::cerr << "Error calling pthread_setaffinity_np: " << rc << "\n";
    }
  }

すべてのクレジットはブログの作者であるElienderskyに与えられるべきであり、リンクは上に貼り付けられました。

1
Z-Y00