与Windows,MSVC和OpenMP的线程关联

Z b*_*son 6 multithreading openmp affinity visual-c++

我想将代码中的线程绑定到每个物理核心.使用GCC我已成功完成此操作,sched_setaffinity因此我不再需要设置export OMP_PROC_BIND=true.我想在Windows中使用MSVC做同样的事情.Windows和Linux使用不同的线程拓扑.当Windows使用紧凑形式时,Linux会分散线程.换句话说,在具有四个内核和八个超线程的Linux中,我只需要将线程绑定到前四个处理单元.在Windows中,我将它们设置为每个其他处理单元.

我已成功完成此操作SetProcessAffinityMask.当我右键单击进程并单击"Set Affinity"时,我可以从Windows Task Manger中看到每个其他CPU都已设置(我的8个超线程系统上的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
Run Code Online (Sandbox Code Playgroud)

编辑:这是我现在使用的代码,它似乎在Linux和Windows上稳定

    #ifdef _WIN32   
    HANDLE process;
    DWORD_PTR processAffinityMask;
    //Windows uses a compact thread topology.  Set mask to every other thread
    for(int i=0; i<ncores; i++) processAffinityMask |= 1<<(2*i);
    process = GetCurrentProcess();
    SetProcessAffinityMask(process, processAffinityMask);
    #pragma omp parallel 
    {
        HANDLE thread = GetCurrentThread();
        DWORD_PTR threadAffinityMask = 1<<(2*omp_get_thread_num());
        SetThreadAffinityMask(thread, threadAffinityMask);
    }
    #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);
    #pragma omp parallel 
    {
       cpu_set_t  mask;
       CPU_ZERO(&mask);
       CPU_SET(omp_get_thread_num(),&mask);
       pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask); 
    }
    #endif
Run Code Online (Sandbox Code Playgroud)

YeP*_*IcK 1

您应该使用该SetThreadAffinityMask函数(请参阅MSDN 参考)。您正在设置进程的掩码。

您可以使用以下代码在 OpenMP 中获取thread ID

int tid = omp_get_thread_num();
Run Code Online (Sandbox Code Playgroud)

然而上面的代码提供了OpenMP的内部thread ID,而不是系统thread ID。本文解释了有关该主题的更多信息:

http://msdn.microsoft.com/en-us/magazine/cc163717.aspx

如果您需要显式地使用这些 trheads - 请使用显式的 affinity type,如本英特尔文档中所述:

https://software.intel.com/sites/products/documentation/studio/composer/en-us/2011Update/compiler_c/optaps/common/optaps_openmp_thread_affinity.htm

  • 顺便说一句,有很多方法可以创建不良的亲和力掩模,从而导致问题。如果您要手动设置线程关联性,则应查看[核心检测](http://code.msdn.microsoft.com/Core-Detection-Sample-7afd28f0) 示例。 (2认同)