CPU亲和力有哪些注意事项?

时间:2018-01-21 20:57:52

标签: multithreading openmp

用户何时应该在OMP并行应用程序中将OMP_PROC_BIND设置为TRUE?似乎将线程保持在同一个CPU应该更快,因为您可能正在减少一些调度并可能缓存移动开销。

我对多个OMP并行化过程中的这个问题的答案很感兴趣。

让我们举一个具体的例子。我有一个48核盒子和两个类似的OMP_NUM_THREADS=16应用程序。我最好不要让OMP_PROC_BIND解开,让自然亲和力走上正轨吗?

尝试使用OMP_PROC_BIND=TRUE,当有多个OMP进程时,我的libgomp系统似乎不能很好地运行:所有32个线程都安排在相同的16个cpus上。如果没有OMP_PROC_BIND,所有48个内核似乎都会在某个时刻使用,而且一切运行得更快。

然后问题是:CPU亲和力到底是什么?

2 个答案:

答案 0 :(得分:1)

与任何与效果相关的设置最重要的规则是:衡量,不要猜测。

通常,将每个OpenMP线程的关联性固定/绑定/设置为一个专用核心(或硬件线程)是最有效的。固定线程而不确保核心专用于该线程会导致您描述的问题。两个OpenMP流程是分开的,它们使用相同的核心,因为他们根本不知道要选择哪个核心。

如果您可以控制系统上的所有进程,则可以将它们分配到不同的核心集上。有几件事情做同样的事情:

  1. 使用操作系统限制进程的cpuset,然后让OpenMP执行线程的固定:

    $ OMP_PROC_BIND=true taskset -c 0-15 ./a
    $ OMP_PROC_BIND=true taskset -c 16-31 ./b
    

    这样的事情通常由HPC批处理系统透明地完成。

  2. 使用libgomp特定的环境变量

    $ OMP_NUM_THREADS=16 GOMP_CPU_AFFINITY="0-15" ./a
    $ OMP_NUM_THREADS=16 GOMP_CPU_AFFINITY="16-32" ./b
    
  3. 使用功能强大但复杂的标准OMP_PLACES环境变量:

    $ OMP_NUM_THREADS=16 OMP_PLACES="{0}:16" ./a
    $ OMP_NUM_THREADS=16 OMP_PLACES="{16}:16" ./b
    
  4. 现在,亲和力的另一个方面是,当您拥有比线程更多的内核时,这一点尤其重要。根据应用程序的特性,将线程尽可能放置close(线程之间的通信速度更快)或通过硬件spread放出线程(更多可用的共享资源)是有益的。它可以使用三个相关的(G)OMP环境变量中的任何一个进行控制。这一切都取决于您的应用程序和您的系统 - 这里没有一般规则。

答案 1 :(得分:0)

OMP_PROC_BIND仅禁止在不同的cpu之间移动线程,它不是 affinity 的一般概念。

对我来说, affinity 是将线程限制为一组硬件处理器。如果您的计算机具有NUMA体系结构,将线程从特定的cpus组移动到另一个组是不可接受的,这将非常重要。

引自https://gcc.gnu.org/onlinedocs/libgomp/OMP_005fPLACES.html

  

如果未设置OMP_PLACES和GOMP_CPU_AFFINITY并且OMP_PROC_BIND未设置或为false,则可以在没有放置策略的情况下在CPU之间移动线程。

表示如果您未指定关联策略,则可能会将一个线程移动到其他NUMA节点。因此,通常我将使用GOMP_CPU_AFFINITY在单个NUMA节点中指定cpus列表,以防止出现意外行为。