OpenMP 4.0 提供 OMP_PLACES 和 OMP_PROC_BIND 环境变量来指定程序中的 OpenMP 线程如何绑定到处理器。这两个环境变量通常结合使用。OMP_PLACES 用于指定线程将绑定到的计算机位置。OMP_PROC_BIND 用于指定绑定策略(线程关联性策略),这项策略指定如何将线程分配到位置。仅设置 OMP_PLACES 不会启用绑定。您还需设置 OMP_PROC_BIND。
根据 OpenMP 规范,OMP_PLACES 的值可以是以下两种类型值之一:用于描述一组位置(线程、核心或插槽)的抽象名称或非负数描述的明确位置列表。通过使用 <lowerbound> : <length> : <stride> 表示法表示以下编号列表,还可以使用间隔来定义位置:"<lower-bound>, <lower-bound> + <stride>, …, <lower-bound> + (<length>-1)*<stride>"。省略 <stride> 时,将采用单元距值。如果不设置 OMP_PLACES,则缺省值为核心。
示例 14 一个位置中一个硬件线程% OMP_PLACES="{0:1}:8:32" {0:1} defines a place which has one hardware thread only, namely place {0}. The interval {0:1}:8:32 is therefore equivalent to {0}:8:32, which defines 8 places starting with place {0}, and the stride is 32. So the list of places is as follows: Place 0: {0} Place 1: {32} Place 2: {64} Place 3: {96} Place 4: {128} Place 5: {160} Place 6: {192} Place 7: {224}示例 15 一个位置中两个硬件线程
% OMP_PLACES="{0:2}:32:8" {0:2} defines a place which has two hardware threads, namely place {0,1}. The interval {0:2}:24:8 is therefore equivalent to {0,1}:24:8 which defines 24 places starting with place {0,1}, and the stride is 8. So the list of places is as follows: Place 0: {0,1} Place 1: {8,9} Place 2: {16,17} Place 3: {24,25} Place 4: {32,33} Place 5: {40,41} Place 6: {48,49} Place 7: {56,57} Place 8: {64,65} Place 9: {72,73} Place 10: {80,81} Place 11: {88,89} Place 12: {96,97} Place 13: {104,105} Place 14: {112,113} Place 15: {120,121} Place 16: {128,129} Place 17: {136,137} Place 18: {144,145} Place 19: {152,153} Place 20: {160,161} Place 21: {168,169} Place 22: {176,177} Place 23: {184,185}
除了 OMP_PLACES 和 OMP_PROC_BIND 这两个环境变量外,OpenMP 4.0 还提供可在 parallel 指令中使用的 proc_bind 子句。proc_bind 子句用于指定如何将执行并行区域的线程组绑定到处理器。
有关 OMP_PLACES 和 OMP_PROC_BIND 环境变量以及 proc_bind 子句的详细信息,请参阅 OpenMP 4.0 规范。
本节详细介绍 OpenMP 4.0 规范中的 2.5.2 节“控制 OpenMP 线程关联性”。
当线程遇到包括 proc_bind 子句的并行构造时,OMP_PROC_BIND 环境变量用于确定将线程绑定到位置的策略。如果并行构造包括 proc_bind 子句,则 proc_bind 子句指定的绑定策略将覆盖 OMP_PROC_BIND 指定的策略。组中的线程分配到某个位置后,实现不会将其移到其他位置。
master 线程关联性策略指示执行环境将组中的每个线程分配到与主线程相同的位置。此策略不会更改位置分区,且每个隐式任务将继承父隐式任务的 place-partition-var 内部控制变量 (Internal Control Variable, ICV)。
close 线程关联性策略指示执行环境将组中的线程分配到靠近父线程位置的位置。此策略不会更改位置分区,且每个隐式任务将继承父隐式任务的 place-partition-var ICV。如果 T 指组中的线程数量,P 指父线程所在位置分区中的位置数量,那么将按以下方法将组中的线程分配到位置:
T <= P。主线程在父线程(即遇到并行构造的线程)的位置上执行。下一个线程编号最小的线程在位置分区的下一个位置上执行,以此类推,相对主线程的位置分区进行绕回分配。
T > P。每个位置 P 将包含 Sp 个线程编号连续的线程,其中 floor(T/P) <= Sp <= ceiling(T/P)。前 S0 个线程(包括主线程)分配到父线程的位置。接下来的 S1 个线程分配到位置分区的下一个位置,以此类推,相对主线程的位置分区进行绕回分配。当 P 不能整除 T 时,特定位置的具体线程数由实现定义。
spread 线程关联性策略的目的是将一组 T 个线程稀疏地分布到父线程所在位置分区的 P 个位置。要实现稀疏分布,首先将父分区分割为 T 个子分区(如果 T <= P)或 P 个子分区(如果 T > P)。然后,将一个线程 (T <= P) 或一组线程 (T > P) 分配到每个子分区。每个隐式任务的 place-partition-var ICV 均设置为其子分区。分割为子分区不仅是实现稀疏分布的机制,还定义了在创建嵌套并行区域时可供线程使用的位置子集。将线程分配到位置的方法如下所示:
T <= P。父线程的位置分区拆分为 T 个子分区,其中每个子分区包含 floor(P/T) 个或 ceiling(P/T) 个连续位置。向每个子分区分配一个线程。主线程在父线程的位置上执行,并分配到包含该位置的子分区。下一个线程编号最小的线程分配到下一个子分区的第一个位置,以此类推,相对主线程的原始位置分区进行绕回分配。
T > P。父线程的位置分区拆分为 P 个子分区,每个子分区包含一个位置。每个子分区分配有 Sp 个线程编号连续的线程,其中 floor(T/P) <= Sp <= ceiling(T/P)。前 S0 个线程(包括主线程)分配到包含父线程位置的子分区。接下来的 S1 个线程分配到下一个子分区,以此类推,相对主线程的原始位置分区进行绕回分配。当 P 不能整除 T 时,特定子分区中的具体线程数由实现定义。