微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

OpenMP 似乎将其线程绑定到不同的内核,但实际的关联掩码允许使用所有内核

如何解决OpenMP 似乎将其线程绑定到不同的内核,但实际的关联掩码允许使用所有内核

在 AMD Ryzen 9 5900X(12 核,AMD 的超线程等效禁用)上使用 x64 msvc v19.29,这是一个仅使用 omp_set_num_threads( 10 );#pragma omp parallel for schedule( dynamic,1 ) 并行化的程序似乎一个主线程和九个工作线程绑定到不同的内核。观察 Windows 任务管理器,10 个内核被 100% 使用,而两个内核或多或少处于空闲状态。每次重新启动程序时,空闲内核和单元化内核都会发生变化,但观察到的行为保持不变。使用 SetThreadAffinitMask( . ) 的返回值检查 静态 OpenMP 循环中每个线程的线程关联性表明所有线程都可以在所有 12 个内核上运行。

相比之下,使用基于C++17的线程池(这里主线程不做任何工作,10个工作线程都做),可以观察到严重的线程乒乓现象,没有准空闲内核。毋庸置疑,OpenMP 变体的性能明显优越。

我的问题是,如果 OpenMP 没有将线程绑定到不同的内核,则使用哪种机制来导致观察到的行为?如何通过 Windows API 复制行为?

作为旁注,我对使用 OpenMP 犹豫不决,因为它不能保证与 C++11 或更高的构造一起使用(据我所知,忽略实验设置,Visual Studio支持 OpenMP 2.0)。

编辑 1:回答 J. Richard 的问题

auto getMask =
  []( HANDLE handle )
  {
    auto mask = DWORD_PTR{ 1 };
    mask = SetThreadAffinityMask( handle,mask );
    SetThreadAffinityMask( handle,mask );
    return mask;
  };

std::vector< DWORD_PTR > masks( 10 );

#pragma omp parallel for schedule( static,1 )
for ( auto i = 0; i < 10; ++i )
{
  masks[ i ] = getMask( GetCurrentThread() );
}

masks 的每个元素都等于 4095(十进制)或 111111111111(二进制)。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。