CPUあたり22個の実コアまたはCPUあたり44個のハイパースレッドを備えたデュアルソケットシステムがあります。openMPで最初のCPU(22コア/ 44ハイパー)を完全に利用することはできますが、2番目のCPUを利用することはできません。
CPUIDHWMonitorを使用してコアの使用状況を確認しています。2番目のCPUは、すべてのコアで常に0%またはその近くにあります。
使用:
int nProcessors = omp_get_max_threads();
nProcessors = 44を取得しますが、44個の実際のコア(88個のハイパースレッドである必要があります)ではなく、1個のCPUの44個のハイパースレッドを使用していると思います。
よく見てみると、他のCPUの使い方がわかりません。
それらすべてを利用する他の並列処理プログラムを実行できるため、CPUは正常に実行されています。
私はこれを64ビットでコンパイルしていますが、それは問題ではないと思います。また、Visual Studio 2017Professionalバージョン15.2を使用しています。MP 2.0を開きます(1つのみvsサポート)。Windows 10 Pro、64ビット、2つのIntel Xeon E5-2699v4 @ 2.2Ghzプロセッサで実行。
それで、いくつかの洞察を提供してくれた@AlexGに感謝して、私自身の質問に答えます。質問のコメントセクションをご覧ください。
これは、Microsoft VisualStudioとWindowsの問題です。
最初にWindows用のプロセッサグループを読んでください。
基本的に、64未満の論理コアがある場合、これは問題にはなりません。ただし、それを乗り越えると、ソケットごとに2つのプロセスグループが作成されます(またはWindowsが選択する他の組織)。私の場合、各プロセスグループには44個のハイパースレッドがあり、1つの物理CPUソケットを表しており、正確に2つのプロセスグループがありました。デフォルトでは、すべてのプロセス(プログラム)には1つのプロセスグループへのアクセスしか許可されていないため、最初は1つのコアで44のスレッドしか利用できませんでした。ただし、手動でスレッドを作成し、SetThreadGroupAffinityを使用して、スレッドのプロセッサグループを、プログラムの最初に割り当てられたグループとは異なるグループに設定すると、プログラムはマルチプロセッサグループになります。これはマルチプロセッサを有効にするための回り道のように思えますが、そうです、これはそれを行う方法です。
このようにオープンMPブロックを作成し、プロセスグループを調べて割り当てることができました。
..。
#pragma omp parallel num_threads( 88 )
{
HANDLE thread = GetCurrentThread();
if (omp_get_thread_num() > 32)
{
// Reserved has to be zero'd out after each use if reusing structure...
GroupAffinity1.Reserved[0] = 0;
GroupAffinity1.Reserved[1] = 0;
GroupAffinity1.Reserved[2] = 0;
GroupAffinity1.Group = 0;
GroupAffinity1.Mask = 1 << (omp_get_thread_num()%32);
if (SetThreadGroupAffinity(thread, &GroupAffinity1, &previousAffinity))
{
sprintf(buf, "Thread set to group 0: %d\n", omp_get_thread_num());
OutputDebugString(buf);
}
}
else
{
// Reserved has to be zero'd out after each use if reusing structure...
GroupAffinity2.Reserved[0] = 0;
GroupAffinity2.Reserved[1] = 0;
GroupAffinity2.Reserved[2] = 0;
GroupAffinity2.Group = 1;
GroupAffinity2.Mask = 1 << (omp_get_thread_num() % 32);
if (SetThreadGroupAffinity(thread, &GroupAffinity2, &previousAffinity))
{
sprintf(buf, "Thread set to group 1: %d\n", omp_get_thread_num());
OutputDebugString(buf);
}
}
}
したがって、上記のコードを使用して、ソケットごとにそれぞれ32スレッド、64スレッドを強制的に実行することができました。omp_set_num_threadsを88に強制しようとしても、64スレッドを超えることができませんでした。理由は、64を超えるOpenMPスレッドを許可しないVisualStudioのOpenMPの実装に関連しているようです。詳細については、そのリンクをご覧ください。
最終的な答えに役立ったいくつかのちょっとした情報を集めるのを手伝ってくれてありがとう!
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加