OpenMp并未利用所有CPU(双插槽,Windows和Microsoft Visual Studio)

时间:2019-04-19 18:37:53

标签: windows visual-studio multiprocessing openmp

我有一个双插槽系统,每个CPU有22个实际内核,每个CPU有44个超线程。我可以使用openMP来完全利用第一个CPU(22核/ 44超级),但是不能使用第二个CPU。

我正在使用CPUID HWMonitor检查我的核心使用情况。在所有内核上,第二个CPU始终为0%或接近0%。

使用:

int convertTime::invalidHr(int hour) { ... }
int convertTime::invalidMin(int min) { ... }
int convertTime::invalidSec(int sec) { ... }

让我nProcessors = 44,但是我认为它只使用1个CPU的44个超线程,而不是44个真实内核(应该是88个超线程)

环顾四周后,我不确定如何利用其他CPU。

我的CPU运行良好,因为我可以运行利用所有这些程序的其他并行处理程序。

我正在以64位编译此文件,但我认为这并不重要。另外,我正在使用Visual Studio 2017专业版15.2。打开MP 2.0(仅一个vs支持)。在带有2个Intel Xeon E5-2699v4 @ 2.2Ghz处理器的Windows 10 Pro(64位)上运行。

1 个答案:

答案 0 :(得分:0)

因此,感谢@AlexG为我提供了一些见解,回答了我自己的问题。请参阅问题的评论部分。

这是Microsoft Visual Studio和Windows的问题。

先读Processor Groups for Windows

基本上,如果您拥有64个以下的逻辑核心,这将不是问题。但是,一旦超过该限制,每个套接字(或Windows选择的其他组织)现在将具有两个进程组。就我而言,每个进程组都有44个超线程,并代表一个物理CPU插槽,而我恰好有两个进程组。默认情况下,每个进程(程序)都只能访问一个进程组,因此我最初只能在一个内核上利用44个线程。但是,如果您手动创建线程并使用SetThreadGroupAffinity将线程的处理器组设置为与程序最初分配的组不同的线程,则您的程序现在将成为多处理器组。这似乎是一种启用多处理器的环回方法,但是可以,这是方法。一旦开始设置每个线程的单个进程组,对GetProcessGroupAffinity的调用将显示组数大于1。

我能够像这样创建一个开放的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);
        }
    }
}

因此,使用上面的代码,我能够强制运行64个线程,每个套接字每个都运行32个线程。现在,即使我尝试将omp_set_num_threads强制设置为88,也无法获得64个线程。原因似乎与Visual Studio的OpenMP实现有关,该实现不允许超过64个OpenMP线程。这是更多information

的链接

感谢大家帮助收集了更多有助于最终答案的花絮!