windows - OpenMp 不使用所有 CPU(双路、windows 和 Microsoft visual studio)

标签 windows visual-studio multiprocessing openmp

我有一个双插槽系统,每个 CPU 有 22 个真正的核心或每个 CPU 有 44 个超线程。我可以让 openMP 完全利用第一个 CPU(22 核/44 hyper),但我无法让它利用第二个 CPU。

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

使用:

int nProcessors = omp_get_max_threads();

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

看了很多之后,我不确定如何利用另一个 CPU。

我的 CPU 运行良好,因为我可以运行其他利用它们的并行处理程序。

我正在用 64 位编译它,但我认为这不重要。另外,我使用的是 Visual Studio 2017 Professional 15.2 版。打开 MP 2.0(只有一个 vs 支持)。在配备 2 个 Intel Xeon E5-2699v4 @ 2.2Ghz 处理器的 64 位 Windows 10 Pro 上运行。

最佳答案

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

这是 Microsoft Visual Studio 和 Windows 的问题。

先读 Processor Groups for Windows .

基本上,如果您的逻辑内核数少于 64 个,这将不是问题。但是,一旦你通过了这一点,你现在将为每个套接字(或 Windows 选择的其他组织)拥有两个进程组。在我的例子中,每个进程组有 44 个超线程,代表一个物理 CPU 插槽,而我正好有两个进程组。默认情况下,每个进程(程序)只能访问一个进程组,因此我最初只能在一个内核上使用 44 个线程。但是,如果您手动创建线程并使用 SetThreadGroupAffinity 将线程的处理器组设置为与您的程序最初分配的组不同的组,那么您的程序现在变成了一个多处理器组。这似乎是一种启用多处理器的迂回方式,但是是的,这就是实现它的方法。调用 GetProcessGroupAffinity 将显示,一旦您开始设置每个线程的单独进程组,组数就会大于 1。

我能够像这样创建一个开放的 MP block ,并通过并分配进程组:

...

#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

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

关于windows - OpenMp 不使用所有 CPU(双路、windows 和 Microsoft visual studio),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57041262/

相关文章:

c# - 如何在 android 项目属性中启用调试 (Xamarin Android)

c++ - Visual Studio 中 C++ 代码的变量依赖关系图

Python 3 非阻塞同步行为

python - 管理具有不同内存使用情况的 Python 多进程进程

c# - 在给定 HWND 的情况下如何获取窗口的子窗口?

linux - 在 windows git powershell 中访问 linux 路径

fonts - Visual Studio 调色板窗口背景

python 2.7 : Themed "common dialog" tkinter interfaces via Ttk?

c - DAQmxReadAnalogScalarF64 到底做什么?

Python 多处理关键字参数