我想将代码中的线程绑定到每个物理核心。
使用GCC,我已成功使用sched_setaffinity
完成此操作,因此我不再需要设置export OMP_PROC_BIND=true
。我想在Windows中使用MSVC做同样的事情。 Windows和Linux使用不同的线程拓扑。当Windows使用紧凑形式时,Linux会分散线程。换句话说,在具有四个内核和八个超线程的Linux中,我只需要将线程绑定到前四个处理单元。在Windows中,我将它们设置为每个其他处理单元。
我已使用SetProcessAffinityMask
成功完成此操作。当我右键单击进程并点击" Set Affinity"我可以从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
编辑:这是我现在使用的代码,它似乎在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
答案 0 :(得分:1)
您应该使用SetThreadAffinityMask
功能(请参阅MSDN reference)。您正在设置进程的掩码。
您可以使用以下代码在OpenMP中获取thread ID
:
int tid = omp_get_thread_num();
但是,上面的代码提供了OpenMP的内部thread ID
,而不是系统thread ID
。本文将详细介绍该主题:
http://msdn.microsoft.com/en-us/magazine/cc163717.aspx
如果您需要明确使用这些标头 - 请使用显式 affinity type
,如本英特尔文档中所述: