通过处理器绑定,程序员可指示 Solaris 操作系统在整个程序执行期间在同一处理器上运行该程序中的线程。(在 Linux 上不提供此功能。)
在将处理器绑定与静态调度一起使用时,将有益于展示某个数据重用模式的应用程序,在该模式中,由并行区域或工作共享区域中的线程访问的数据将位于上次调用的并行区域或工作共享区域的本地缓存中。
从硬件的角度看,计算机系统是由一个或多个物理处理器组成的。从操作系统的角度看,其中每个物理处理器都映射到可运行程序中的线程的一个或多个虚拟处理器。如果 n 个虚拟处理器可用,则可同时调度运行 n 个线程。根据系统的不同,虚拟处理器可能是处理器、内核,等等。例如,每个 UltraSPARC IV 物理处理器都具有两个内核;从 Solaris OS 的角度看,其中每个内核都是一个虚拟处理器,可以在其中安排要运行的线程。另一方面,UltraSPARC T1 物理处理器具有八个内核,每个内核可运行四个同时进行处理的线程;从 Solaris OS 的角度看,共有 32 个虚拟处理器,可以在其中安排要运行的线程。在 Solaris 操作系统上,可以使用 psrinfo(1M) 命令来确定虚拟处理器的数量。
当操作系统将线程绑定到处理器时,实际上是将线程绑定到特定的虚拟处理器而不是物理处理器。
当在 Solaris OS 下运行时,设置 SUNW_MP_PROCBIND 环境变量,以便将 OpenMP 程序中的线程绑定到特定的虚拟处理器。为 SUNW_MP_PROCBIND 指定的值可以是下列值之一:
字符串 "TRUE" 或 "FALSE"(或小写的 "true" 或 "false")。例如, % setenv SUNW_MP_PROCBIND "false"
非负整数。例如,% setenv SUNW_MP_PROCBIND "2"
由一个或多个空格分隔的两个或更多非负整数的列表。例如,% setenv SUNW_MP_PROCBIND "0 2 4 6"
两个非负整数 n1 和 n2,二者之间由减号 ("-") 分隔;n1 必须小于或等于 n2。例如,% setenv SUNW_MP_PROCBIND "0-6"
请注意,上文提到的非负整数表示逻辑标识符 (ID)。逻辑 ID 可能不同于虚拟处理器 ID。下面将介绍二者之间的差异。
虚拟处理器 ID:
系统中的每个虚拟处理器都有唯一的处理器 ID。可以使用 Solaris 操作系统的 psrinfo(1M) 命令显示有关系统中处理器的信息,包括其处理器 ID。此外,还可以使用 prtdiag(1M) 命令显示系统配置和诊断信息。
可以使用 psrinfo -pv 列出系统中的所有物理处理器以及与每个物理处理器关联的虚拟处理器。
虚拟处理器 ID 可能是连续的,也可能是不连续的。例如,在具有 8 个 UltraSPARC IV 处理器(16 个内核)的 Sun Fire 4810 上,虚拟处理器 ID 可能是:0、1、2、3、8、9、10、11、512、513、514、515、520、521、522、523。
逻辑 ID:
如上所述,为 SUNW_MP_PROCBIND 指定的非负整数是逻辑 ID。逻辑 ID 是从 0 开始的连续整数。如果系统中可用的虚拟处理器数为 n,则其逻辑 ID 为 0、1、...、n-1(按 psrinfo(1M) 命令显示的顺序)。以下 Korn shell 脚本可用于显示从虚拟处理器 ID 到逻辑 ID 的映射。
#!/bin/ksh NUMV= `psrinfo | fgrep "on-line" | wc -l ` set -A VID `psrinfo | cut -f1 ` echo "Total number of on-line virtual processors = $NUMV" echo let "I=0" let "J=0" while [[ $I -lt $NUMV ]] do echo "Virtual processor ID ${VID[I]} maps to logical ID ${J}" let "I=I+1" let "J=J+1" done |
在将单个物理处理器映射到多个虚拟处理器的系统上,了解哪些逻辑 ID 与属于同一物理处理器的虚拟处理器相对应会很有用。在以后的 Solaris 发行版中,可以使用以下 Korn shell 脚本来显示此信息。
#!/bin/ksh NUMV= `psrinfo | grep "on-line" | wc -l ` set -A VLIST `psrinfo | cut -f1 ` set -A CHECKLIST `psrinfo | cut -f1 ` let "I=0" while [ $I -lt $NUMV ] do let "COUNT=0" SAMELIST="$I" let "J=I+1" while [ $J -lt $NUMV ] do if [ ${CHECKLIST[J]} -ne -1 ] then if [ `psrinfo -p ${VLIST[I]} ${VLIST[J]} ` = 1 ] then SAMELIST="$SAMELIST $J" let "CHECKLIST[J]=-1" let "COUNT=COUNT+1" fi fi let "J=J+1" done if [ $COUNT -gt 0 ] then echo "The following logical IDs belong to the same physical processor:" echo "$SAMELIST" echo " " fi let "I=I+1" done |
解释为 SUNW_MP_PROCBIND 指定的值:
如果为 SUNW_MP_PROCBIND 指定的值是非负整数,则该整数表示线程应绑定到的虚拟处理器的起始逻辑 ID。线程会从具有指定逻辑 ID 的处理器开始,以循环方式绑定到虚拟处理器,在绑定到逻辑 ID 为 n-1 的处理器后,返回到逻辑 ID 为 0 的处理器。如果为 SUNW_MP_PROCBIND 指定的值是包含两个或更多非负整数的列表,则线程将以循环方式绑定到具有指定逻辑 ID 的虚拟处理器。将不会使用其逻辑 ID 不是指定逻辑 ID 的处理器。
如果为 SUNW_MP_PROCBIND 指定的值是用减号 ("-") 分隔的两个非负整数,则线程将以循环方式绑定到如下范围的虚拟处理器:以第一个逻辑 ID 开头,并以第二个逻辑 ID 结尾。将不会使用其逻辑 ID 在此范围之外的处理器。
如果为 SUNW_MP_PROCBIND 指定的值不符合上述任何一种形式,或者给定的逻辑 ID 无效,则会发出一条错误消息,并终止程序的执行。
请注意,微任务化库 libmtsk 创建的线程数取决于环境变量、用户程序中的 API 调用和 num_threads 子句。SUNW_MP_PROCBIND 指定线程应绑定到的虚拟处理器的逻辑 ID。线程将以循环方式绑定到该组处理器。如果程序中使用的线程数少于 SUNW_MP_PROCBIND 指定的逻辑 ID 数,则程序将不使用某些虚拟处理器。如果线程数大于 SUNW_MP_PROCBIND 指定的逻辑 ID 数,则一些虚拟处理器将绑定多个线程。