本章提供使用 Sun 或 Cray 指令和 pragma 将传统程序转换为 OpenMP 的指导。
传统的 Sun 和 Cray 并行化指令现已过时,不再受 Sun Studio 编译器支持。
传统 Fortran 程序使用 Sun 或 Cray 风格的并行化指令。《Fortran 编程指南》的“并行化”一章中有对这些指令的描述。
下列各表提供了与 Sun 并行化指令及其子子句几乎等效的 OpenMP 指令和子子句。这些只是建议值。
表 B–1 将 Sun 并行化指令转换为 OpenMP| 
 Sun 指令  | 
 等效 OpenMP 指令  | 
|---|---|
| 
 C$PAR DOALL [qualifiers]  | 
 !$omp parallel do [qualifiers]  | 
| 
 C$PAR DOSERIAL  | 
 无完全等效指令。可以使用: !$omp master loop !$omp end master  | 
| 
 C$PAR DOSERIAL*  | 
 无完全等效指令。可以使用: !$omp master loopnest !$omp end master  | 
| 
 C$PAR TASKCOMMON block[,...]  | 
 !$omp threadprivate (/block/[,...])  | 
DOALL 指令可带有下列可选的限定符子句。
表 B–2 DOALL 限定符子句和等效的 OpenMP 子句| 
 Sun DOALL 子句  | 
 等效的 OpenMP PARALLEL DO 子句  | 
|---|---|
| 
 PRIVATE(v1,v2,...)  | 
 private(v1,v2,...)  | 
| 
 SHARED(v1,v2,...)  | 
 shared(v1,v2,...)  | 
| 
 MAXCPUS(n)  | 
 num_threads(n)。无完全等效子句。  | 
| 
 READONLY(v1,v2,...)  | 
 无完全等效指令。使用 firstprivate(v1,v2,...) 可以获得相同效果。  | 
| 
 STOREBACK(v1,v2,...)  | 
 lastprivate(v1,v2,...)。  | 
| 
 SAVELAST  | 
 无完全等效指令。使用 lastprivate(v1,v2,...) 可以获得相同效果。  | 
| 
 REDUCTION(v1,v2,...)  | 
 reduction(operator:v1,v2,...) 必须提供约简操作符和变量列表。  | 
| 
 SCHEDTYPE(spec)  | 
 schedule(spec)(请参见表 B–3)  | 
SCHEDTYPE(spec) 子句接受下列调度规范。
表 B–3 SCHEDTYPE 调度和等效的 OpenMP schedule 子句| 
 SCHEDTYPE(spec)  | 
 等效的 OpenMP schedule(spec) 子句  | 
|---|---|
| 
 SCHEDTYPE(STATIC)  | 
 schedule(static)  | 
| 
 SCHEDTYPE(SELF(chunksize))  | 
 schedule(dynamic,chunksize) 缺省 chunksize 为 1。  | 
| 
 SCHEDTYPE(FACTORING(m))  | 
 无完全等效指令。  | 
| 
 SCHEDTYPE(GSS(m))  | 
 schedule(guided, m) 缺省 m 为 1。  | 
私有变量作用域必须使用 OpenMP 加以显式声明。对于 Sun 指令,编译器对未在 PRIVATE 或 SHARED 子句中显式确定作用域的变量使用它自己的缺省作用域确定规则:所有标量均按 PRIVATE 处理;所有数组引用均按 SHARED 处理。对于 OpenMP,除非 PARALLEL DO 指令中出现 DEFAULT(PRIVATE) 子句,否则缺省数据作用域为 SHARED。DEFAULT(NONE) 子句会使编译器标记那些未显式确定作用域的变量。有关在 Fortran 中自动确定作用域的信息,请参见4.4 有关使用嵌套并行操作的一些提示。
由于没有 DOSERIAL 指令,因此混合使用自动和显式 OpenMP 并行化的效果可能会不同: 某些使用 Sun 指令不能自动并行化的循环可能会被自动并行化。
OpenMP 通过提供并行区域和并行段来提供更丰富的并行操作模型。使用 Sun 指令来重新设计程序的并行操作策略,以利用 OpenMP 的这些功能,便有可能获得更高的性能。
Cray 风格的 Fortran 并行化指令与 Sun 风格的并行化指令几乎完全相同,只不过标识这些指定的标记是 !MIC$。此外,!MIC$ DOALL 上的限定符子句集也不同。
表 B–4 Cray 风格的 DOALL 限定符子句的等效 OpenMP 子句| 
 Cray DOALL 子句  | 
 等效的 OpenMP PARALLEL DO 子句  | 
|---|---|
| 
 SHARED(v1,v2,...)  | 
 SHARED(v1,v2,...)  | 
| 
 PRIVATE(v1,v2,...)  | 
 PRIVATE(v1,v2,...)  | 
| 
 AUTOSCOPE  | 
 无等效子句。必须显式确定作用域,或者使用 DEFAULT 子句或 __AUTO 子句。  | 
| 
 SAVELAST  | 
 无完全等效指令。使用 lastprivate 可以获得相同效果。  | 
| 
 MAXCPUS(n)  | 
 num_threads(n)。无完全等效子句。  | 
| 
 GUIDED  | 
 schedule(guided, m) 缺省 m 为 1。  | 
| 
 SINGLE  | 
 schedule(dynamic,1)  | 
| 
 CHUNKSIZE(n)  | 
 schedule(dynamic,n)  | 
| 
 NUMCHUNKS(m)  | 
 schedule(dynamic,n/m) 其中 n 为迭代次数  | 
差别基本上与和 Sun 风格指令的差别相同,只不过没有与 Cray AUTOSCOPE 等效的指令。
C 编译器接受传统 pragma 来进行显式并行化。《C 用户指南》中有对这些内容的描述。与 Fortran 指令相同,这些只是建议值。
传统并行化 pragma 为:
表 B–5 将传统 C 并行化 Pragma 转换为 OpenMP| 
 传统 C Pragma  | 
 等效的 OpenMP Pragma  | 
|---|---|
| 
 #pragma MP taskloop [clauses]  | 
 #pragma omp parallel for [clauses]  | 
| 
 #pragma MP serial_loop  | 
 无完全等效指令。可以使用 #pragma omp master loop  | 
| 
 #pragma MP serial_loop_nested  | 
 无完全等效指令。可以使用 #pragma omp master loopnest  | 
taskloop pragma 可带有下列可选子句中的一个或多个子句。
表 B–6 taskloop 可选子句和等效的 OpenMP 子句| 
 taskloop 子句  | 
 等效的 OpenMP parallel for 子句  | 
|---|---|
| 
 maxcpus(n)  | 
 无完全等效指令。使用 num_threads(n)  | 
| 
 private(v1,v2,...)  | 
 private(v1,v2,...)  | 
| 
 shared(v1,v2,...)  | 
 shared(v1,v2,...)  | 
| 
 readonly(v1,v2,...)  | 
 无完全等效指令。使用 firstprivate(v1,v2,...) 可以获得相同效果。  | 
| 
 storeback(v1,v2,...)  | 
 使用 lastprivate(v1,v2,...) 可以获得相同效果。  | 
| 
 savelast  | 
 无完全等效指令。使用 lastprivate(v1,v2,...) 可以获得相同效果。  | 
| 
 reduction(v1,v2,...)  | 
 reduction(operator:v1,v2,...)。必须提供约简操作符和变量列表。  | 
| 
 schedtype(spec)  | 
 schedule(spec)(请参见表 B–7)  | 
schedtype(spec) 子句接受下列调度规范。
表 B–7 SCHEDTYPE 调度和等效的 OpenMP schedule 子句| 
 schedtype(spec)  | 
 等效的 OpenMP schedule(spec) 子句  | 
|---|---|
| 
 SCHEDTYPE(STATIC)  | 
 schedule(static)  | 
| 
 SCHEDTYPE(SELF(chunksize))  | 
 schedule(dynamic,chunksize) 注意: 缺省 chunksize 为 1。  | 
| 
 SCHEDTYPE(FACTORING(m))  | 
 无完全等效指令。  | 
| 
 SCHEDTYPE(GSS(m))  | 
 schedule(guided, m) 缺省 m 为 1。  | 
OpenMP 作用域变量在并行构造内声明为 private。#pragma omp parallel for 指令中的 default(none) 子句会使编译器标记未显式确定作用域的变量。
由于没有 serial_loop 指令,因此混合使用自动和显式 OpenMP 并行化的效果可能会不同: 某些使用传统 C 指令不能自动并行化的循环可能会被自动并行化。
由于 OpenMP 提供了更丰富的并行操作模型,因此使用传统 C 指令来重新设计程序的并行操作策略,以利用这些功能,往往可能会获得更高的性能。