コンパイラは、領域のコードを有効にして、コンパイラが生成した、別のエントリポイントにコードを置くことによって、並列領域をサポートします。これは、アウトライン化 (他のコンパイラに使用される手法、つまりサブルーチンの作成) とは異なりますが、同じデバッグ手法を適用できます。
コンパイラが生成する並列領域のエントリポイント名は、次の連続した文字列で構成されます。
"__" 文字
オリジナルのルーチンのエントリポイント名 (例: _parallel)
"_" 文字
並列領域の行番号
OpenMP* 並列領域の __par_region (!$OMP PARALLEL)
OpenMP 並列ループの __par_loop (MP PARALLEL DO)、
OpenMP 並列セクションの __par_section (!$OMP PARALLEL SECTIONS)
並列領域の連続番号 (各ソースファイルで、連続番号は 0 から始まります。)
ルーチン名 (例: padd) やエントリ名 (例 : _PADD, ___PADD_6__par_loop0) が使用されると、Fortran コンパイラは次のように動作します:
デフォルトでは、コンパイラは最初に小文字および大文字/小文字の混在したルーチン名を大文字に変換します。例えば、pAdD() は PADD() に変換され、これに "_" を付けることによりエントリ名になります。その後に、第 2 のエントリ名の変換が行われます。そのため、エントリ名の "__par_loop" 部分は小文字のままになります。これは、デバッガがブレークポイントを設定する際、大文字のルーチン名 "PADD" を認識せず、 代わりに、小文字の "padd" を認識していたためです。
例 1 では、並列領域によるコードのデバッグを示します。例 1 は次のコマンドで生成されます。
ifort -openmp -g -O0 -S file.f90
例 1 のサブルーチン parallel のコードを検証します。
サブルーチン PARALLEL() のソースリスト
1 subroutine parallel
2 integer id,OMP_GET_THREAD_NUM
3 !$OMP PARALLEL PRIVATE(id)
4 id = OMP_GET_THREAD_NUM()
5 !$OMP END PARALLEL
6 end
3 行目が並列領域です。コンパイラは 2 つのエントリポイント、parallel_ と ___parallel_3__par_region0 を作成しました。最初のエントリポイントはサブルーチン parallel() に対応し、2 番目のエントリポイントは、3 行目の OpenMP 並列領域に対応しています。
例 1: 並列領域によるコードのデバッグ
サブルーチン parallel() のマシン・コード・リスト
.globl parallel_
parallel_:
..B1.1: # Preds ..B1.0
..LN1:
pushl %ebp #1.0
movl %esp, %ebp #1.0
subl $44, %esp #1.0
pushl %edi #1.0
... ... ... ... ... ... ... ... ... ... ... ... ...
..B1.13: # Preds ..B1.9
addl $-12, %esp #6.0
movl $.2.1_2_kmpc_loc_struct_pack.2, (%esp) #6.0
movl $0, 4(%esp) #6.0
movl $_parallel__6__par_region1, 8(%esp) #6.0
call __kmpc_fork_call #6.0
# LOE
..B1.31: # Preds ..B1.13
addl $12, %esp #6.0
# LOE
..B1.14: # Preds ..B1.31 ..B1.30
..LN4:
leave #9.0
ret #9.0
# LOE
.type parallel_,@function
.size parallel_,.-parallel_
.globl _parallel__3__par_region0
_parallel__3__par_region0:
# parameter 1: 8 + %ebp
# parameter 2: 12 + %ebp
..B1.15: # Preds ..B1.0
pushl %ebp #9.0
movl %esp, %ebp #9.0
subl $44, %esp #9.0
..LN5:
call omp_get_thread_num_ #4.0
# LOE eax
..B1.32: # Preds ..B1.15
movl %eax, -32(%ebp) #4.0
# LOE
..B1.16: # Preds ..B1.32
movl -32(%ebp), %eax #4.0
movl %eax, -20(%ebp) #4.0
..LN6:
leave #9.0
ret #9.0
# LOE
.type _parallel__3__par_region0,@function
.size _parallel__3__par_region0,._parallel__3__par_region0
.globl _parallel__6__par_region1
_parallel__6__par_region1:
# parameter 1: 8 + %ebp
# parameter 2: 12 + %ebp
..B1.17: # Preds ..B1.0
pushl %ebp #9.0
movl %esp, %ebp #9.0
subl $44, %esp #9.0
..LN7:
call omp_get_thread_num_ #7.0
# LOE eax
..B1.33: # Preds ..B1.17
movl %eax, -28(%ebp) #7.0
# LOE
..B1.18: # Preds ..B1.33
movl -28(%ebp), %eax #7.0
movl %eax, -16(%ebp) #7.0
..LN8:
leave #9.0
ret #9.0
.align 4,0x90
# mark_end;
このレベルでプログラムをデバッグすることは、POSIX スレッド を直接使用するプログラムをデバッグするようなものです。他のルーチンと同じように、スレッドコード内で、ブレークポイントを設定できます。GNU デバッガの場合、ソースレベル・ルーチン名 (parallel など) にブレークポイントを設定できます。また、エントリポイント名 (parallel_、 _parallel__3__par_region0 など) にも設定できます。Linux* 版インテル® Fortran コンパイラが、大文字の Fortran サブルーチン名を小文字に変換したことに注意してください。