Multithreading 与Windows、MSVC和OpenMP的线程关联
我想将代码中的线程绑定到每个物理核心。 有了GCC,我已经使用Multithreading 与Windows、MSVC和OpenMP的线程关联,multithreading,visual-c++,openmp,affinity,Multithreading,Visual C++,Openmp,Affinity,我想将代码中的线程绑定到每个物理核心。 有了GCC,我已经使用sched_setaffinity成功地完成了这项工作,因此我不再需要设置export-OMP\u-PROC\u-BIND=true。我想用MSVC在Windows中做同样的事情。Windows和Linux使用不同的线程拓扑。Linux分散线程,而windows使用紧凑形式。换句话说,在具有四个内核和八个超线程的Linux中,我只需要将线程绑定到前四个处理单元。在windows中,我将它们设置为每隔一个处理单元 我已经使用SetPro
sched_setaffinity
成功地完成了这项工作,因此我不再需要设置export-OMP\u-PROC\u-BIND=true
。我想用MSVC在Windows中做同样的事情。Windows和Linux使用不同的线程拓扑。Linux分散线程,而windows使用紧凑形式。换句话说,在具有四个内核和八个超线程的Linux中,我只需要将线程绑定到前四个处理单元。在windows中,我将它们设置为每隔一个处理单元
我已经使用SetProcessAffinityMask
成功地完成了这项工作。当我右键单击进程并单击“设置关联性”时,我可以从Windows任务管理器中看到每隔一个CPU都已设置(在我的八超线程系统上为0、2、4、6)。问题是我的代码在运行时效率不稳定。有时它几乎是恒定的,但大多数时候它有很大的变化。我把优先级改为“高”,但没有什么区别。在Linux中,效率是稳定的。也许Windows仍在迁移线程?我还需要做些什么来绑定Windows中的线程吗
这是我正在使用的代码
#ifdef _WIN32
HANDLE process;
DWORD_PTR processAffinityMask = 0;
//Windows uses a compact thread topology. Set mask to every other thread
for(int i=0; i<ncores; i++) processAffinityMask |= 1<<(2*i);
//processAffinityMask = 0x55;
process = GetCurrentProcess();
SetProcessAffinityMask(process, processAffinityMask);
#else
cpu_set_t mask;
CPU_ZERO(&mask);
for(int i=0; i<ncores; i++) CPU_SET(i, &mask);
sched_setaffinity(0, sizeof(mask), &mask);
#endif
\ifdef\u WIN32
处理过程;
DWORD_PTR processAffinityMask=0;
//Windows使用紧凑的线程拓扑。将掩码设置为每隔一个线程
对于(int i=0;i您应该使用SetThreadAffinityMask
函数(请参阅)。您正在设置进程的掩码
您可以使用以下代码在OpenMP中获取线程ID
:
int tid = omp_get_thread_num();
但是,上面的代码提供了OpenMP的内部线程ID
,而不是系统线程ID
。本文详细介绍了该主题:
如果需要显式使用这些trhead,请使用显式关联类型
,如本英特尔文档中所述:
在这两种平台上,您的代码为每个线程设置进程关联掩码而不是关联掩码,因此调度程序仍然可以在进程关联掩码允许的CPU之间自由移动线程。@hristoilev,我理解您的意思。您知道如何获取OpenMP创建的每个线程的线程句柄吗?在并行区域用于获取当前线程的句柄,并根据omp\u get\u thread\u num()的结果为其分配一个具有单个位集的关联掩码
@HristoIliev,你是说在并行区内?我试过了,它会为每个线程返回相同的句柄。我会继续尝试…我的意思是从并行区内调用它,以便所有OpenMP线程都进行调用。在这种情况下,它不应该返回相同的线程句柄,除非你分配给共享变量。你有一些e吗示例代码?我是指为每个线程设置掩码的代码?可能有办法获取与进程关联的线程并在其上循环。Microsoft的OpenMP实现使用系统管理的线程池。枚举和绑定所有进程线程会影响不属于线程池的一些线程(例如,管理器线程,可能隐藏的窗口消息循环线程等)。我会在并行区域内执行绑定。顺便说一句,有很多方法可以创建导致问题的不良关联掩码。如果您要手动设置线程关联,您应该看一看示例。
int tid = omp_get_thread_num();