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/55766303/

相关文章:

c++ - Windows、Linux 和内存管理

c++ - LNK1168 : cannot open debug\file. exe 写入

python - 在 Mac OS 10.7 上使用 pygame 的 IO python 多处理模块

python - 嵌入式CPython,使用命名管道进行线程交互

assembly - 在引导加载程序中初始化单独的 CPU 内核

Windows 脚本 (VBS) 始终使应用程序保持打开状态

python - PyUSB 与 Windows、libusb1 和 libusb-win32 后端不工作

c# - 在VS中可视化二叉树

c# - 如何在另一个文件更改时自动生成一个文件?

c# - 如何在片段中转义字符串插值