我想将代码中的线程绑定到每个物理核心。在GCC中,我成功地使用了sched_setaffinity来实现这一点,因此不再需要设置export OMP_PROC_BIND=true。我想在Windows下使用MSVC做同样的事情。Windows和Linux使用不同的线程拓扑。Linux会分散线程,而Windows则使用紧凑形式。换句话说,在具有四个内核和八个超线程的Linux系统中,我只需要将线程绑定到前四个处理单元。在Windows中,我将它们设置为每隔一个处理单元设置一次。
我已经成功地使用SetProcessAffinityMask实现了这一点。当我在进程上右键单击并点击“设置关联性”时,可以从Windows任务管理器中看到每隔一个CPU被设置(我的八个超线程系统上的0、2、4、6)。问题是当我运行代码时,效率是不稳定的。有时它几乎是恒定的,但大部分时间都有很大变化。我将优先级改为高,但没有任何区别。在Linux下,效率是稳定的。也许Windows仍在迁移线程?还有其他需要在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
编辑:以下是我现在使用的代码,似乎在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
omp_get_thread_num()
的结果将其分配到一个设置了单个位的亲和掩码中。 - Hristo Ilievpthread_setaffinity_np
?到目前为止似乎可以(并且pthread_self()
确实为并行区域中的每个线程返回不同的值)。 - Z boson